При интеграции прайс-листов, каталогов и накладных от внешних контрагентов разработчики часто сталкиваются с жестко зашитыми в коде номерами колонок. Когда структура входящего файла Excel меняется, алгоритм перестает работать корректно или аварийно завершается. Разберем по шагам, как параметризовать номера колонок, избежать распространенных ошибок типов данных, а также рассмотрим нюансы работы с COM-объектом и более надежные альтернативные методы загрузки.
Проанализируем базовый код чтения через COM-объект, в котором обращение к ячейкам зафиксировано жесткими числовыми индексами:
НоваяСтрока.Артикул = Лист.Cells(ТекСтрока, 3).Text;
НоваяСтрока.Производитель = Лист.Cells(ТекСтрока, 1).Text;
НоваяСтрока.СсылкаНаКартинку = Лист.Cells(ТекСтрока, 4).Text;
НоваяСтрока.ОписаниеТовара = Лист.Cells(ТекСтрока, 5).Text;
В методе Cells(НомерСтроки, НомерКолонки) второй параметр представляет собой порядковый номер столбца листа Excel. Чтобы сделать выбор колонок настраиваемым для пользователя, вынесем эти параметры на форму обработки.
Разберем по шагам правильную настройку:
НомерКолонкиАртикула, НомерКолонкиПроизводителя, НомерКолонкиКартинки, НомерКолонкиОписания.Число (длина 3, точность 0, неотрицательное). Если оставить строковый тип данных по умолчанию, COM-сервер Excel выбросит исключительную ситуацию при попытке передать строку в метод Cells().Посмотрим на пример итогового кода цикла обхода строк:
Пока Лист.Cells(ТекСтрока, НомерКолонкиПроизводителя).Text <> "" Цикл
НоваяСтрока = ДанныеПоискаИзExcel.Добавить();
НоваяСтрока.Артикул = Лист.Cells(ТекСтрока, НомерКолонкиАртикула).Text;
НоваяСтрока.Производитель = Лист.Cells(ТекСтрока, НомерКолонкиПроизводителя).Text;
НоваяСтрока.СсылкаНаКартинку = Лист.Cells(ТекСтрока, НомерКолонкиКартинки).Text;
НоваяСтрока.ОписаниеТовара = Лист.Cells(ТекСтрока, НомерКолонкиОписания).Text;
ТекСтрока = ТекСтрока + 1;
КонецЦикла;
Использование COM-соединения сопряжено с рядом технических ограничений, о которых важно помнить при промышленной эксплуатации обработки:
Книга.Close(False) и Эксель.Quit() часто бывает недостаточно. Если в переменных 1С сохраняются ссылки на ячейки, листы или книгу, процесс EXCEL.EXE продолжает работать в фоновом режиме, блокируя файлы. Чтобы гарантированно освободить память, необходимо обнулять все промежуточные переменные:
Лист = Неопределено;
Книга = Неопределено;
Эксель.Quit();
Эксель = Неопределено;
Text возвращает строку именно в том виде, в каком она видна на экране в приложении Excel. Если ширина колонки недостаточна, свойство вернет ###, а числа и даты будут отформатированы по региональным стандартам Windows. Для получения точных и типизированных значений рекомендуется считывать свойство Value.Пока Лист.Cells(ТекСтрока, 1).Text <> "" немедленно остановит обработку, если в середине таблицы встретится одна пустая строка или незаполненная ключевая ячейка. Надежнее использовать цикл Для по уже вычисленному максимальному количеству строк ФайлСтрок, проверяя заполненность данных внутри тела цикла.Рассмотрим более современный, стабильный и кроссплатформенный способ чтения Excel-файлов средствами встроенного языка без использования COM-сервера. Объект ТабличныйДокумент позволяет открывать файлы .xls и .xlsx напрямую как на клиенте, так и на сервере под управлением Windows или Linux.
Посмотрим на пример реализации универсального обхода через ТабличныйДокумент:
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу);
Исключение
ВызватьИсключение "Не удалось прочитать файл: " + ОписаниеОшибки();
КонецПопытки;
ВсегоСтрок = ТабДок.ВысотаТаблицы;
НачальнаяСтрока = 8;
Для НомерСтроки = НачальнаяСтрока По ВсегоСтрок Цикл
ТекстАртикула = СокрЛП(ТабДок.Область(НомерСтроки, НомерКолонкиАртикула).Текст);
// Пропускаем строки без артикула
Если ПустаяСтрока(ТекстАртикула) Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = ДанныеПоискаИзExcel.Добавить();
НоваяСтрока.Артикул = ТекстАртикула;
НоваяСтрока.Производитель = СокрЛП(ТабДок.Область(НомерСтроки, НомерКолонкиПроизводителя).Текст);
НоваяСтрока.СсылкаНаКартинку = СокрЛП(ТабДок.Область(НомерСтроки, НомерКолонкиКартинки).Текст);
НоваяСтрока.ОписаниеТовара = СокрЛП(ТабДок.Область(НомерСтроки, НомерКолонкиОписания).Текст);
КонецЦикла;
Преимущества такого подхода очевидны: код работает автономно, в несколько раз быстрее обращается к ячейкам, не оставляет зависших процессов в диспетчере задач и не требует установленного на сервере или клиентской машине пакета Microsoft Office.
Если задача заключается в загрузке цен поставщиков, поступлений или начальных остатков, проанализируем возможность использования штатных механизмов конфигурации. В «1С:Управление торговлей 11» интегрирована подсистема БСП «Загрузка данных из внешних файлов». Она предоставляет готовый пользовательский диалог сопоставления колонок, автоматическое распознавание заголовков, предварительную валидацию типов и сохранение шаблонов настроек сопоставления под каждого контрагента без необходимости доработки конфигурации в режиме Конфигуратора.