Как передать произвольные параметры во внешнюю печатную форму в УТ 10.3?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

При работе с конфигурацией «1С:Управление торговлей 10.3» (или аналогичными на обычных формах, такими как УПП 1.3) часто возникает задача передать специфические данные во внешнюю печатную форму (ВПФ). Классический пример — выбор конкретного руководителя или ответственного лица прямо перед печатью, когда эти данные не сохранены в самом документе. Рассмотрим, как реализовать это максимально корректно, не прибегая к изменению типовой конфигурации и избегая лишних записей в базу данных.

Анализ проблемы: почему стандартный подход не всегда удобен

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

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

  1. Блокировки базы данных: При одновременной работе нескольких пользователей запись в один и тот же элемент справочника вызовет ожидания на блокировках.
  2. Конфликты данных: Если два пользователя одновременно нажмут «Печать», один может перезаписать параметры другого, и в итоге оба получат документы с одинаковой подписью.
  3. Износ транзакционного лога: Постоянная запись в справочник неоправданно увеличивает объем логов и нагрузку на сервер.

Проанализируем более изящные способы решения этой задачи.

Решение 1: Передача параметров через структуру расшифровки

Давайте рассмотрим, как работает типовой механизм вызова печати. В УТ 10.3 при формировании списка доступных печатных форм создается дерево макетов. Каждая строка этого дерева содержит структуру Расшифровка. Именно эту структуру функция УниверсальныеМеханизмы.НапечататьВнешнююФорму использует для инициализации обработки.

Разберем, как можно «вклиниться» в этот процесс. Если вы вызываете печать из своей собственной обработки или формы, вы можете подготовить структуру параметров и передать её напрямую в механизм печати, минуя запись в справочник. Посмотрим на пример кода:


// 1. Подготавливаем структуру с нашими данными
НашиПараметры = Новый Структура;
НашиПараметры.Вставить("Руководитель", ВыбРуководитель);
НашиПараметры.Вставить("ГлавныйБухгалтер", ВыбГлавБух);

// 2. Получаем стандартное дерево макетов для документа
ДеревоМакетов = УниверсальныеМеханизмы.ПолучитьДеревоМакетовПечати(СсылкаНаДокумент, Неопределено);

// 3. Находим нужную нам внешнюю форму в дереве по наименованию
СтрокаВПФ = ДеревоМакетов.Строки.Найти("Счет-фактура (внешняя)", "Текст");
Если СтрокаВПФ <> Неопределено Тогда
    Расшифровка = СтрокаВПФ.Расшифровка;
    
    // В типовых конфигурациях Расшифровка — это структура.
    // Мы можем напрямую добавить в неё наши параметры, если подправим вызов 
    // или используем особенности типового кода.
    Расшифровка.Вставить("ДополнительныеПараметрыОбработки", НашиПараметры);
    
    // 4. Вызываем печать
    ТабДок = УниверсальныеМеханизмы.НапечататьВнешнююФорму(СсылкаНаДокумент, Расшифровка);
    УниверсальныеМеханизмы.НапечататьДокумент(ТабДок);
КонецЕсли;

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

Решение 2: Использование Хранилища общих настроек

Если по каким-то причинам модификация структуры расшифровки кажется сложной, рассмотрим метод с использованием ХранилищаОбщихНастроек. Этот способ хорош тем, что он позволяет изолировать данные разных пользователей.

Суть метода: перед вызовом печати мы сохраняем структуру параметров в хранилище под уникальным ключом (например, включая имя пользователя), а внутри ВПФ — считываем её. Проанализируем реализацию:

Код в форме вызова печати:


КлючНастроек = "ПечатьВПФ_Параметры_" + ИмяПользователя();
СтруктураПараметров = Новый Структура("Руководитель", ВыбранноеФизЛицо);
ХранилищеОбщихНастроек.Сохранить("ПараметрыПечатиПодписантов", КлючНастроек, СтруктураПараметров);

// Далее вызываем штатную печать

Код внутри внешней печатной формы (функция Печать):


Функция Печать() Экспорт
    КлючНастроек = "ПечатьВПФ_Параметры_" + ИмяПользователя();
    ПараметрыИзХранилища = ХранилищеОбщихНастроек.Загрузить("ПараметрыПечатиПодписантов", КлючНастроек);
    
    Руководитель = Справочники.ФизическиеЛица.ПустаяСсылка();
    Если ТипЗнч(ПараметрыИзХранилища) = Тип("Структура") Тогда
        Руководитель = ПараметрыИзХранилища.Руководитель;
    КонецЕсли;
    
    // ... логика формирования макета ...
    
    // После использования желательно очистить хранилище
    ХранилищеОбщихНастроек.Удалить("ПараметрыПечатиПодписантов", КлючНастроек);
КонецФункции

Этот метод считается более «кошерным», чем перезапись справочника, так как ХранилищеОбщихНастроек оптимизировано для работы с пользовательскими данными и не вызывает тяжелых блокировок всей таблицы справочника.

Решение 3: Прямое подключение внешней обработки (наиболее надежное)

Если вы хотите полностью контролировать процесс передачи данных, мы рекомендуем отказаться от использования УниверсальныеМеханизмы.НапечататьВнешнююФорму в пользу прямого программного подключения .epf файла. Рассмотрим этот процесс по шагам.

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


// Получаем объект внешней обработки из справочника
СсылкаНаВПФ = Справочники.ВнешниеОбработки.НайтиПоНаименованию("Счет-фактура");
ДвоичныеДанные = СсылкаНаВПФ.ХранилищеВнешнейОбработки.Получить();

// Создаем временный файл
ИмяФайла = ПолучитьИмяВременногоФайла("epf");
ДвоичныеДанные.Записать(ИмяФайла);

// Подключаем и создаем объект
ОбработкаОбъект = ВнешниеОбработки.Создать(ИмяФайла);
ОбработкаОбъект.СсылкаНаОбъект = СсылкаНаДокумент;

// ПРЯМАЯ ПЕРЕДАЧА ПАРАМЕТРА
// Предположим, в ВПФ есть экспортная переменная или реквизит "ДопПараметры"
ОбработкаОбъект.ДополнительныеПараметры = МояСтруктураСРуководителем;

// Вызываем печать
ТабДок = ОбработкаОбъект.Печать();

// Удаляем временный файл
УдалитьФайлы(ИмяФайла);

ТабДок.Показать();

Преимущества данного метода:

Подведем итоги

Мы проанализировали три основных подхода к передаче параметров во внешнюю печатную форму для УТ 10.3. Выбор конкретного метода зависит от ваших архитектурных предпочтений:

  1. Если вы хотите максимально использовать типовой код УниверсальныеМеханизмы, используйте подмену структуры Расшифровка.
  2. Если вам нужно простое и быстрое решение, работающее «из коробки» без изменения вызовов типовых функций, используйте ХранилищеОбщихНастроек.
  3. Если вы пишете свою систему печати или сложную обработку, используйте прямое создание объекта ВПФ и инициализацию его реквизитов перед вызовом функции Печать().

Помните, что использование ХранилищаЗначения внутри справочника с последующей перезаписью (Объект.Записать()) — это крайняя мера, которую стоит избегать в многопользовательской среде.

← На главную