Created
February 12, 2019 14:29
-
-
Save PlugFox/49820e26c842889a26264f53ff64e6c8 to your computer and use it in GitHub Desktop.
NativeXLSX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Область NativeXLSX | |
// Метод "NativeXLSX" (ЧтениеXML). | |
// Преобразует текст формата XML (файл типа XLSX) в таблицу значений, | |
// при этом колонки таблицы формируются на основе описания в XML. | |
// | |
// Параметры: | |
// ФайлEXCEL - Полное имя файла (путь к файлу с именем файла и расширением) | |
// ИмяНомерЛиста - Структура Имя и Номер выбранного листа файла EXCEL. | |
// СтрокаЗаголовка (по умолчанию = 1) - Номер строки EXCEL, в которой расположены заголовки колонок. | |
// Не используется. | |
// В обработке 1-я строка анализируется для сопоставления колонок EXCEL с реквизитами 1С (справочники, докуметны, регистры). | |
// НачСтрока (по-умолчанию = 0) - Номер начальной строки, начиная с которой считываются данные из EXCEL. | |
// КонСтрока (по-умолчанию = 0) - Номер конечной строки, которой заканчиваются считываемые данные из EXCEL. | |
// Если НачСтрока=0 и КонСтрока=0, то считывается вся таблица, находящаяся на листе EXCEL. | |
// КолвоСтрокExcel - Количество строк на листе "ИмяЛиста" EXCEL. Возвращается в вызываемую процедуру. | |
// | |
// Возвращаемые значения: | |
// ТаблицаРезультат - Результат считывания с листа "ИмяНомерЛиста" EXCEL. | |
// | |
&НаСервере | |
Функция ЗагрузитьМетодом_NativeXLSX(Знач ФайлEXCEL, Знач ИмяНомерЛиста, Знач СтрокаЗаголовка = 1, Знач НачСтрока = 0, Знач КонСтрока = 0, КолвоСтрокExcel = 0) | |
Перем ZIPКаталог, ФайлИмяЛиста, ФайлНомерЛиста, КолвоКолонокEXCEL, НомерСтроки, НомерКолонки, ИмяКолонки, ИндексКолонки, ШиринаКолонки, ДлинаСтроки; | |
Перем МассивИменКолонокXLSX, МассивSharedStrings, МассивNumFmtId, СоответствиеNumFmtIdFormatCode; | |
Перем SheetX,ЗначениеЯчейки, ТипЗначения, ФорматЯчейки, ФорматСтиля; | |
Перем ТаблицаРезультат, НоваяСтрока; | |
ФайлНомерЛиста = ИмяНомерЛиста.НомерЛиста; | |
ФайлНомерЛиста = ?(ФайлНомерЛиста = 0, 1, ФайлНомерЛиста); | |
ZIPКаталог = КаталогВременныхФайлов() + "XLSX\"; | |
Если НЕ ПредварительнаяОбработкаФайлаXLSX(ФайлEXCEL, ZIPКаталог) Тогда | |
Возврат Новый ТаблицаЗначений; | |
КонецЕсли; | |
СоответствиеNumFmtIdFormatCode = Новый Соответствие; | |
МассивNumFmtId = ИзвлечьДанныеИзФайла_StylesXML(ZIPКаталог, СоответствиеNumFmtIdFormatCode); | |
МассивSharedStrings = ИзвлечьДанныеИзФайла_SharedStringsXML(ZIPКаталог); | |
SheetX = Новый ЧтениеXML; | |
SheetX.ОткрытьФайл(ZIPКаталог + "XL\WorkSheets\Sheet" + ФайлНомерЛиста + ".xml"); | |
МассивИменКолонокXLSX = ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX); | |
КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество(); | |
// Создание результирующей таблицы, в которую будут записываться считанные из EXCEL данные. | |
ТаблицаРезультат = Новый ТаблицаЗначений; | |
// Формирование колонок результирующей таблицы. | |
// "НомерСтроки" - для наглядности и удобства. | |
// В зависимости от разрабатываемой обработки. | |
// "Сопоставлено" - может быть другим. | |
// Здесь же могут быть добавлены другие колонки, не формируемые из содержимого файла EXCEL. | |
ТаблицаРезультат.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"), "№", 4); | |
ТаблицаРезультат.Колонки.Добавить("Сопоставлено", Новый ОписаниеТипов("Булево"), "Сопоставлено", 1); | |
ТаблицаРезультат.Колонки.Добавить("УровеньГруппировки", Новый ОписаниеТипов("Число"), "Гр", 2); // Группировка строк в файле EXCEL. | |
Для ит = 1 ПО КолвоКолонокExcel Цикл | |
ИмяКолонки = "N" + ит; | |
Колонка = ТаблицаРезультат.Колонки.Добавить(ИмяКолонки); | |
КонецЦикла; | |
SheetX = Новый ЧтениеXML; | |
SheetX.ОткрытьФайл(ZIPКаталог + "XL\WorkSheets\Sheet" + ФайлНомерЛиста + ".xml"); | |
ЭтоНачалоДанных = Ложь; | |
// Считать очередной узел XML. | |
Пока SheetX.Прочитать() Цикл | |
Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
ЭтоНачалоДанных = Истина; | |
Прервать; | |
КонецЕсли; | |
КонецЦикла; | |
Если НЕ ЭтоНачалоДанных Тогда | |
Возврат Новый ТаблицаЗначений; | |
КонецЕсли; | |
// Считать очередной узел XML. | |
НомерСтроки = 0; | |
Пока SheetX.Прочитать() Цикл | |
Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда | |
Прервать; // Окончание данных. | |
КонецЕсли; | |
Если ВРег(SheetX.Имя) = "ROW" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
НомерСтроки = НомерСтроки + 1; | |
Если НЕ НачСтрока = 0 И НЕ НомерСтроки = 1 И НомерСтроки < НачСтрока Тогда | |
Продолжить; | |
КонецЕсли; | |
НоваяСтрока = ТаблицаРезультат.Добавить(); | |
НоваяСтрока.НомерСтроки = НомерСтроки; | |
НоваяСтрока.УровеньГруппировки = SheetX.ЗначениеАтрибута("outlineLevel"); | |
Пока SheetX.Прочитать() Цикл // Считаем колонки строки EXCEL. | |
Если ВРег(SheetX.Имя) = "ROW" Тогда | |
Прервать; | |
КонецЕсли; | |
Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда | |
Прервать; // Окончание данных. | |
КонецЕсли; | |
Если ВРег(SheetX.Имя) = "C" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
ТипЗначения = SheetX.ЗначениеАтрибута("t"); | |
ФорматЯчейки = SheetX.ЗначениеАтрибута("s"); | |
ИмяКолонки = SheetX.ЗначениеАтрибута("r"); | |
ИмяКолонкиБезЦифр = ЗаменитьОдниСимволыДругими("0123456789", ИмяКолонки, ""); | |
ИндексКолонки = МассивИменКолонокXLSX.Найти(ИмяКолонкиБезЦифр)+1; | |
SheetX.Прочитать(); | |
Если ВРег(SheetX.Имя) = "V" ИЛИ ВРег(SheetX.Имя) = "F" Тогда // "V" - Значение, "F" - Формула. | |
Если ВРег(SheetX.Имя) = "F" Тогда | |
Пока НЕ ВРег(SheetX.Имя) = "V" Цикл | |
SheetX.Прочитать(); | |
КонецЦикла; | |
КонецЕсли; | |
SheetX.Прочитать(); | |
Если ВРег(SheetX.Имя) = "#TEXT" Тогда | |
ЗначениеЯчейки = SheetX.Значение; | |
ФорматСтиля = ""; | |
Если (НЕ ФорматЯчейки = "" И НЕ ФорматЯчейки = Неопределено) Тогда | |
Попытка | |
ИндексФормата = Число(ФорматЯчейки); | |
ФорматСтиля = СоответствиеNumFmtIdFormatCode.Получить(МассивNumFmtId[ИндексФормата]); | |
Исключение | |
ФорматСтиля = ""; | |
КонецПопытки; | |
КонецЕсли; | |
Если ЗначениеЗаполнено(ЗначениеЯчейки) Тогда | |
Если ТипЗначения = Неопределено ИЛИ ВРег(ТипЗначения) = "N" ИЛИ ВРег(ТипЗначения) = "B" Тогда | |
Попытка | |
Значение1 = Число(ЗначениеЯчейки); | |
Исключение | |
Значение1 = ЗначениеЯчейки; | |
КонецПопытки; | |
ЗначениеЯчейки = Значение1; | |
Если (ФорматСтиля = "" ИЛИ ФорматСтиля = Неопределено) Тогда | |
// ФорматСтиля = Неопределено - Атрибут "s" отсутствует. | |
// MS Office (2010) может не формировать в xml-файле описание стиля форматирования для ячейки. | |
// LibreOffice (4.1.5) формирует в xml-файле необходимые описания стиля форматирования ячейки. | |
// Сообщить("Не определен стиль форматирования для кода " + ФорматЯчейки + " значения " + ЗначениеЯчейки); | |
КонецЕсли; | |
Если ТипЗнч(ЗначениеЯчейки) = Тип("Строка") | |
И (Найти(ЗначениеЯчейки, "E-") > 0 ИЛИ Найти(ЗначениеЯчейки, "E+") > 0) Тогда | |
ЗначениеЯчейки = ПолучитьЧислоВСтепениИзСтроковогоЗначения(ЗначениеЯчейки); | |
КонецЕсли; | |
Если ТипЗнч(ЗначениеЯчейки) = Тип("Число") Тогда | |
// ПРОЦЕНТ. | |
Если ЭтоПроцентXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда | |
ЗначениеЯчейки = Окр(ЗначениеЯчейки * 100, 3); | |
// БУЛЕВО. | |
ИначеЕсли ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда | |
ЗначениеЯчейки = Булево(ЗначениеЯчейки); | |
// ВРЕМЯ. | |
ИначеЕсли ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда | |
ЗначениеЯчейки = КонвертироватьЧислоXLSXвДатуВремя(ЗначениеЯчейки); | |
// ДАТА. | |
ИначеЕсли ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда | |
ЗначениеЯчейки = КонвертироватьЧислоXLSXвДату(ЗначениеЯчейки); | |
// ЧИСЛО. | |
ИначеЕсли ТипЗначения = Неопределено | |
ИЛИ ( ЭтоЧислоXLSX(ЗначениеЯчейки, ФорматСтиля) | |
И НЕ ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) | |
И НЕ ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля) | |
И НЕ ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) ) | |
Тогда | |
// Без преобразования. | |
Иначе | |
// Прочие форматы. | |
КонецЕсли; | |
Иначе | |
Сообщить("Не удалось преобразовать значение к ""числовому""(процент, время, дата, число) типу."); | |
КонецЕсли; | |
ИначеЕсли ВРег(ТипЗначения) = "S" Тогда | |
// МассивSharedStrings может быть пустым. | |
Попытка | |
ЗначениеЯчейки = СокрЛП(МассивSharedStrings[Число(SheetX.Значение)]); | |
Исключение | |
ЗначениеЯчейки = ""; | |
КонецПопытки; | |
ИначеЕсли ВРег(ТипЗначения) = "STR" Тогда | |
Если ТипЗнч(ЗначениеЯчейки) = Тип("Строка") Тогда | |
ЗначениеЯчейки = СокрЛП(ЗначениеЯчейки); | |
КонецЕсли; | |
КонецЕсли; | |
КонецЕсли; | |
ИмяКолонки = "N"+ИндексКолонки; | |
НоваяСтрока[ИмяКолонки] = ЗначениеЯчейки; | |
// Используется при формировании таблицы на форме обработки. | |
ШиринаКолонки = ТаблицаРезультат.Колонки[ИмяКолонки].Ширина; | |
ДлинаСтроки = СтрДлина(СокрЛП(ЗначениеЯчейки)); | |
ТаблицаРезультат.Колонки[ИмяКолонки].Ширина = ?(ШиринаКолонки < ДлинаСтроки, ДлинаСтроки, ШиринаКолонки); | |
КонецЕсли; | |
КонецЕсли; | |
КонецЕсли; | |
КонецЦикла; | |
Если ((НЕ КонСтрока = 0 И (НомерСтроки + 1) > КонСтрока) | |
ИЛИ (НЕ КолвоСтрокExcel = 0 И (НомерСтроки + 1) > КолвоСтрокExcel)) Тогда | |
Прервать; // Окончание диапазона считываемых данных. | |
КонецЕсли; | |
КонецЕсли; | |
КонецЦикла; | |
// Завершение работы. | |
// Закрытие Объектов. | |
SheetX.Закрыть(); | |
УдалитьКолонкиСНулевойШириной(ТаблицаРезультат); | |
Возврат ТаблицаРезультат; | |
КонецФункции | |
&НаСервере | |
Функция ПредварительнаяОбработкаФайлаXLSX(ФайлEXCEL, ZIPКаталог) | |
Перем Файл; | |
Файл = ПолучитьОбъектФайл(ФайлEXCEL); | |
Если Файл = Неопределено Тогда | |
Сообщить("Невозможно загрузить данные, т.к. невозможно открыть для чтения файл: | |
|" + ФайлEXCEL); | |
Возврат Ложь; | |
КонецЕсли; | |
Если НЕ ВРег(Файл.Расширение) = ".XLSX" Тогда | |
Сообщить("Файл с расширением " + Файл.Расширение +" не поддерживается методом NativeXLSX: | |
|" + ФайлEXCEL); | |
Возврат Ложь; | |
КонецЕсли; | |
Если НЕ РаспаковатьXLSXвКаталогВременныхФайлов(ФайлEXCEL, ZIPКаталог) Тогда | |
Сообщить("Ошибка распаковки файла. | |
|Возможно каталог временных файлов занят. | |
|" + ФайлEXCEL); | |
Возврат Ложь; | |
КонецЕсли; | |
Возврат Истина; | |
КонецФункции | |
&НаСервере | |
Функция ПолучитьОбъектФайл(Знач ФайлEXCEL) | |
Перем Файл; | |
Если НЕ ЗначениеЗаполнено(ФайлEXCEL) Тогда | |
Возврат Неопределено; | |
КонецЕсли; | |
Файл = Новый Файл(ФайлEXCEL); | |
Если НЕ ФайлСуществуетИДоступен(Файл.ПолноеИмя) Тогда | |
Сообщить("Файл не существует/не доступен: | |
|" + ФайлEXCEL); | |
Возврат Неопределено; | |
КонецЕсли; | |
Возврат Файл; | |
КонецФункции | |
&НаСервере | |
Функция ФайлСуществуетИДоступен(ПолноеИмяФайла) | |
Перем Файл; | |
Файл = Новый Файл(ПолноеИмяФайла); | |
Если НЕ Файл.Существует() Тогда | |
Возврат Ложь; | |
КонецЕсли; | |
// Проверка: Занят ли файл другим процессом? | |
Если НЕ ВРег(Файл.Расширение) = ".DBF" Тогда | |
Попытка | |
ПереместитьФайл(Файл.ПолноеИмя,Файл.ПолноеИмя); | |
Исключение | |
Сообщить("Файл не доступен: | |
|" + Файл.ПолноеИмя); | |
Возврат Ложь; | |
КонецПопытки; | |
КонецЕсли; | |
Возврат Истина; | |
КонецФункции | |
&НаСервере | |
Функция РаспаковатьXLSXвКаталогВременныхФайлов(ФайлEXCEL, ZIPКаталог) | |
Перем ZIPФайл; | |
Попытка | |
УдалитьФайлы(ZIPКаталог); | |
ZIPФайл = Новый ЧтениеZipФайла; | |
ZIPФайл.Открыть(ФайлEXCEL); | |
ZIPФайл.ИзвлечьВсе(ZIPКаталог, РежимВосстановленияПутейФайловZIP.Восстанавливать); | |
Возврат Истина; | |
Исключение | |
Возврат Ложь; | |
КонецПопытки; | |
Возврат Истина; | |
КонецФункции | |
&НаСервере | |
Функция ИзвлечьДанныеИзФайла_StylesXML(ZIPКаталог, СоответствиеNumFmtIdFormatCode) | |
Перем Файл, Styles; | |
Перем МассивNumFmtId, ит; | |
МассивNumFmtId = Новый Массив; | |
СоответствиеNumFmtIdFormatCode = Новый Соответствие; | |
Файл = Новый Файл(ZIPКаталог + "XL\Styles.xml"); | |
Если НЕ Файл.Существует() Тогда | |
Возврат МассивNumFmtId; | |
КонецЕсли; | |
Styles = Новый ЧтениеXML; | |
Styles.ОткрытьФайл(Файл.ПолноеИмя); | |
Пока Styles.Прочитать() Цикл | |
Если ВРег(Styles.Имя) = ВРег("numFmt") И Styles.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
СоответствиеNumFmtIdFormatCode.Вставить(Styles.ЗначениеАтрибута("numFmtId"), ВРег(Styles.ЗначениеАтрибута("formatCode"))); | |
КонецЕсли; | |
Если ВРег(Styles.Имя) = ВРег("cellXfs") Тогда | |
Пока Styles.Прочитать() Цикл | |
Если ВРег(Styles.Имя) = ВРег("xf") И Styles.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
МассивNumFmtId.Добавить(Styles.ЗначениеАтрибута("numFmtId")); | |
КонецЕсли; | |
КонецЦикла; | |
КонецЕсли; | |
КонецЦикла; | |
// Завершение работы. | |
// Закрытие Объектов. | |
Styles.Закрыть(); | |
// Проверка сопоставления кодов массива и соответствия. | |
// MS Office может не формировать в xml-файле описание стиля форматирования для ячейки. | |
// LibreOffice формирует в xml-файле необходимые описания стиля форматирования ячейки. | |
Для Каждого ит ИЗ МассивNumFmtId Цикл | |
Если СоответствиеNumFmtIdFormatCode.Получить(ит) = Неопределено Тогда | |
Если ит = "0" Тогда // Стандарт для числа (Целое число). | |
СоответствиеNumFmtIdFormatCode.Вставить(ит, "GENERAL"); | |
ИначеЕсли ит = "9" ИЛИ ит = "10" Тогда // Форматы для % ("0%", "0.00%"). | |
СоответствиеNumFmtIdFormatCode.Вставить(ит, "0%"); | |
ИначеЕсли ит = "14" ИЛИ ит = "16" Тогда // Форматы для даты. | |
СоответствиеNumFmtIdFormatCode.Вставить(ит, "DD.MM.YYYY"); | |
ИначеЕсли ит = "45" ИЛИ ит = "46" ИЛИ ит = "47" Тогда // Форматы для времени. | |
СоответствиеNumFmtIdFormatCode.Вставить(ит, "HH:MM:SS"); | |
КонецЕсли; | |
КонецЕсли; | |
КонецЦикла; | |
Возврат МассивNumFmtId; | |
КонецФункции | |
&НаСервере | |
Функция ИзвлечьДанныеИзФайла_SharedStringsXML(ZIPКаталог) | |
Перем Файл, SharedStrings; | |
Перем МассивSharedStrings; | |
// Если в файле EXCEL не содержится значений, имеющих тип "СТРОКА", то файл "SharedStrings.xml" не формируется. | |
МассивSharedStrings = Новый Массив; | |
Файл = Новый Файл(ZIPКаталог + "XL\SharedStrings.xml"); | |
Если НЕ Файл.Существует() Тогда | |
Возврат МассивSharedStrings; | |
КонецЕсли; | |
SharedStrings = Новый ЧтениеXML; | |
SharedStrings.ОткрытьФайл(Файл.ПолноеИмя); | |
Пока SharedStrings.Прочитать() Цикл | |
Если ВРег(SharedStrings.Имя) = "#TEXT" Тогда | |
МассивSharedStrings.Добавить(SharedStrings.Значение); | |
КонецЕсли; | |
КонецЦикла; | |
// Завершение работы. | |
// Закрытие Объектов. | |
SharedStrings.Закрыть(); | |
Возврат МассивSharedStrings; | |
КонецФункции | |
&НаСервере | |
Функция ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX) | |
Перем ДиапазонДанных, ДиапазонКолонок, ПерваяКолонка, ПоследняяКолонка, НомерПервойК, НомерПоследнейК; | |
Перем Подсчет, ИмяКолонки; | |
Перем МассивИменКолонокXLSX, КолвоКолонокEXCEL; | |
МассивИменКолонокXLSX = Новый Массив; | |
Подсчет = Ложь; | |
// Считать очередной узел XML. | |
Пока SheetX.Прочитать() Цикл | |
// DIMENSION. | |
Если ВРег(SheetX.Имя) = "DIMENSION" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
ДиапазонДанных = SheetX.ПолучитьАтрибут("ref"); | |
ДиапазонКолонок = ЗаменитьОдниСимволыДругими("0123456789", ДиапазонДанных, ""); | |
ПерваяКолонка = Лев(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") - 1); | |
ПоследняяКолонка= Сред(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") + 1); | |
НомерПервойК = НомерКолонкиДесятичный(ПерваяКолонка); | |
НомерПоследнейК = НомерКолонкиДесятичный(ПоследняяКолонка); | |
КонецЕсли; | |
// Подсчет по 1-ой строке. | |
Если ВРег(SheetX.Имя) = "ROW" Тогда | |
Если SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
// Начало отсчета. | |
Подсчет = Истина; | |
ИначеЕсли SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда | |
// Окончание отсчета. | |
Прервать; | |
КонецЕсли; | |
КонецЕсли; | |
Если Подсчет И ВРег(SheetX.Имя) = "C" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда | |
ИмяКолонки = SheetX.ПолучитьАтрибут("r"); | |
ИмяКолонки = ЗаменитьОдниСимволыДругими("0123456789", ИмяКолонки, ""); | |
МассивИменКолонокXLSX.Добавить(ИмяКолонки); | |
КонецЕсли; | |
КонецЦикла; | |
КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество(); | |
Если НЕ НомерПоследнейК = Неопределено Тогда | |
Если КолвоКолонокEXCEL < НомерПоследнейК Тогда | |
Сообщить("Строка заголовков колонок (1-я строка) заполнена не полностью: | |
|К-во колонок строки меньше объявленной: " + КолвоКолонокEXCEL + "<" + НомерПоследнейК); | |
ДополнитьМассивИменКолонокXLSX(НомерПоследнейК, МассивИменКолонокXLSX); | |
ИначеЕсли КолвоКолонокEXCEL > НомерПоследнейК Тогда | |
Сообщить("Строка заголовков колонок (1-я строка) содержит больше колонок, чем объявлено: | |
|К-во колонок строки больше объявленной:" + КолвоКолонокEXCEL + ">" + НомерПоследнейК); | |
КонецЕсли; | |
КонецЕсли; | |
Возврат МассивИменКолонокXLSX; | |
КонецФункции | |
&НаСервере | |
Функция НомерКолонкиДесятичный(ИмяКолонкиXLSX) | |
Перем Латиница, ДлинаНомера, Поз, ит; | |
Перем НомерКолонки; | |
Латиница = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 26. | |
ДлинаНомера = СтрДлина(ИмяКолонкиXLSX); | |
НомерКолонки = 0; | |
Для ит = 1 ПО ДлинаНомера Цикл | |
Поз = Найти(Латиница, Сред(ИмяКолонкиXLSX, (ДлинаНомера + 1 - ит), 1)); | |
НомерКолонки = НомерКолонки + Поз * Pow(26, ит - 1); | |
КонецЦикла; | |
Возврат НомерКолонки; | |
КонецФункции | |
&НаСервере | |
Процедура ДополнитьМассивИменКолонокXLSX(Знач КолвоКолонокExcel, МассивИменКолонокXLSX, Индекс = - 1) | |
Перем Алфавит, ит, Буква; | |
Алфавит = РазложитьСтрокуВМассивПодстрок("A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z", ","); | |
Если МассивИменКолонокXLSX.Количество() >= КолвоКолонокExcel Тогда | |
Возврат; | |
КонецЕсли; | |
Если Индекс > Алфавит.Количество() - 1 Тогда | |
Возврат; | |
КонецЕсли; | |
Буква = ?(Индекс = -1, "", Алфавит[Индекс]); | |
Для ит = 0 ПО Алфавит.Количество() - 1 Цикл | |
Если МассивИменКолонокXLSX.Найти(Буква + Алфавит[ит]) = Неопределено Тогда | |
МассивИменКолонокXLSX.Добавить(Буква + Алфавит[ит]); | |
КонецЕсли; | |
Если МассивИменКолонокXLSX.Количество() >= КолвоКолонокExcel Тогда | |
Возврат; | |
КонецЕсли; | |
КонецЦикла; | |
Если МассивИменКолонокXLSX.Количество() > КолвоКолонокExcel Тогда | |
Возврат; | |
Иначе | |
Индекс = Индекс + 1; | |
ДополнитьМассивИменКолонокXLSX(КолвоКолонокExcel, МассивИменКолонокXLSX, Индекс); | |
КонецЕсли; | |
Возврат; | |
КонецПроцедуры | |
// Функция "расщепляет" строку на подстроки, используя заданный | |
// разделитель. Разделитель может иметь любую длину. | |
// Если в качестве разделителя задан пробел, рядом стоящие пробелы | |
// считаются одним разделителем, а ведущие и хвостовые пробелы параметра Стр | |
// игнорируются. | |
// Например, | |
// РазложитьСтрокуВМассивПодстрок(",один,,,два", ",") возвратит массив значений из пяти элементов, | |
// три из которых - пустые строки, а | |
// РазложитьСтрокуВМассивПодстрок(" один два", " ") возвратит массив значений из двух элементов | |
// | |
// Параметры: | |
// Стр - строка, которую необходимо разложить на подстроки. | |
// Параметр передается по значению. | |
// Разделитель - строка-разделитель, по умолчанию - запятая. | |
// | |
// Возвращаемое значение: | |
// массив значений, элементы которого - подстроки | |
// | |
&НаСервере | |
Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") | |
МассивСтрок = Новый Массив(); | |
Если Разделитель = " " Тогда | |
Стр = СокрЛП(Стр); | |
Пока 1 = 1 Цикл | |
Поз = Найти(Стр, Разделитель); | |
Если Поз = 0 Тогда | |
МассивСтрок.Добавить(СокрЛП(Стр)); | |
Возврат МассивСтрок; | |
КонецЕсли; | |
МассивСтрок.Добавить(СокрЛП(Лев(Стр, Поз - 1))); | |
Стр = СокрЛ(Сред(Стр, Поз)); | |
КонецЦикла; | |
Иначе | |
ДлинаРазделителя = СтрДлина(Разделитель); | |
Пока 1 = 1 Цикл | |
Поз = Найти(Стр, Разделитель); | |
Если Поз = 0 Тогда | |
Если (СокрЛП(Стр) <> "") Тогда | |
МассивСтрок.Добавить(СокрЛП(Стр)); | |
КонецЕсли; | |
Возврат МассивСтрок; | |
КонецЕсли; | |
МассивСтрок.Добавить(СокрЛП(Лев(Стр,Поз - 1))); | |
Стр = Сред(Стр, Поз + ДлинаРазделителя); | |
КонецЦикла; | |
КонецЕсли; | |
КонецФункции | |
&НаСервере | |
Функция ЭтоЧислоXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) | |
Если ( ВРег(ФорматСтиля) = "GENERAL" | |
ИЛИ ВРег(ФорматСтиля) = "STANDARD" | |
ИЛИ Найти(ФорматСтиля, "0") > 0 ) | |
Тогда | |
Возврат Истина; | |
КонецЕсли; | |
Возврат Ложь; | |
КонецФункции | |
&НаСервере | |
Функция ЭтоПроцентXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) | |
Если ( Найти(ФорматСтиля, "%") > 0 ) | |
Тогда | |
Возврат Истина; | |
КонецЕсли; | |
Возврат Ложь; | |
КонецФункции | |
&НаСервере | |
Функция ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) | |
Если (ЗначениеЯчейки = 0 ИЛИ ЗначениеЯчейки = 1) | |
И Найти(ВРег(ФорматСтиля), "ИСТИНА") > 0 ИЛИ Найти(ВРег(ФорматСтиля), "ЛОЖЬ") > 0 | |
ИЛИ Найти(ВРег(ФорматСтиля), "TRUE") > 0 ИЛИ Найти(ВРег(ФорматСтиля), "FALSE") > 0 | |
Тогда | |
Возврат Истина; | |
КонецЕсли; | |
Возврат Ложь; | |
КонецФункции | |
&НаСервере | |
Функция ЭтоДатаXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) | |
Если ЗначениеЯчейки = Цел(ЗначениеЯчейки) И | |
( Найти(ФорматСтиля, "DD") > 0 | |
ИЛИ Найти(ФорматСтиля, "MM") > 0 | |
ИЛИ Найти(ФорматСтиля, "YY") > 0 | |
ИЛИ Найти(ФорматСтиля, "QQ") > 0 | |
ИЛИ Найти(ФорматСтиля, "WW") > 0 ) | |
Тогда | |
Возврат Истина; | |
КонецЕсли; | |
Возврат Ложь; | |
КонецФункции | |
&НаСервере | |
Функция ЭтоВремяXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) | |
Если ЗначениеЯчейки < 1 И | |
( Найти(ФорматСтиля, "HH:") > 0 | |
ИЛИ Найти(ФорматСтиля, "[HH]:") > 0 | |
ИЛИ Найти(ФорматСтиля, "[H]:") > 0 | |
ИЛИ Найти(ФорматСтиля, "MM:") > 0 | |
ИЛИ Найти(ФорматСтиля, ":SS") > 0 ) | |
Тогда | |
Возврат Истина; | |
КонецЕсли; | |
Возврат Ложь; | |
КонецФункции | |
&НаСервере | |
Функция КонвертироватьЧислоXLSXвДату(Знач Число) | |
Перем Дата1900, Разница, ДатаРезультат; | |
Дата1900 = Дата("19000101"); | |
Разница = Число - 2; // EXCEL ошибочно считает 1900-й год високосным. | |
Разница = ?(Разница < 0, 0, Разница); | |
ДатаРезультат = Дата1900 + Разница * 24 * 60 * 60; | |
Возврат ДатаРезультат; | |
КонецФункции | |
&НаСервере | |
Функция КонвертироватьЧислоXLSXвДатуВремя(Знач Число) | |
Перем КВоСекунд; | |
Перем ВремяРезультат; | |
// 0,0000115740740740741 = 1 сек. | |
// 1 = 24 часа 00 мин 00 сек. | |
Если ТипЗнч(Число) = Тип("Число") Тогда | |
КВоСекунд = Число * 100000 / 1.15740740740741; | |
КВоСекунд = Окр(КВоСекунд); | |
Иначе | |
Сообщить("Ошибка определения значения типа ""Время""."); | |
КонецЕсли; | |
ВремяРезультат = Дата("19000101000000") + КВоСекунд; | |
Возврат ВремяРезультат; | |
КонецФункции | |
&НаСервере | |
Функция ПолучитьЧислоВСтепениИзСтроковогоЗначения(Знач ЗначениеЯчейки) | |
Перем Поз1Е, Степень; | |
Перем Значение; | |
Если Найти(ЗначениеЯчейки, "E-") > 0 Тогда | |
Поз1Е = Найти(ЗначениеЯчейки, "E-"); | |
Степень = Сред(ЗначениеЯчейки, Поз1Е+2); | |
Значение = Лев(ЗначениеЯчейки, Поз1Е-1); | |
Попытка | |
Степень = Число(Степень); | |
Значение = Число(Значение) / Pow(10, Степень); | |
Исключение | |
Значение = ЗначениеЯчейки; | |
КонецПопытки; | |
ИначеЕсли Найти(ЗначениеЯчейки, "E+") > 0 Тогда | |
Поз1Е = Найти(ЗначениеЯчейки, "E+"); | |
Степень = Сред(ЗначениеЯчейки, Поз1Е+2); | |
Значение = Лев(ЗначениеЯчейки, Поз1Е-1); | |
Попытка | |
Степень = Число(Степень); | |
Значение = Число(Значение) * Pow(10, Степень); | |
Исключение | |
Значение = ЗначениеЯчейки; | |
КонецПопытки; | |
Иначе | |
Значение = ЗначениеЯчейки; | |
КонецЕсли; | |
Возврат Значение; | |
КонецФункции | |
&НаСервере | |
Функция ЗаменитьОдниСимволыДругими(ЗаменяемыеСимволы, Строка, СимволыЗамены) | |
Результат = Строка; | |
Для НомерСимвола = 1 По СтрДлина(ЗаменяемыеСимволы) Цикл | |
Результат = СтрЗаменить(Результат, Сред(ЗаменяемыеСимволы, НомерСимвола, 1), Сред(СимволыЗамены, НомерСимвола, 1)); | |
КонецЦикла; | |
Возврат Результат; | |
КонецФункции | |
&НаСервере | |
Процедура УдалитьКолонкиСНулевойШириной(ТаблицаРезультат) | |
Перем МассивПустыхКолонок; | |
// Найдем пустые колонки. | |
МассивПустыхКолонок = Новый Массив; | |
Для Каждого Колонка ИЗ ТаблицаРезультат.Колонки Цикл | |
Если Колонка.Ширина = 0 Тогда | |
МассивПустыхКолонок.Добавить(Колонка.Имя); | |
КонецЕсли; | |
КонецЦикла; | |
// Удалим пустые колонки. | |
Для Каждого ПустаяКолонка ИЗ МассивПустыхКолонок Цикл | |
ТаблицаРезультат.Колонки.Удалить(ПустаяКолонка); | |
КонецЦикла; | |
КонецПроцедуры | |
#КонецОбласти |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment