При самостоятельной разработке выгрузки номенклатуры в файл Excel разработчики часто сталкиваются с двумя типичными сложностями: ошибками при передаче ссылочных реквизитов (например, единиц измерения) в ячейки таблицы и необходимостью сохранить иерархическую структуру папок и товаров с группировками строк. Разберем основные причины этих проблем и рассмотрим эффективные варианты реализации выгрузки.
Проанализируем типичные ошибки, возникающие при попытке заполнить ячейки Excel напрямую через Excel.Application:
СправочникСсылка.ЕдиницыИзмерения), COM-объект Excel не может автоматически преобразовать внутренний объект 1С в поддерживаемый тип данных. В ячейку необходимо передавать строковое представление или примитивный тип.Номенклатура.ДополнительныеРеквизиты.(...)) возвращает в каждой строке вложенную таблицу значений, которую невозможно напрямую присвоить значению ячейки.Лист.Cells(Строка, Колонка).Value = Значение при больших объемах данных занимает значительное время из-за постоянных межпроцессных вызовов между 1С и Microsoft Excel.Наиболее быстрый и надежный способ — сформировать ТабличныйДокумент на стороне сервера и сохранить его в формате XLSX методом Записать(). Этот подход работает без установленного Microsoft Excel, платформенно независим (подходит для Linux-серверов) и в десятки раз быстрее прямого обращения к COM.
Разберем по шагам построение запроса с иерархией и сохранение документа:
&НаСервере
Процедура ВыгрузитьНоменклатуруВФайл(ПутьКФайлу)
// 1. Формируем запрос с получением иерархии
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.ЭтоГруппа КАК ЭтоГруппа,
| Номенклатура.Код КАК Код,
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.Наименование КАК Наименование,
| ПРЕДСТАВЛЕНИЕ(Номенклатура.ЕдиницаИзмерения) КАК ЕдиницаИзмерения,
| ПРЕДСТАВЛЕНИЕ(Номенклатура.ВидНоменклатуры) КАК ВидНоменклатуры
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ИТОГИ ПО
| Ссылка ТОЛЬКО ИЕРАРХИЯ";
РезультатЗапроса = Запрос.Выполнить();
// 2. Создаем табличный документ и включаем автогруппировку
ТабДок = Новый ТабличныйДокумент;
ТабДок.НачатьАвтогруппировкуСтрок();
// Заполняем шапку
ТабДок.Область(1, 1).Текст = "Код";
ТабДок.Область(1, 2).Текст = "Артикул";
ТабДок.Область(1, 3).Текст = "Наименование";
ТабДок.Область(1, 4).Текст = "Ед. изм.";
ТабДок.Область(1, 5).Текст = "Вид номенклатуры";
ТекущаяСтрока = 1;
// 3. Обходим результат по иерархическим группировкам
Выборка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
ВывестиИерархиюВТабличныйДокумент(Выборка, ТабДок, ТекущаяСтрока);
ТабДок.ЗакончитьАвтогруппировкуСтрок();
// 4. Сохраняем в формат XLSX
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
КонецПроцедуры
&НаСервере
Процедура ВывестиИерархиюВТабличныйДокумент(Выборка, ТабДок, ТекущаяСтрока)
Пока Выборка.Следующий() Цикл
ТекущаяСтрока = ТекущаяСтрока + 1;
Уровень = Выборка.Уровень();
ТабДок.Область(ТекущаяСтрока, 1).Текст = Выборка.Код;
ТабДок.Область(ТекущаяСтрока, 2).Текст = Выборка.Артикул;
ТабДок.Область(ТекущаяСтрока, 3).Текст = Выборка.Наименование;
ТабДок.Область(ТекущаяСтрока, 4).Текст = Выборка.ЕдиницаИзмерения;
ТабДок.Область(ТекущаяСтрока, 5).Текст = Выборка.ВидНоменклатуры;
// Устанавливаем уровень группировки для строки
ТабДок.УстановитьУровеньГруппировкиСтрок(ТекущаяСтрока, Уровень);
// Рекурсивно выводим подчиненные элементы
ВыборкаПодчиненные = Выборка.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
Если ВыборкаПодчиненные.Количество() > 0 Тогда
ВывестиИерархиюВТабличныйДокумент(ВыборкаПодчиненные, ТабДок, ТекущаяСтрока);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Использование методов НачатьАвтогруппировкуСтрок() и ЗакончитьАвтогруппировкуСтрок() гарантирует, что при открытии полученного файла в Excel пользователю будет доступна стандартная структура сворачиваемых уровней.
Если специфика задачи требует обязательного использования прямого COM-соединения, необходимо скорректировать текст запроса и процесс заполнения ячеек:
Номенклатура.ЕдиницаИзмерения.Наименование) или системную функцию ПРЕДСТАВЛЕНИЕ(Номенклатура.ЕдиницаИзмерения).Посмотрим на пример правильного формирования запроса для COM-выгрузки:
&НаСервере
Функция ПолучитьТаблицуДляВыгрузки()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Код КАК Код,
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.ЕдиницаИзмерения.Наименование КАК ЕдиницаИзмерения,
| ПРЕДСТАВЛЕНИЕ(Номенклатура.ВидНоменклатуры) КАК ВидНоменклатуры
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
После получения таблицы данных, где все колонки имеют простые типы (число, строка), перенос в COM-объект не вызовет исключений.
Для создания гибких отчетов с выгрузкой иерархии можно использовать программный запуск схемы компоновки данных:
Ссылка (или Номенклатура) указывается тип «Иерархия».ТабличныйДокумент с помощью ПроцессорКомпоновкиДанных и ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент.ТабличныйДокумент.Записать() в файл XLSX. Этот вариант полностью исключает ручное написание кода рекурсивного обхода иерархических уровней.