Часто разработчики 1С сталкиваются с ситуацией: при формировании отчета пользователем в табличный документ цифры верные, но как только мы пытаемся получить те же данные программно в ТаблицаЗначений для дальнейшей обработки, результат внезапно меняется. Суммы могут «удваиваться», обнуляться или просто не соответствовать ожидаемым. Рассмотрим подробнее, почему так происходит, и разберем по шагам, как добиться идентичности данных.
Проанализируем типичный код инициализации компоновки. Одной из самых частых ошибок является прямое использование свойства КомпоновщикНастроек.Настройки. В Системе Компоновки Данных (СКД) существует три уровня настроек: основные, пользовательские и фиксированные.
Когда пользователь меняет даты или отборы на форме, эти изменения чаще всего попадают в ПользовательскиеНастройки. Если в коде мы передаем в КомпоновщикМакета.Выполнить() просто Настройки, платформа проигнорирует всё, что ввел пользователь. Выясним, как правильно собрать итоговый вариант настроек:
// Неправильно:
// МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, КомпоновщикНастроек.Настройки);
// Правильно:
ПолныеНастройки = ОтчетОбъект.КомпоновщикНастроек.ПолучитьНастройки();
МакетКомпоновки = КомпМакета.Выполнить(ОтчетОбъект.СхемаКомпоновкиДанных, ПолныеНастройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
Метод ПолучитьНастройки() выполняет «сборку» всех уровней в один результирующий объект. Только так параметры и отборы, установленные на форме, попадут в расчет.
Разберем ситуацию, когда настройки переданы верно, но цифры все равно отличаются. Посмотрим на стандартный метод СкомпоноватьРезультат(). Он является «высокоуровневым» и автоматически вызывает обработчик события ПриКомпоновкеРезультата в модуле отчета.
В этом обработчике программисты часто пишут важную логику: дозаполнение параметров, программную установку отборов или даже модификацию текста запроса. Однако, когда мы используем ручной цикл генерации макета через КомпоновщикМакета.Выполнить(), это событие не вызывается автоматически. В результате вся логика, заложенная внутри модуля отчета, просто пролетает мимо нашей таблицы значений.
Чтобы решить эту проблему, нам необходимо либо вручную вызвать процедуру из модуля, либо (если процедура экспортируемая) продублировать её логику в нашем коде формирования ТЗ.
Проанализируем, как ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений работает со структурой отчета. В отличие от табличного документа, который визуально разделяет итоги и детальные записи, ТаблицаЗначений получает данные плоским списком.
Если в настройках отчета указаны группировки, то при выводе в ТаблицаЗначений система выгрузит и детальные записи, и строки итогов по каждой группировке. Посмотрим на последствия: если вы попытаетесь свернуть полученную таблицу или просуммировать колонку, вы получите завышенные данные, так как одна и та же сумма будет учтена и в детальной строке, и в строке группировки.
Рекомендация: Перед генерацией макета для таблицы значений программно удаляйте группировки из настроек, если вам нужны только детальные данные, либо проверяйте тип записи при обходе результата.
// Удаление группировок для получения только детальных записей
НастройкиДляТЗ = ОтчетОбъект.КомпоновщикНастроек.ПолучитьНастройки();
НастройкиДляТЗ.Структура.Очистить();
Группировка = НастройкиДляТЗ.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Группировка.Использование = Истина;
ПолеДетальныхЗаписей = Группировка.ВыбранныеПоля.Элементы.Добавить(Тип("АвтовыбранноеПолеКомпоновкиДанных"));
ПолеДетальныхЗаписей.Использование = Истина;
Выясним причину, связанную с внешними данными. Если отчет строится на базе внешнего набора данных (таблицы, передаваемой в запрос), при использовании СкомпоноватьРезультат() система сама ищет подходящий объект в свойствах отчета. При программном выводе мы обязаны явно передать эти данные в ПроцессорКомпоновкиДанных.
Также важно учитывать «Фиксированные настройки», которые часто используются в конфигурациях на базе БСП для ограничения прав или привязки к организации. Если их не учесть при вызове КомпоновщикМакета.Выполнить(), отчет может выдать данные по всем организациям сразу, что приведет к расхождению с экранной формой.
Суммируя всё вышесказанное, составим эталонный алгоритм программного получения данных из СКД:
КомпоновщикНастроек.ПолучитьНастройки() для объединения всех уровней (основные, пользовательские, фиксированные).ПриКомпоновкеРезультата, обязательно выполняем аналогичные действия с объектом настроек.Структура.КомпоновщикМакета с типом генератора Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений").ПроцессорКомпоновкиДанных, не забывая передать внешние наборы данных, если они есть.ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений.Соблюдение этого порядка действий гарантирует, что цифры в вашей таблице значений будут в точности совпадать с тем, что видит пользователь в стандартном отчете на экране.