Как реализовать печать только выделенных строк табличной части во внешней печатной форме

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

При разработке внешних печатных форм (ВПФ) в среде 1С:Предприятие 8.3 часто возникает задача ограничить вывод данных только теми строками, которые пользователь выделил мышкой в табличной части документа. Стандартный механизм печати Библиотеки Стандартных Подсистем (БСП) обычно передает в печатную форму только ссылку на сам объект, что заставляет форму печатать все строки документа целиком. Разберем, как обойти это ограничение и реализовать выборочную печать, особенно на примере конфигурации ЗУП и шаблонов Word.

Анализ механизмов взаимодействия с формой

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

  1. Использование клиентского метода: Это наиболее гибкий способ. Мы регистрируем команду ВПФ как ВызовКлиентскогоМетода. В этом случае управление сначала передается в модуль формы внешней обработки, где нам доступен объект ВладелецФормы. Через него мы можем программно считать выделенные строки.
  2. Заполнение формы: Как упоминалось в обсуждении, этот вариант также позволяет получить доступ к родительской форме, но он чаще используется для заполнения данных, а не для вывода на печать.

Шаг 1. Регистрация внешней печатной формы

Рассмотрим структуру функции СведенияОВнешнейОбработке в модуле объекта. Чтобы мы могли перехватить выделенные строки на клиенте, нам нужно указать правильный тип команды. Выясним, как это выглядит в коде:


Функция СведенияОВнешнейОбработке() Экспорт
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
    
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидДополнительнойОбработкиПечатнаяФорма();
    ПараметрыРегистрации.Назначение.Добавить("Документ.ГрафикОтпусков");
    ПараметрыРегистрации.Наименование = "Печать выделенных строк (Word)";
    ПараметрыРегистрации.БезопасныйРежим = Ложь;
    
    НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
    НоваяКоманда.Представление = "Печать выделенных сотрудников (Word)";
    НоваяКоманда.Идентификатор = "ПечатьВыделенныхСтрок";
    НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
    НоваяКоманда.ПоказыватьОповещение = Истина;
    
    Возврат ПараметрыРегистрации;
КонецФункции

Обратите внимание на ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода(). Именно эта настройка позволит нам запустить код на стороне клиента перед тем, как данные уйдут на сервер для формирования Word-файла.

Шаг 2. Получение выделенных строк на клиенте

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

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


&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
    
    // ОбъектыНазначения[0] содержит ссылку на текущий документ
    СсылкаНаДокумент = ОбъектыНазначения[0];
    
    // Получаем доступ к форме документа
    ФормаДокумента = ВладелецФормы;
    
    // Массив для хранения идентификаторов строк
    МассивИдентификаторов = Новый Массив;
    
    Если ТипЗнч(ФормаДокумента) = Тип("УправляемаяФорма") Тогда
        // "Сотрудники" — это имя элемента Таблица на форме документа
        МассивИдентификаторов = ФормаДокумента.Элементы.Сотрудники.ВыделенныеСтроки;
    КонецЕсли;
    
    Если МассивИдентификаторов.Количество() = 0 Тогда
        ПоказатьПредупреждение(, "Пожалуйста, выделите хотя бы одну строку в таблице сотрудников!");
        Возврат;
    КонецЕсли;

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

Важный нюанс: свойство ВыделенныеСтроки возвращает массив внутренних идентификаторов строк формы. На сервере нам нужно будет сопоставить эти идентификаторы с данными табличной части объекта.

Шаг 3. Обработка данных на сервере и формирование Word-шаблона

Когда управление переходит в модуль объекта в процедуру Печать, нам становится доступна структура ПараметрыПечати. Проанализируем ситуацию: как нам использовать массив идентификаторов строк в запросе?

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


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

КонецПроцедуры

Особенности работы с шаблонами Word

Поскольку мы печатаем шаблон Word в ЗУП, разберем, как передать туда ограниченный список сотрудников. Обычно в Word-шаблонах используется механизм макетов, где данные заполняются через параметры или области. Для автоматизации серверной печати документов по шаблонам без использования MS Office на стороне сервера можно применить обработку для печати дополнительных соглашений из Word.

Проанализируем шаги работы с макетом:

  1. Получение макета: Используем ПолучитьМакет("ИмяМакета"). В случае Word это будет двоичный макет.
  2. Инициализация MS Word: Через COM-объект или встроенные средства БСП (рекомендуется).
  3. Цикл по отфильтрованной таблице: Мы проходим только по тем строкам, которые отобрали на предыдущем шаге. Если шаблон предусматривает список (например, список отпусков), мы создаем новые строки в таблице Word или копируем области.
  4. Заполнение параметров: Используем <code>Параметры.Вставить() для одиночных полей и механизмы группировки для списков.

Выясним, почему метод НайтиПоИдентификатору является ключевым. В управляемых формах ВыделенныеСтроки хранят именно числовые идентификаторы, которые привязаны к конкретному сеансу отображения данных. На сервере метод НайтиПоИдентификатору у табличной части объекта позволяет мгновенно получить нужную строку, не прибегая к медленному поиску по значениям полей.

Альтернативный подход: Передача ссылок

Рассмотрим еще один вариант, если вы не хотите полагаться на идентификаторы строк. На клиенте можно перебрать выделенные строки, извлечь из них ссылки на сотрудников и передать в ПараметрыПечати уже готовый массив ссылок.


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

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


ГДЕ
    ГрафикОтпусковСотрудники.Сотрудник В (&МассивСсылок)
    И ГрафикОтпусковСотрудники.Ссылка = &СсылкаНаДокумент

Заключение

Подведем итоги. Для реализации печати выделенных строк необходимо:

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

← На главную