Как передать параметр или реквизит формы во внешнюю печатную форму в 1С БСП

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

При разработке внешних печатных форм (ВПФ) на платформе «1С:Предприятие 8.3» с использованием Библиотеки стандартных подсистем (БСП) версии 3.x разработчики часто сталкиваются со следующей проблемой. Стандартный механизм печати жестко регламентирует состав параметров, передаваемых в менеджер печати на сервер. В процедуру Печать стандартно приходят только массив объектов, коллекция печатных форм, объекты печати и параметры вывода.

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

Причина сложности: архитектура подключаемых команд БСП

Прежде чем перейти к решениям, проанализируем, почему возникает эта сложность. Когда пользователь нажимает кнопку «Печать», срабатывает механизм подключаемых команд БСП:

ПодключаемыеКомандыКлиент.ВыполнитьКоманду(ЭтотОбъект, Команда, Объект);

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

Давайте рассмотрим, какими путями мы можем решить эту задачу.

---

Способ 1. Переопределение обработчика команды печати в форме документа (Рекомендуемый стандартный метод БСП)

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

Этот способ позволяет перехватить нажатие кнопки печати на клиенте, заполнить структуру дополнительных параметров значениями из формы и штатно передать их на сервер.

Разберем реализацию этого способа по шагам:

Шаг 1. Описание команды в модуле менеджера объекта

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


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

Шаг 2. Реализация обработчика в модуле формы документа

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


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

Шаг 3. Получение параметров на сервере в модуле ВПФ

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


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

---

Способ 2. Получение данных контекста формы-владельца напрямую в ВПФ (Без доработки конфигурации)

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

При регистрации ВПФ в функции СведенияОВнешнейОбработке мы указываем тип запуска команды как ВызовКлиентскогоМетода или ОткрытиеФормы. БСП при открытии формы ВПФ автоматически назначает форму документа ее владельцем.

Проанализируем, как в модуле формы ВПФ обратиться к данным родительской формы документа:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    // Проверяем, открыта ли ВПФ из формы документа
    Если Владелец <> Неопределено Тогда
        Попытка
            // Читаем реквизиты объекта формы-владельца напрямую
            ВыводитьАртикул = Владелец.Объект.ВыводитьАртикул;
            
            // Если данные не связаны с объектом, а находятся в элементах формы:
            ЗначениеЭлемента = Владелец.Элементы.ИмяЭлементаДекорации.Значение;
        Исключение
            // Обрабатываем исключение, если реквизиты отсутствуют
            ВыводитьАртикул = Ложь;
        КонецПопытки;
    КонецЕсли;
    
КонецПроцедуры

Этот способ автономен, безопасен и не требует изменения основного кода вашей информационной базы. В качестве основы реализации можно использовать пример внешней печатной формы для БСП 3.1.10.

---

Способ 3. Упаковка параметров в структуру «ОбъектыНазначения» (Классический метод обхода ограничений БСП)

Что делать, если в ВПФ есть своя форма настроек, мы собрали параметры на клиенте, но хотим вывести печать в стандартное окно предварительного просмотра БСП (ПечатьДокументов)?

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

Рассмотрим, как это реализовать:

Шаг 1. Формирование структуры на клиенте в форме настройки ВПФ


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

Шаг 2. Распаковка структуры в модуле объекта ВПФ на сервере

На стороне сервера в модуле объекта внешней обработки мы должны сделать проверку типа входящего аргумента. Если пришел не массив, а структура — извлекаем данные.


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

---

Способ 4. Перехват управления через глобальный переопределяемый модуль

Если вам требуется массово внедрить логику обработки параметров для целого ряда документов или внешних отчетов, в БСП существует специализированный общий модуль УправлениеПечатьюПереопределяемый. В нем расположена экспортная процедура ПередПечатью.

Синтаксис процедуры выглядит следующим образом:


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

Этот способ отлично подходит, когда параметры для печати можно вычислить на сервере по ссылкам документов, не передавая их напрямую с клиента.

---

Способ 5. Динамическое изменение таблицы команд (Обходной путь через временные таблицы БСП)

Выясним причину появления «костылей» в коде и разберем нестандартное решение, предложенное в обсуждении темы. При создании подключаемых команд БСП на клиенте генерируется служебная таблица, которая хранит информацию о командах в адресе временного хранилища: ПараметрыПодключаемыхКоманд.АдресТаблицыКоманд.

Разработчик может пойти на хитрость и динамически скорректировать эту таблицу прямо перед вызовом печати:


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

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

---

Резюме

Мы подробно проанализировали различные варианты решения проблемы передачи реквизитов формы в ВПФ. При выборе решения рекомендуем руководствоваться следующими правилами:

  1. Используйте Способ 1 (Обработчик в форме) во всех случаях, когда у вас есть доступ к изменению конфигурации или созданию расширений. Это штатный, наиболее надежный и поддерживаемый метод БСП.
  2. Используйте Способ 2 или 3, если конфигурация находится на строгой поддержке, а вся логика должна быть инкапсулирована исключительно внутри внешней печатной формы.
← На главную