Как настроить корректный вывод многостраничного договора на печать и подключить шаблон Word в 1С

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

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

Разберем подробно, почему возникают эти сложности и как правильно реализовать оба подхода в 1С.

Вариант 1. Корректная верстка и контроль страниц в Табличном документе

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

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

  1. Отказ от объединения ячеек по горизонтали для многострочного текста. Если длинный текст с включенным свойством РазмещениеТекста = Переносить помещен в объединенную по горизонтали ячейку, платформа 1С не всегда может автоматически рассчитать высоту строки. В результате текст снизу обрезается. Для текстовых пунктов договора делайте одну широкую колонку без объединения.
  2. Фиксация параметров страницы. Чтобы разбивка на страницы при формировании соответствовала реальной печати на принтере, зададим свойства документа программно:

ТабДокумент = Новый ТабличныйДокумент;
ТабДокумент.АвтоМасштаб = Истина;
ТабДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДокумент.ПолеСверху = 10;
ТабДокумент.ПолеСнизу  = 10;
ТабДокумент.ПолеСлева  = 20;
ТабДокумент.ПолеСправа = 10;

Для управления разрывами страниц воспользуемся методом ПроверитьВывод(). Этот метод проверяет, помещается ли массив переданных областей на текущую страницу с учетом ранее выведенного содержимого. Если блок не помещается, принудительно вставляется разделитель страниц.

Посмотрим на пример вывода разделов договора с контролем разрыва страниц:


Макет = ПолучитьМакет("МакетДоговора");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьРазделЗаголовок = Макет.ПолучитьОбласть("ЗаголовокРаздела");
ОбластьРазделТекст = Макет.ПолучитьОбласть("ТекстРаздела");
ОбластьПодписи = Макет.ПолучитьОбласть("Подписи");

ТабДокумент.Вывести(ОбластьШапка);

Для Каждого СтрРаздела Из ТаблицаРазделовДоговора Цикл
    // Заполняем параметры областей
    ОбластьРазделЗаголовок.Параметры.Заполнить(СтрРаздела);
    ОбластьРазделТекст.Параметры.Заполнить(СтрРаздела);
    
    // Проверяем, поместятся ли заголовок и текст раздела вместе
    МассивПроверки = Новый Массив;
    МассивПроверки.Добавить(ОбластьРазделЗаголовок);
    МассивПроверки.Добавить(ОбластьРазделТекст);
    
    Если НЕ ТабДокумент.ПроверитьВывод(МассивПроверки) Тогда
        ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЕсли;
    
    ТабДокумент.Вывести(ОбластьРазделЗаголовок);
    ТабДокумент.Вывести(ОбластьРазделТекст);
КонецЦикла;

// Проверяем вывод блока подписей, чтобы он не остался один на новой странице
МассивПодписи = Новый Массив;
МассивПодписи.Добавить(ОбластьПодписи);
Если НЕ ТабДокумент.ПроверитьВывод(МассивПодписи) Тогда
    ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
ТабДокумент.Вывести(ОбластьПодписи);

Вариант 2. Использование шаблонов Microsoft Word в виде внешней печатной формы (ВПФ)

Если договор имеет сложную текстовую структуру с плавающими абзацами и отступами, удобнее использовать документ Word (.doc или .docx). Однако при интеграции такой формы в типовую конфигурацию на базе БСП часто возникает ошибка: «Не сформирован табличный документ».

Выясним причину ошибки: процедура печати БСП УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию() жестко требует объект типа ТабличныйДокумент. Передача объекта ActiveDocument, COM-соединения или двоичных данных приводит к падению процедуры.

Кроме того, при работе с COM-объектом Word.Application действуют следующие ограничения:

  1. Безопасный режим: В функции СведенияОВнешнейОбработке() значение ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина); блокирует создание COM-объектов. Необходимо указывать Ложь.
  2. Клиентский контекст: Вызов COM-объекта Word должен выполняться на стороне клиента через команду с типом вызова ВызовКлиентскогоМетода или ОткрытиеФормы, так как на сервере (особенно под Linux или 64-битной ОС без установленного MS Office) создание COM-объекта завершится ошибкой.

Разберем по шагам, как зарегистрировать команду печати документа Word в БСП:


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

Рассмотрим заполнение шаблона Word через COM-объект на клиенте:


&НаКлиенте
Процедура Печать(МассивОбъектов, ВладелецФормы) Экспорт
    ДанныеДляЗаполнения = ПолучитьДанныеДоговора(МассивОбъектов);
    
    Попытка
        WordApp = Новый COMОбъект("Word.Application");
    Исключение
        Предупреждение("Не удалось инициализировать Microsoft Word на клиенте!");
        Возврат;
    КонецПопытки;
    
    // Получаем макет из двоичных данных и сохраняем во временный файл
    ДвоичныеДанныеМакета = ПолучитьДвоичныеДанныеМакета();
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");
    ДвоичныеДанныеМакета.Записать(ИмяВременногоФайла);
    
    ДокументWord = WordApp.Documents.Open(ИмяВременногоФайла);
    
    // Замена маркеров в тексте
    Для Каждого КлючИЗначение Из ДанныеДляЗаполнения Цикл
        Замена = ДокументWord.Content.Find;
        Замена.Execute("[" + КлючИЗначение.Ключ + "]", Ложь, Истина, Ложь, , , Истина, 1, Ложь, Строка(КлючИЗначение.Значение), 2);
    КонецЦикла;
    
    WordApp.Visible = Истина;
    WordApp.Activate();
КонецПроцедуры

Альтернативный вариант: формирование DOCX без использования COM-объектов

Чтобы печать работала на сервере, в веб-клиенте и на операционных системах Linux без установленного Microsoft Office, шаблон договора в формате .docx загружают в макет как двоичные данные. Файл .docx представляет собой ZIP-архив, содержащий XML-структуру документа.

При формировании печатной формы выполняются следующие действия:

  1. Архив распаковывается с помощью объекта ЧтениеZipФайла во временный каталог.
  2. В файле word/document.xml программно заменяются текстовые маркеры на значения реквизитов из базы 1С.
  3. Файлы упаковываются обратно с помощью ЗаписьZipФайла.
  4. Готовый файл отправляется пользователю или сохраняется в присоединенные файлы объекта.
← На главную