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