Почему не выгружается группа основных средств в Excel из 1С и как это исправить

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке собственных отчетов и обработок выгрузки данных по основным средствам в Microsoft Excel разработчики часто сталкиваются с ситуацией, когда классификационные признаки (группа ОС, амортизационная группа) заполняются некорректно либо остаются пустыми. Рассмотрим причины возникновения этой проблемы, типичные ошибки при обращении к свойствам объектов и способы оптимизации программного кода.

Причины некорректного получения группы основного средства

Выясним, из-за чего в результирующем файле поле группы может оставаться пустым или вызывать исключение во время выполнения программы:

  1. Разница между иерархией справочника и классификацией: В справочнике ОсновныеСредства папка, в которой лежит элемент, доступна через системный реквизит Родитель (тип СправочникСсылка.ОсновныеСредства). В то же время реквизит ГруппаОС (или ГруппаУчетаОС в зависимости от редакции конфигурации) представляет собой ссылку на системное перечисление (ПеречислениеСсылка.ГруппыОС). Если требуется вывести именно папку каталога, а программа обращается к реквизиту перечисления (или наоборот), на выходе получается пустое значение.
  2. Попытка обращения к несуществующим реквизитам перечисления: При обращении вида ОсновноеСредство.ГруппаОС.Наименование платформа генерирует исключительную ситуацию «Поле объекта не обнаружено (Наименование)», поскольку у элементов перечислений нет свойства Наименование — строковое представление перечисления получается с помощью стандартной функции Строка() или конструкции ПРЕДСТАВЛЕНИЕ() в тексте запроса.
  3. Невыбранные поля в исходном запросе (разыменование через точку): Если поле не выбрано в секции ВЫБРАТЬ, а запрашивается в цикле через точку от результата выборки (например, РезультатЗапроса.ОсновноеСредство.ГруппаОС), платформа выполняет неявный SQL-запрос к СУБД для каждой строки (проблема N+1). Если связь нарушена или поле не заполнено в самом элементе, значение будет пустым.

Исправление текста запроса и выборки данных

Проанализируем структуру исходного запроса. Чтобы исключить неявные обращения к базе данных внутри цикла и сразу получить корректные строковые представления, вынесем все реквизиты в текст запроса. Также обязательно приведем составной тип субконто к типу Справочник.ОсновныеСредства с помощью оператора ВЫРАЗИТЬ.

Посмотрим на пример оптимизированного текста запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Хозрасчетный.Регистратор КАК Регистратор,
    |	Хозрасчетный.Регистратор.Номер КАК НомерДокумента,
    |	Хозрасчетный.Регистратор.Дата КАК ДатаДокумента,
    |	Хозрасчетный.СчетДт.Код КАК СчетДтКод,
    |	Хозрасчетный.Сумма КАК Сумма,
    |	Хозрасчетный.СуммаНУДт КАК СуммаНУДт,
    |	Хозрасчетный.СуммаНУКт КАК СуммаНУКт,
    |	ВЫРАЗИТЬ(Хозрасчетный.СубконтоКт1 КАК Справочник.ОсновныеСредства) КАК ОсновноеСредство,
    |	ПРЕДСТАВЛЕНИЕ(ВЫРАЗИТЬ(Хозрасчетный.СубконтоКт1 КАК Справочник.ОсновныеСредства).НаименованиеПолное) КАК ОСПолноеНаименование,
    |	ПРЕДСТАВЛЕНИЕ(ВЫРАЗИТЬ(Хозрасчетный.СубконтоКт1 КАК Справочник.ОсновныеСредства).АмортизационнаяГруппа) КАК АмортизационнаяГруппа,
    |	ПРЕДСТАВЛЕНИЕ(ВЫРАЗИТЬ(Хозрасчетный.СубконтоКт1 КАК Справочник.ОсновныеСредства).ГруппаОС) КАК ГруппаУчетаОС,
    |	ПРЕДСТАВЛЕНИЕ(ВЫРАЗИТЬ(Хозрасчетный.СубконтоКт1 КАК Справочник.ОсновныеСредства).Родитель) КАК ИерархическаяГруппа,
    |	ПервоначальныеСведения.ПервоначальнаяСтоимость КАК ПервоначальнаяСтоимость,
    |	ПервоначальныеСведения.Период КАК ДатаВвода
    |ИЗ
    |	РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
    |			&НачалоПериода,
    |			&КонецПериода,
    |			СчетДт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ОсновноеПроизводство), ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ОбщепроизводственныеРасходы), ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ОбщехозяйственныеРасходы))
    |				И СчетКт = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.АмортизацияОС_01),
    |			,
    |			) КАК Хозрасчетный
    |		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПервоначальныеСведенияОСБухгалтерскийУчет КАК ПервоначальныеСведения
    |		ПО (ПервоначальныеСведения.ОсновноеСредство = ВЫРАЗИТЬ(Хозрасчетный.СубконтоКт1 КАК Справочник.ОсновныеСредства))
    |ГДЕ
    |	Хозрасчетный.Сумма <> 0";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ДатаНачала));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ДатаКонца));

Выборка = Запрос.Выполнить().Выбрать();

Корректный вывод данных в Excel через COM-объект

Разберем процесс заполнения листа книги Excel. Поскольку строковые представления всех перечислений и ссылок мы уже сформировали в запросе с помощью функции ПРЕДСТАВЛЕНИЕ(), в цикле выгрузки отпадает необходимость вызывать функции преобразования и обращаться к свойствам объектов через точку.

Посмотрим на пример заполнения строк:


Попытка
    Excel = Новый COMОбъект("Excel.Application");
Исключение
    Сообщить("Не удалось запустить Excel. Проверьте установку офисного пакета.");
    Возврат;
КонецПопытки;

Книга = Excel.Workbooks.Open("C:\Temp\ExportOS.xlsx");
Лист = Книга.Sheets(1);

НомерСтроки = 1;
Пока Выборка.Следующий() Цикл
    НомерСтроки = НомерСтроки + 1;
    
    // Номер и дата регистратора
    Лист.Cells(НомерСтроки, 1).NumberFormat = "@";
    Лист.Cells(НомерСтроки, 1).Value = Выборка.НомерДокумента;
    Лист.Cells(НомерСтроки, 2).NumberFormat = "ДД.ММ.ГГГГ";
    Лист.Cells(НомерСтроки, 2).Value = Выборка.ДатаДокумента;
    
    // Суммовые показатели
    Лист.Cells(НомерСтроки, 10).NumberFormat = "0,00";
    Лист.Cells(НомерСтроки, 10).Value = Выборка.Сумма;
    
    // Сведения по основному средству
    Лист.Cells(НомерСтроки, 14).NumberFormat = "@";
    Лист.Cells(НомерСтроки, 14).Value = Выборка.ОСПолноеНаименование;
    
    Лист.Cells(НомерСтроки, 15).NumberFormat = "@";
    Лист.Cells(НомерСтроки, 15).Value = Выборка.АмортизационнаяГруппа;
    
    Лист.Cells(НомерСтроки, 16).NumberFormat = "ДД.ММ.ГГГГ";
    Лист.Cells(НомерСтроки, 16).Value = Выборка.ДатаВвода;
    
    Лист.Cells(НомерСтроки, 17).NumberFormat = "0,00";
    Лист.Cells(НомерСтроки, 17).Value = Выборка.ПервоначальнаяСтоимость;
    
    // Классификационная группа учета (перечисление)
    Лист.Cells(НомерСтроки, 18).NumberFormat = "@";
    Лист.Cells(НомерСтроки, 18).Value = Выборка.ГруппаУчетаОС;
    
    // Папка в справочнике (если нужна иерархия каталога)
    Лист.Cells(НомерСтроки, 19).NumberFormat = "@";
    Лист.Cells(НомерСтроки, 19).Value = Выборка.ИерархическаяГруппа;
КонецЦикла;

Книга.Save();
Excel.Quit();

Альтернативный и более быстрый способ: Табличный документ

Рассмотрим альтернативу работе через COMОбъект("Excel.Application"). Прямая поячеечная запись в COM-объект в больших циклах работает медленно и требует обязательного наличия установленного Excel на рабочем месте.

Рекомендуется формировать отчет с помощью встроенного объекта ТабличныйДокумент и сохранять его штатными средствами 1С:


ТабДок = Новый ТабличныйДокумент;
// Заполнение ТабДок данными отчета или макета...

// Сохранение готовой таблицы напрямую в XLSX без использования Excel
ТабДок.Записать("C:\Temp\ExportOS.xlsx", ТипФайлаТабличногоДокумента.XLSX);

Такой подход выполняется в разы быстрее, работает в среде Linux, в веб-клиенте и на сервере без вызова внешних компонентов.

← На главную