В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача реализации печати документов или справочников непосредственно из формы списка. Стандартная подсистема печати БСП (Библиотека стандартных подсистем) по умолчанию ориентирована на работу с выделенными объектами (массив ссылок, передаваемый через параметры формы). Однако пользователи часто запрашивают возможность «напечатать всё, что я сейчас вижу в списке», не прибегая к ручному выделению всех строк через Ctrl+A.
В этой статье мы подробно разберем, как программно перехватить текущие настройки динамического списка (отборы, поиск, условия), сформировать на их основе запрос и получить полный список ссылок для последующей передачи в печатную форму.
Динамический список в управляемых формах — это сложный объект, который не хранит в себе все данные одновременно. Он подгружает их порциями для оптимизации скорости интерфейса. Поэтому мы не можем просто «прочитать» строки таблицы на форме. Чтобы получить все элементы, нам необходимо обратиться к источнику данных списка (его схеме компоновки данных) и применить к ней те же настройки, которые пользователь установил в интерфейсе.
Рассмотрим ситуацию: пользователь применил отбор по организации и периоду, а также воспользовался строкой поиска. Нам нужно получить массив всех ссылок, которые удовлетворяют этим условиям.
Проанализируем наиболее надежный метод, основанный на получении текущих настроек компоновщика. Для этого в коде формы (или в серверном модуле, куда передается объект списка) мы будем использовать метод ПолучитьИсполняемыеНастройкиКомпоновкиДанных().
Рассмотрим пошагово алгоритм реализации:
Ниже приведен пример кода, реализующий эту логику:
Процедура ПолучитьСсылкиВсехЭлементовСписка(Элементы, ИмяСписка)
// 1. Получаем динамический список из реквизитов формы
Список = ЭтаФорма[ИмяСписка];
// 2. Получаем исполняемые настройки (с учетом всех отборов и поиска)
НастройкиДС = Элементы[ИмяСписка].ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
// 3. Получаем схему компоновки данных самого списка
Схема = Элементы[ИмяСписка].ПолучитьИсполняемуюСхемуКомпоновкиДанных();
// Очищаем выбранные поля, чтобы получить только Ссылку
НастройкиДС.Выбор.Элементы.Очистить();
ВыбранноеПоле = НастройкиДС.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Ссылка");
ВыбранноеПоле.Использование = Истина;
// 4. Подготавливаем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, НастройкиДС, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
// 5. Инициализируем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , , Истина);
// 6. Выводим результат в таблицу значений
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТаблицаРезультат = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
ТаблицаРезультат = ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Теперь ТаблицаРезультат содержит колонку "Ссылка" со всеми объектами списка
МассивОбъектов = ТаблицаРезультат.ВыгрузитьКолонку("Ссылка");
// Далее передаем МассивОбъектов в менеджер печати БСП
КонецПроцедуры
Иногда требуется более тонкая настройка, например, если запрос динамического списка слишком сложен или содержит специфические объединения, которые могут замедлять работу при полной выборке. В этом случае мы можем создать в метаданных отдельную «Схему компоновки данных выбора ссылок», которая содержит только простейший запрос к основной таблице, и программно перенести в неё отборы из списка.
Рассмотрим пример функции для копирования элементов отбора, которая умеет работать с группами (И, ИЛИ, НЕ):
Процедура ПеренестиОтбор(ОтборПриемник, ОтборИсточник) Экспорт
Для Каждого ЭлементИсточник Из ОтборИсточник.Элементы Цикл
Если ТипЗнч(ЭлементИсточник) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
// Проверяем использование и корректность левого значения
Если ЭлементИсточник.Использование Тогда
НовыйЭлемент = ОтборПриемник.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЗаполнитьЗначенияСвойств(НовыйЭлемент, ЭлементИсточник);
КонецЕсли;
ИначеЕсли ТипЗнч(ЭлементИсточник) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
НоваяГруппа = ОтборПриемник.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
НоваяГруппа.ТипГруппы = ЭлементИсточник.ТипГруппы;
НоваяГруппа.Использование = ЭлементИсточник.Использование;
ПеренестиОтбор(НоваяГруппа, ЭлементИсточник);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот метод позволяет «наложить» фильтры динамического списка на любой другой запрос к той же таблице БД. Однако стоит помнить, что такой подход не учитывает полнотекстовый поиск, если он был активирован пользователем через стандартную панель поиска, так как данные поиска не всегда хранятся в коллекции Отбор компоновщика настроек.
При реализации печати «всех элементов» крайне важно проанализировать возможные риски, связанные с производительностью и стабильностью системы.
"В списке слишком много элементов. Пожалуйста, уточните отбор перед печатью".ДлительныеОперации. Это позволит интерфейсу оставаться отзывчивым, а пользователю видеть индикатор прогресса.ПолучитьИсполняемыеНастройкиКомпоновкиДанных() в современных версиях платформы 8.3 (начиная с 8.3.10+) корректно учитывает строку поиска. Если ваша конфигурация работает на более старых релизах, результаты поиска могут быть проигнорированы, и в печать попадут лишние документы.ДобавитьКомандыПечати вы можете указать параметр ДополнительныеПараметрыКоманды. Туда можно передать признак "ПечатьВсегоСписка". В серверном менеджере печати, если этот признак установлен, вызовите описанную выше логику получения ссылок вместо использования стандартного параметра ОбъектыПечати.Если задача подразумевает обработку по-настоящему больших массивов данных для печати, наиболее эффективным способом будет не передача массива ссылок между клиентом и сервером, а использование Временных Таблиц. Вы можете выполнить запрос на сервере, поместить ссылки во временную таблицу и передать в менеджер печати только идентификатор этой таблицы или структуру отборов. Это кардинально ускоряет работу подсистемы печати при пакетной обработке.
Выясним причину, почему разработчики часто выбирают Ctrl+A. Это самый простой путь, не требующий написания кода. Но для создания качественного и дружелюбного интерфейса, программное получение отборов является признаком высокого профессионализма разработчика и заботы о конечном пользователе.