Как из внешней обработки распечатать выбранный договор в 1С?

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

При разработке внешних обработок в среде 1С:Предприятие 8.3 на управляемых формах часто возникает задача организации печати различных объектов. Типичный пример: на форме внешней обработки присутствует реквизит Договор (ссылка на справочник договоров контрагентов), и нам необходимо по нажатию кнопки отправить этот договор на печать так, как если бы пользователь открыл сам элемент и нажал стандартную кнопку печати.

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

Анализ неверного подхода: почему код с форума использовать нельзя?

На форумах часто можно встретить "быстрое" решение, подобное коду ниже:


&НаКлиенте
Процедура КомандаПечатиНеверно(Команда)
    ПараметрыФормы = Новый Структура("Ключ", Объект.Договор);
    ФормаДоговора = ПолучитьФорму("Справочник.ДоговорыКонтрагентов.ФормаОбъекта", ПараметрыФормы);
    УправлениеПечатьюКлиент.ВыполнитьПодключаемуюКомандуПечати(ФормаДоговора.Команды.Найти("ГруппаВажныеКомандыКомандаПечати0"), ФормаДоговора, ФормаДоговора.Объект);
КонецПроцедуры

Давайте проанализируем ситуацию и разберем по шагам, почему этот код является крайне некачественным и опасным для использования в реальных базах данных:

  1. Крайне низкая производительность. Функция ПолучитьФорму заставляет платформу полностью смоделировать и инициализировать форму объекта на сервере. При этом срабатывают все тяжелые процедуры модуля формы, такие как ПриСозданииНаСервере, ПриЧтенииНаСервере, заполняются динамические списки, выполняются проверки прав доступа. Все это генерирует огромный бесполезный трафик между клиентом и сервером и перегружает систему ради одного действия — получения имени печатной формы.
  2. Нестабильность при обновлениях (хрупкость кода). Поиск команды по жестко прописанному имени вида "ГруппаВажныеКомандыКомандаПечати0" завязан на порядок генерации команд платформой. Как только фирма 1С выпустит очередное обновление конфигурации или в справочник добавится новая стандартная команда печати, этот индекс изменится. В результате ваша внешняя обработка мгновенно сломается, выдавая критическую ошибку пользователям.
  3. Блокировки и интерфейсные артефакты. Неявное открытие и закрытие форм в памяти может приводить к неожиданному поведению интерфейса и лишним транзакциям чтения данных.

Для решения этой задачи в современных конфигурациях 1С (таких как Бухгалтерия предприятия, ERP, Комплексная автоматизация, Управление торговлей) используется подсистема "Печать" из состава БСП. Рассмотрим правильные варианты интеграции.

Решение №1: Прямой вызов команды печати БСП на клиенте (Рекомендуемый способ)

Если нам требуется просто открыть стандартное окно предпросмотра печати 1С, нам абсолютно не нужно получать форму договора. Мы можем напрямую обратиться к глобальному клиентскому модулю БСП УправлениеПечатьюКлиент и передать ему ссылку на наш договор.

Давайте посмотрим на пример реализации команды на управляемой форме нашей внешней обработки:


&НаКлиенте
Процедура РаспечататьДоговор(Команда)

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

    // 2. Механизмы БСП всегда ожидают массив объектов для печати, даже если объект один
    МассивДоговоров = Новый Массив;
    МассивДоговоров.Добавить(Объект.Договор);

    // 3. Задаем параметры менеджера печати и идентификатор команды.
    // Классический менеджер для договоров — это сам справочник договоров.
    ИмяМенеджераПечати = "Справочник.ДоговорыКонтрагентов";
    
    // Имя макета (идентификатор) берется из модуля менеджера этого справочника.
    // Обычно для договоров это "Договор" или "ДоговорКонтрагента".
    ИменаМакетов = "Договор";

    // 4. Вызываем процедуру БСП, которая сделает всю работу за нас
    УправлениеПечатьюКлиент.ВыполнитьКомандуПечати(
        ИмяМенеджераПечати,
        ИменаМакетов,
        МассивДоговоров,
        ЭтотОбъект
    );

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

Как это работает? Метод УправлениеПечатьюКлиент.ВыполнитьКомандуПечати самостоятельно обращается к серверу, вызывает процедуру печати из менеджера справочника договоров, формирует табличный документ и открывает стандартную форму "Печать документов", где пользователь может отредактировать документ, отправить его на принтер или сохранить в PDF/Excel.

Важное примечание: Чтобы узнать точное имя макета (переменная ИменаМакетов), откройте конфигуратор вашей базы данных, найдите справочник ДоговорыКонтрагентов (или аналогичный), откройте его Модуль менеджера и найдите процедуру ДобавитьКомандыПечати. В ней вы увидите строчки настройки команд печати, где будет указан точный текстовый идентификатор макета.

Решение №2: Формирование табличного документа на сервере (Без открытия диалоговых окон)

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

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


&НаСервере
Функция ПолучитьТабличныйДокументДоговораНаСервере()

    // Подготавливаем массив со ссылкой на наш договор
    МассивДоговоров = Новый Массив;
    МассивДоговоров.Добавить(Объект.Договор);

    // Идентификатор макета, который мы хотим получить
    ИдентификаторМакета = "Договор";

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

    // Вызываем процедуру "Печать" непосредственно из менеджера справочника
    Справочники.ДоговорыКонтрагентов.Печать(
        МассивДоговоров,
        ПараметрыПечати,
        КоллекцияПечатныхФорм,
        ОбъектыПечати,
        ПараметрыВывода
    );

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

    Возврат Неопределено;

КонецФункции

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

Этот способ работает невероятно быстро, поскольку не требует инициализации интерфейсных окон и форм. Мы напрямую работаем со слоем бизнес-логики нашей конфигурации.

Особенности печати договоров по шаблонам Microsoft Word и OpenOffice

Очень часто в современных конфигурациях договоры хранятся и выводятся не в виде классических таблиц 1С (формат .mxl), а в виде офисных шаблонов (файлы .docx или .odt), в которых расставлены специальные теги для замены данных (например, {ИмяПартнера}, {НомерДоговора} и т.д.).

Если в вашей конфигурации используется именно такой механизм, то Решение №1 по-прежнему будет работать идеально! Общие модули БСП под капотом сами определят тип макета, выполнят COM-соединение или внутреннее чтение zip-архива документа, заменят все теги на реальные реквизиты договора из базы и откроют заполненный файл Word на компьютере пользователя.

Если же вы используете Решение №2 на сервере для таких шаблонов, помните, что серверные методы печати БСП для файлов docx/odt вернут вам не стандартный ТабличныйДокумент, а двоичные данные готового файла. Их вы сможете сохранить на диск сервера или передать на клиент для открытия во внешнем текстовом редакторе.

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

← На главную