Как программно выгрузить данные из СКД в таблицу значений с учетом пользовательских отборов?

Программист 1С v8.3 (Обычные формы) Промышленность, строительство и АПК
← На главную

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

Анализ механизма компоновки данных

Для начала разберем стандартный алгоритм программного вывода СКД в коллекцию значений. Процесс состоит из нескольких этапов, на каждом из которых может возникнуть ошибка логики. Проанализируем типичный код, представленный в вопросе:


СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных"); 
НастройкиКомпоновкиДанных = КомпоновщикНастроек.Настройки; 
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных; 
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновки, НастройкиКомпоновкиДанных,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")); 
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных; 
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных); 
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений; 
ТЗ = ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

На первый взгляд код выглядит корректным (хотя для сокращения листинга может пригодиться СКДБилдер). Однако основная проблема здесь кроется в строке НастройкиКомпоновкиДанных = КомпоновщикНастроек.Настройки;. Выясним причину, по которой этот подход не работает при наличии пользовательских отборов.

Разница между Настройки и ПользовательскиеНастройки

В системе компоновки данных существует разделение настроек на "фиксированные" (те, что заданы разработчиком в конфигураторе) и "пользовательские" (те, что пользователь изменил на форме отчета). Объект КомпоновщикНастроек содержит в себе три ключевых свойства:

  1. Настройки — это базовые настройки из схемы.
  2. ПользовательскиеНастройки — это коллекция, в которой хранятся только те элементы (отборы, параметры, группировки), которые вынесены в пользовательский интерфейс и изменены пользователем (в том числе через механизм пользовательской СКД).
  3. ФиксированныеНастройки — настройки, которые нельзя изменить пользователю.

Когда мы обращаемся напрямую к КомпоновщикНастроек.Настройки, мы получаем исходное состояние отчета без учета тех галочек и значений, которые пользователь проставил перед формированием. Именно поэтому результирующая ТаблицаЗначений может оказаться пустой (если параметры по умолчанию не заполнены) или содержать лишние данные.

Решение проблемы: Метод ПолучитьНастройки()

Чтобы система объединила все виды настроек в один результирующий объект, который и должен быть передан в КомпоновщикМакета, необходимо использовать метод ПолучитьНастройки(). Разберем по шагам, как должен выглядеть правильный код:


// 1. Получаем схему из макета
СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных"); 

// 2. ВАЖНО: Получаем ПОЛНЫЕ настройки, включая пользовательские
НастройкиКомпоновкиДанных = КомпоновщикНастроек.ПолучитьНастройки(); 

// 3. Создаем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных; 

// 4. Генерируем макет именно для коллекции значений
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновки, НастройкиКомпоновкиДанных,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")); 

// 5. Инициализируем процессор компоновки
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных; 
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных); 

// 6. Выводим результат в ТЗ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений; 
ТЗ = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТЗ);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

Проверка структуры настроек СКД

Если после замены метода ПолучитьНастройки() таблица всё равно пустая, проанализируем структуру самой схемы компоновки. Для корректной выгрузки в ТаблицаЗначений необходимо соблюдение следующих условий:

  1. Наличие детальных записей: Перейдем на вкладку "Настройки" в СКД (даже если у вас две разных схемы в отчете). В иерархии группировок обязательно должен присутствовать элемент "Детальные записи". Если вместо них создана группировка, например, по полю Номенклатура, то процессор вывода может создать иерархическую структуру, которую сложнее интерпретировать в плоской таблице.
  2. Выбранные поля: Убедимся, что на уровне "Детальных записей" или на уровне всего отчета выбраны нужные поля. Если список выбранных полей пуст, в ТЗ не будет колонок (подробнее о ситуации, когда нет данных — нет столбцов, читайте в профильных материалах).
  3. Использование параметров: Если в запросе СКД используются параметры (например, &ВидыНоменклатуры), они должны быть отмечены как "Используемые" в пользовательских настройках. Если параметр обязателен, но не заполнен, запрос вернет пустой результат.

Особенности работы с запросами и типами данных

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

Если в ТЗ на форме вы планируете отображать результат, не забудьте вызвать метод СоздатьКолонки() для элемента формы, чтобы визуализировать программно полученные данные:


ЭлементыФормы.ВашаТаблицаНаФорме.Значение = ТЗ;
ЭлементыФормы.ВашаТаблицаНаФорме.СоздатьКолонки();

Дополнительные советы

Если вы работаете в толстом клиенте (обычные формы), помните, что КомпоновщикНастроек на форме инициализируется автоматически при открытии, если он связан с реквизитом. Однако если вы создаете компоновщик программно в коде, вам придется вручную загрузить в него схему и инициализировать настройки:


КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки));
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновки.НастройкиПоУмолчанию);

Подводя итог, можно сказать, что ключевым моментом является правильное "схлопывание" всех настроек в один объект. Использование КомпоновщикНастроек.ПолучитьНастройки() гарантирует, что все фильтры, которые пользователь кропотливо выставлял на форме, будут учтены при формировании запроса к базе данных, и вы получите именно тот результат, который ожидаете.

← На главную