При разработке отчетов с использованием объекта БухгалтерскиеИтоги в платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ошибкой: «Значение не представляет агрегатный объект (ИмяРеквизита)» при попытке обратиться через точку к реквизитам субконто справочника (например, Ит.Субконто(ВидыСубконто.РасходыБудущихПериодов).ДатаНачалаСписания). При этом в ячейке таблицы отчета это же выражение может отрабатывать корректно.
Разберем подробно причины возникновения этой ошибки, выясним различия в обработке выражений кодом и макетом таблицы, а также рассмотрим по шагам правильные способы обращения к реквизитам субконто и передачи данных в секции печатной формы.
Проанализируем механику работы платформы 1С 7.7. Ошибка времени выполнения возникает по следующим причинам:
Ит.ПолучитьСубконто(), объект Ит.Субконто() еще не содержит ссылки на конкретный элемент справочника. Он возвращает пустое значение или неопределенный тип, у которого нет запрашиваемого реквизита.Сформировать_Колонки), внутри которой прописано чтение реквизита субконто, программа падает, так как курсор выборки итогов на момент вывода шапки еще не спозиционирован на записи.Почему же аналогичное выражение работает в ячейке таблицы? Механизм расчета ячеек печатной формы в 1С 7.7 снабжен встроенной защитой: при попытке вычислить реквизит от неинициализированного или пустого объекта ячейка просто остается пустой, не прерывая работу программы. В программном коде модуля такое поведение считается критической ошибкой.
Разберем, как правильно выстроить последовательность операций при работе с бухгалтерскими итогами. Обращение к реквизитам субконто должно выполняться строго внутри цикла выборки субконто.
Посмотрим на пример правильной структуры формирования отчета:
Процедура Сформировать()
Перем Таб, Ит;
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Сформировать");
Ит = СоздатьОбъект("БухгалтерскиеИтоги");
Ит.ИспользоватьСубконто(ВидыСубконто.РасходыБудущихПериодов,, 1);
// Выполняем бухгалтерский запрос
Ит.ВыполнитьЗапрос(ВыбНачПериода, ВыбКонПериода, "97",,, 1,, "С");
// Выводим шапку отчета
Таб.ВывестиСекцию("Заголовок");
Сформировать_Колонки(Ит, Таб, "Шапка");
Таб.Опции(0, 0, Таб.ВысотаТаблицы, 0);
// Обходим полученные субконто
Ит.ВыбратьСубконто(ВидыСубконто.РасходыБудущихПериодов);
Пока Ит.ПолучитьСубконто(ВидыСубконто.РасходыБудущихПериодов) = 1 Цикл
// Обращение к реквизитам безопасно только внутри этого цикла
Сформировать_Колонки(Ит, Таб, "Субконто1");
КонецЦикла;
// Выводим подвал отчета
Сформировать_Колонки(Ит, Таб, "Подвал");
Таб.ТолькоПросмотр(1);
Таб.Показать("Сформировать", "");
КонецПроцедуры
Для предотвращения аварийных остановок из-за незаполненных субконто рекомендуется использовать проверку на заполненность и выбор элемента. Также вместо длинной конструкции с указанием вида субконто удобнее и быстрее обращаться по номеру уровня группировки:
ДатаНачала = "";
Если ПустоеЗначение(Ит.Субконто(1)) = 0 Тогда
Если Ит.Субконто(1).Выбран() = 1 Тогда
ДатаНачала = НачМесяца(Ит.Субконто(1).ДатаНачалаСписания);
КонецЕсли;
КонецЕсли;
Рассмотрим, как передать вычисленное значение даты в процедуру печати строк таблицы (Сформировать_Колонки):
Способ 1. Передача значения через параметры процедуры
Добавим в процедуру вывода колонок дополнительный параметр со значением по умолчанию:
Процедура Сформировать_Колонки(Ит, Таб, Стр, ДатаНач = "")
// Переменная ДатаНач доступна для вывода в секции таблицы
Таб.ВывестиСекцию(Стр + "|Начало");
Ит.ВыбратьСчета(1);
Пока Ит.ПолучитьСчет() = 1 Цикл
Таб.ПрисоединитьСекцию(Стр + "|Счет");
КонецЦикла;
Таб.ПрисоединитьСекцию(Стр + "|Итог");
КонецПроцедуры
В цикле обхода вызываем процедуру с передачей полученной даты:
Пока Ит.ПолучитьСубконто(1) = 1 Цикл
ДатаНачала = "";
Если ПустоеЗначение(Ит.Субконто(1)) = 0 Тогда
ДатаНачала = НачМесяца(Ит.Субконто(1).ДатаНачалаСписания);
КонецЕсли;
Сформировать_Колонки(Ит, Таб, "Субконто1", ДатаНачала);
КонецЦикла;
Способ 2. Использование переменной уровня модуля
Если объявить переменную в самом начале модуля отчета до всех процедур (Перем ДатаНачала;), она станет глобальной в рамках текущего модуля. При вызове Таб.ВывестиСекцию() ячейки таблицы с типом «Выражение» или «Шаблон» смогут напрямую обращаться к значению переменной ДатаНачала без необходимости передачи её через параметры.
Если при отладке необходимо проверить значение выражения, выполним следующие действия:
Пока Ит.ПолучитьСубконто(...) = 1 Цикл.Ит.Субконто(1).ДатаНачалаСписания или Ит.Субконто(1).