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