Загрузка из EXCEL в 1С. Чтение файла XLSX средствами 1С. ЧтениеXML
ПРАКТИЧЕСКОЕ ПОСОБИЕ РАЗРАБОТЧИКА: Метод "NativeXLSX" (ЧтениеXML).
Обрабатываются данные EXCEL типов: "Строка", "Число", "Дата" ("Время"), "Булево", "Процент".
- Описание
- Подробнее
Описание
В данной статье приведен функционал, с помощью которого в обработке
«Импорт из EXCEL и др.источников (xls,xlsx,ods,sxc,dbf,mxl,csv,sql) в 1С«: //sale.itcity.ru/public/120961/
производится считывание данных из файлов табличного типа *.xlsx средствами 1С (метод «NativeXLSX»).
19.09.2014. Уточненная редакция.
Метод позволяет обрабатывать данные EXCEL типов: «Строка», «Число», «Дата» («Время»), «Булево», «Процент».
Методы загрузки из внешнего источника:
— Метод «MS ADO» (Чтение файлов xls, xlsx средствами Microsoft ADO): //sale.itcity.ru/public/163640/
— Метод «MS EXCEL» (Чтение файлов xls, xlsx с картинками средствами Microsoft Office): //sale.itcity.ru/public/163641/
— Метод «LO CALC» (Чтение файлов xls, xlsx, ods, sxc с картинками средствами LibreOffice): //sale.itcity.ru/public/163642/
— Метод «NativeXLSX» (Чтение файлов xlsx с картинками средствами 1С. ПостроительDOM): //sale.itcity.ru/public/300092/
— Метод «NativeXLSX». Предыдущий вариант (Чтение файлов xlsx средствами 1С. ЧтениеXML)://sale.itcity.ru/public/225624/
— Метод «Excel1C» (Загрузка на платформе 8.3.6 с картинками. Чтение файлов xls, xlsx, ods): //sale.itcity.ru/public/341855/
— Список листов файла: //sale.itcity.ru/public/163724/
Публикаций на тему загрузки из EXCEL — множество, но
«
— Вам билетёр нужен?
— Был нужен, да уже взяли.
— Может и я на что сгожусь?
— Может и сгодишься, если скалиться не будешь …
«
«НЕУЛОВИМЫЕ МСТИТЕЛИ» (1966).
Публикации других авторов:
«XLSX средствами 1С»:
1cmax: Чтение файлов *.xlsx средствами 1С 8.2 (Управляемые формы) в т.ч. Веб-клиент: //sale.itcity.ru/public/142187
Abadonna: Чтение файлов *.xlsx средствами 1С 8.2: //sale.itcity.ru/public/139556
Dzenn: Загрузка файлов Excel XLSX через XML: //sale.itcity.ru/public/205359
webstep: Чтение документа Excel 2007 без офиса, без ВК: //sale.itcity.ru/public/202023
Душелов: Чтение/Запись документа Excel 2007 без офиса, без ВК. (с примером для 7.7, 8.1 и 8.2 на управляемых формах): //sale.itcity.ru/public/19139
«Другое: чтение/редактирование XML»:
anig99: «Однопальцевое» чтение XML для 8.2: //sale.itcity.ru/public/84254
Lokiy: Парсинг, преобразование, редактирование XML: //sale.itcity.ru/public/198131
onec.developer: Редактор XML на управляемых формах 8.2: //sale.itcity.ru/public/201077
Yashazz: Просмотр xml-файлов: //sale.itcity.ru/public/203514
Душелов: Создание документа Word 2007: //sale.itcity.ru/public/16215
«Не 1С, но полезно»:
iddqd: akXmlEdit — v1.5.0.7 редактор XML: //sale.itcity.ru/public/15464
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ФайлEXCEL= «D:\Товар.xlsx»;
ИмяНомерЛиста = Новый Структура («ИмяЛиста, НомерЛиста»,«Alfa1», 1);
СтрокаЗаголовка = 1;
НачСтрока = 0;
КонСтрока = 0;
КолвоСтрокExcel = 0;
ЗагрузитьМетодом_NativeXLSX_НаСервере(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel);
КонецПроцедуры
&НаСервере
Процедура ЗагрузитьМетодом_NativeXLSX_НаСервере(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel)
ТаблицаРезультат = ЗагрузитьМетодом_NativeXLSX(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel);
КонецПроцедуры
// Метод «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 Тогда
МассивПустыхКолонок.Добавить(Колонка.Имя);
КонецЕсли;
КонецЦикла;
// Удалим пустые колонки.
Для Каждого ПустаяКолонка ИЗ МассивПустыхКолонок Цикл
ТаблицаРезультат.Колонки.Удалить(ПустаяКолонка);
КонецЦикла;
КонецПроцедуры
С уважением к сообществу МА!

