Как вывести несколько табличных документов из модуля объекта в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке печатных форм, особенно внешних, программисты часто сталкиваются с ограничением: метод Показать() объекта ТабличныйДокумент работает только на клиенте. Если логика формирования документов находится в модуле объекта (который исполняется на сервере), прямой вызов окна просмотра невозможен. Ситуация усложняется, когда нужно вывести не один, а сразу несколько разных документов (например, комплекты документов по разным товарам). Рассмотрим подробнее, как решить эту задачу, сохранив структуру кода и обеспечив удобство пользователя.

Почему метод Показать() не работает в модуле объекта

Прежде чем переходить к решениям, проанализируем причину проблемы. Модуль объекта внешней обработки или документа выполняется на сервере. Серверная часть 1С ничего не знает об интерфейсе пользователя, окнах и экранных формах. Метод Показать() предназначен для визуализации данных в клиентском приложении. Следовательно, наша задача сводится к тому, чтобы сформировать данные на сервере, передать их на клиент и уже там инициировать открытие окон.

Решение 1: Сбор массива документов и вывод в цикле на клиенте

Это наиболее гибкий способ. Вместо того чтобы пытаться вызвать показ документа сразу, мы соберем все сформированные табличные документы в массив и вернем этот массив в вызывающую форму. Разберем этот процесс по шагам.

Шаг 1. Модификация серверной функции в модуле объекта

В модуле объекта создадим функцию, которая будет возвращать массив. Проанализируем пример кода:


Функция СформироватьПакетДокументов(МассивОбъектов) Экспорт
    МассивРезультатов = Новый Массив;
    
    Для каждого Ссылка Из МассивОбъектов Цикл
        ТабДок = Новый ТабличныйДокумент;
        // Здесь логика заполнения ТабДок (получение макета, вывод областей)
        // ...
        Область = Макет.ПолучитьОбласть("Заголовок");
        ТабДок.Вывести(Область);
        
        МассивРезультатов.Добавить(ТабДок);
    КонецЦикла;
    
    Возврат МассивРезультатов;
КонецФункции

Шаг 2. Вызов на стороне клиента

В модуле формы, откуда инициируется печать, мы принимаем этот массив и обходим его в цикле. Важно помнить, что ТабличныйДокумент является мутабельным типом, но его передача с сервера на клиент в пределах одного контекста вызова обычно разрешена.


&НаКлиенте
Процедура ВыполнитьПечать(Команда)
    РезультатПечати = ПолучитьДокументыНаСервере();
    
    Для каждого ТекущийДок Из РезультатПечати Цикл
        ТекущийДок.Показать("Печать: " + ТекущийДок.ИмяПараметровПечати);
    КонецЦикла;
КонецПроцедуры

&НаСервере
Функция ПолучитьДокументыНаСервере()
    ОбъектОбработка = РеквизитФормыВЗначение("Объект");
    Возврат ОбъектОбработка.СформироватьПакетДокументов(ОбъектыНазначения);
КонецФункции

Решение 2: Использование типа команды «Открытие формы» в БСП

Если ваша обработка подключается через БСП (Библиотека стандартных подсистем), стандартный механизм «Вызов серверного метода» ожидает заполнения коллекции печатных форм. Если мы хотим полностью контролировать процесс вывода, проанализируем вариант с изменением типа команды в функции СведенияОВнешнейОбработке.

Установим использование команды в значение ОткрытиеФормы. Это позволит системе при нажатии кнопки «Печать» не сразу бежать в модуль объекта, а открывать форму обработки. В этой форме мы можем автоматически запустить процесс формирования документов в процедуре ПриСозданииНаСервере или через обработчик ожидания на клиенте.

Для того чтобы форма знала, какие объекты печатать, БСП передает параметр ОбъектыНазначения. Посмотрим, как его извлечь:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Параметры.Свойство("ОбъектыНазначения") Тогда
        МассивСсылок = Параметры.ОбъектыНазначения;
        // Теперь у нас есть ссылки на документы, для которых вызвана печать
    КонецЕсли;
КонецПроцедуры

После получения ссылок мы вызываем серверный код формирования, получаем массив табличных документов и выводим их методом Показать() в цикле на клиенте, как в первом решении.

Решение 3: Пакет отображаемых документов (UX-подход)

Если документов очень много (например, 50), открытие 50 отдельных окон загромождает интерфейс и мешает пользователю. Выясним, как сделать это элегантнее с помощью объекта ПакетОтображаемыхДокументов. Этот объект позволяет показать один интерфейс, в котором слева будет список документов (оглавление), а справа — выбранный документ.

Рассмотрим пример формирования пакета:


&НаСервере
Функция СформироватьПакетДляПоказа()
    Пакет = Новый ПакетОтображаемыхДокументов;
    
    Для Каждого Стр Из ДанныеДляПечати Цикл
        ТабДок = СформироватьОдинДокумент(Стр);
        
        ЭлементПакета = Пакет.Состав.Добавить();
        ЭлементПакета.Данные = ПоместитьВоВременноеХранилище(ТабДок, УникальныйИдентификатор);
        ЭлементПакета.Наименование = "Документ №" + Стр.Номер;
    КонецЦикла;
    
    Возврат Пакет;
КонецФункции

На клиенте достаточно вызвать Пакет.Показать(). Это значительно повышает удобство работы пользователя, объединяя разрозненные документы в одну логическую сущность.

Важные рекомендации при работе с временным хранилищем

При передаче больших объемов данных (десятки тяжелых табличных документов с картинками и QR-кодами) рекомендуется использовать Временное хранилище. Вместо передачи массива объектов напрямую, поместим массив во временное хранилище на сервере, передадим на клиент адрес (строку), а на клиенте извлечем данные. Это снижает риск возникновения ошибок сериализации мутабельных значений и оптимизирует объем передаваемых данных между сервером и клиентом.

Резюме: для вывода нескольких документов из модуля объекта необходимо вынести стадию визуализации (метод Показать()) на сторону клиентского модуля формы, используя массив документов или специальный объект ПакетОтображаемыхДокументов.

← На главную