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