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