Почему возникает ошибка «Поле объекта не обнаружено (НаименованиеПолное)» при выгрузке проводок документа в Excel?

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

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

Разберем детально, почему возникает данная проблема, как устроена типизация субконто в регистрах бухгалтерии, в чем заключаются скрытые логические ошибки в запросах и как правильно организовать выгрузку данных.

Анализ исходного кода и причин ошибки

Рассмотрим фрагмент кода выборки данных и обращения к реквизитам в цикле:


// Фрагмент условия в виртуальной таблице регистра:
СчетДт.Родитель.Код = "62"
И СчетКт.Родитель.Код = "90.01"
ИЛИ СчетКт.Родитель.Код = "41"

// Фрагмент обработки строки в цикле:
Лист.Cells(a,5).value = РезультатЗапроса.СубконтоДт1.НаименованиеПолное;

В приведенном коде скрыты сразу две фундаментальные проблемы: логическая ошибка построения условия в запросе и некорректная работа с составными типами данных аналитики (субконто).

  1. Нарушение приоритета логических операций: в языке запросов 1С логический оператор И имеет более высокий приоритет по сравнению с оператором ИЛИ. Из-за отсутствия явных скобок условие читается платформой как: «(СчетДт из группы 62 И СчетКт из группы 90.01) ИЛИ (любой СчетДт И СчетКт из группы 41)». Документ РеализацияТоваровУслуг делает проводки не только по признанию выручки (Дт 62.01 — Кт 90.01.1), но и по списанию себестоимости (Дт 90.02.1 — Кт 41.01). Вторая проводка полностью подпадает под правую часть условия ИЛИ СчетКт.Родитель.Код = "41".
  2. Неоднородный состав типов субконто: реквизиты СубконтоДт1, СубконтоКт1 и другие имеют составной тип данных (Характеристика.ВидыСубконтоХозрасчетные). Для счета 62 первым субконто выступает справочник Контрагенты, у которого реквизит НаименованиеПолное присутствует. Но для счета 90.02.1 первым субконто является справочник Номенклатурные группы, у которого такого реквизита в типовой конфигурации нет. Прямое обращение через точку в цикле приводит к выбросу критического исключения.
  3. Ошибочная фильтрация по коду родителя счета: конструкция СчетДт.Родитель.Код = "62" ненадежна. Если счет в плане счетов не имеет родителя (является счетом верхнего уровня) или иерархия счетов глубже одного уровня, обращение к свойству Родитель вернет пустое значение или не тот уровень иерархии.

Шаг 1. Исправление логических условий в запросе

Для корректного отбора проводок перепишем условие виртуальной таблицы. Отбор счетов следует выполнять с помощью оператора В ИЕРАРХИИ и предопределенных значений или через явную группировку условий скобками.

Посмотрим на исправленный текст условия параметров виртуальной таблицы:


ГДЕ
    (СчетДт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Покупатели))
        И СчетКт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Выручка)))
    ИЛИ (СчетДт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.СебестоимостьПродаж))
        И СчетКт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Товары)))

Если для выгрузки требуются исключительно расчеты с покупателями (выручка), второе условие следует полностью исключить, чтобы проводки списания себестоимости даже не попадали в выборку.

Шаг 2. Безопасное получение полей через ВЫРАЗИТЬ в запросе

Обращение через точку к ссылочным полям в цикле выборки (РезультатЗапроса.СубконтоДт1.НаименованиеПолное) является грубой ошибкой: во-первых, это вызывает неявные подзапросы к базе данных на каждой итерации цикла (проблема N+1), а во-вторых, приводит к падению при несовпадении типов. Все реквизиты необходимо получать непосредственно в тексте запроса с явным приведением типа.

Проанализируем пример безопасного извлечения данных субконто:


ВЫБРАТЬ
    Хозрасчетный.Период КАК Период,
    Хозрасчетный.Регистратор КАК Регистратор,
    Хозрасчетный.Регистратор.Номер КАК НомерДокумента,
    Хозрасчетный.Регистратор.Дата КАК ДатаДокумента,
    Хозрасчетный.СчетДт.Код КАК СчетДтКод,
    Хозрасчетный.СчетКт.Код КАК СчетКтКод,
    Хозрасчетный.Сумма КАК Сумма,
    Хозрасчетный.СуммаНУКт КАК СуммаНУКт,
    ВЫРАЗИТЬ(Хозрасчетный.СубконтоДт1 КАК Справочник.Контрагенты).НаименованиеПолное КАК КонтрагентНаименованиеПолное,
    ВЫРАЗИТЬ(Хозрасчетный.СубконтоДт1 КАК Справочник.Контрагенты).ИНН КАК КонтрагентИНН,
    ВЫРАЗИТЬ(Хозрасчетный.СубконтоДт1 КАК Справочник.Контрагенты).КПП КАК КонтрагентКПП,
    ВЫРАЗИТЬ(Хозрасчетный.СубконтоДт2 КАК Справочник.ДоговорыКонтрагентов).Наименование КАК ДоговорНаименование
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
        &НачалоПериода,
        &КонецПериода,
        СчетДт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Покупатели))
            И СчетКт В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Выручка)),
        ,
    ) КАК Хозрасчетный

Использование конструкции ВЫРАЗИТЬ(... КАК Справочник.Контрагенты) гарантирует: если в поле СубконтоДт1 окажется значение другого типа (например, номенклатурная группа или склад), выражение вернет NULL, а не вызовет аварийную остановку программы.

Шаг 3. Оптимизация записи данных в Excel

Построчная запись значений через COM-объект Лист.Cells(a, b).Value работает крайне медленно на больших объемах данных из-за постоянного межпроцессного взаимодействия между 1С и Excel. Кроме того, COM-соединение требует обязательной установки MS Office на клиентском компьютере и корректного завершения процесса.

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


ТабДок = Новый ТабличныйДокумент;
// Заполнение макета или программное формирование ячеек
// ...
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);

Если же используется запись через Excel.Application, обязательно закрываем объект и освобождаем занятую память в операционной системе:


Excel.ActiveWorkbook.SaveAs(ПутьКФайлу);
Excel.Quit();
Excel = Неопределено;

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

← На главную