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