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