При формировании печатных форм договоров, соглашений и других объемных документов разработчики часто сталкиваются с двумя проблемами: обрезка текста и некорректный разрыв страниц в стандартном табличном документе, а также ошибки при попытке использовать шаблоны Microsoft Word (макеты типа ActiveDocument или двоичные данные) в механизмах Библиотеки стандартных подсистем (БСП).
Разберем подробно, почему возникают эти сложности и как правильно реализовать оба подхода в 1С.
Когда договор выводится в ТабличныйДокумент, динамическое заполнение параметров разной длины может приводить к тому, что подписи отрываются от основного текста, заголовки остаются внизу листа, а строки в объединенных ячейках обрезаются. Проанализируем правила, позволяющие сформировать аккуратный печатный документ.
Рассмотрим ключевые настройки, которые необходимо задать перед заполнением документа:
РазмещениеТекста = Переносить помещен в объединенную по горизонтали ячейку, платформа 1С не всегда может автоматически рассчитать высоту строки. В результате текст снизу обрезается. Для текстовых пунктов договора делайте одну широкую колонку без объединения.
ТабДокумент = Новый ТабличныйДокумент;
ТабДокумент.АвтоМасштаб = Истина;
ТабДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
ТабДокумент.ПолеСверху = 10;
ТабДокумент.ПолеСнизу = 10;
ТабДокумент.ПолеСлева = 20;
ТабДокумент.ПолеСправа = 10;
Для управления разрывами страниц воспользуемся методом ПроверитьВывод(). Этот метод проверяет, помещается ли массив переданных областей на текущую страницу с учетом ранее выведенного содержимого. Если блок не помещается, принудительно вставляется разделитель страниц.
Посмотрим на пример вывода разделов договора с контролем разрыва страниц:
Макет = ПолучитьМакет("МакетДоговора");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьРазделЗаголовок = Макет.ПолучитьОбласть("ЗаголовокРаздела");
ОбластьРазделТекст = Макет.ПолучитьОбласть("ТекстРаздела");
ОбластьПодписи = Макет.ПолучитьОбласть("Подписи");
ТабДокумент.Вывести(ОбластьШапка);
Для Каждого СтрРаздела Из ТаблицаРазделовДоговора Цикл
// Заполняем параметры областей
ОбластьРазделЗаголовок.Параметры.Заполнить(СтрРаздела);
ОбластьРазделТекст.Параметры.Заполнить(СтрРаздела);
// Проверяем, поместятся ли заголовок и текст раздела вместе
МассивПроверки = Новый Массив;
МассивПроверки.Добавить(ОбластьРазделЗаголовок);
МассивПроверки.Добавить(ОбластьРазделТекст);
Если НЕ ТабДокумент.ПроверитьВывод(МассивПроверки) Тогда
ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
ТабДокумент.Вывести(ОбластьРазделЗаголовок);
ТабДокумент.Вывести(ОбластьРазделТекст);
КонецЦикла;
// Проверяем вывод блока подписей, чтобы он не остался один на новой странице
МассивПодписи = Новый Массив;
МассивПодписи.Добавить(ОбластьПодписи);
Если НЕ ТабДокумент.ПроверитьВывод(МассивПодписи) Тогда
ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
ТабДокумент.Вывести(ОбластьПодписи);
Если договор имеет сложную текстовую структуру с плавающими абзацами и отступами, удобнее использовать документ Word (.doc или .docx). Однако при интеграции такой формы в типовую конфигурацию на базе БСП часто возникает ошибка: «Не сформирован табличный документ».
Выясним причину ошибки: процедура печати БСП УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию() жестко требует объект типа ТабличныйДокумент. Передача объекта ActiveDocument, COM-соединения или двоичных данных приводит к падению процедуры.
Кроме того, при работе с COM-объектом Word.Application действуют следующие ограничения:
СведенияОВнешнейОбработке() значение ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина); блокирует создание COM-объектов. Необходимо указывать Ложь.ВызовКлиентскогоМетода или ОткрытиеФормы, так как на сервере (особенно под 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();
КонецПроцедуры
Чтобы печать работала на сервере, в веб-клиенте и на операционных системах Linux без установленного Microsoft Office, шаблон договора в формате .docx загружают в макет как двоичные данные. Файл .docx представляет собой ZIP-архив, содержащий XML-структуру документа.
При формировании печатной формы выполняются следующие действия:
ЧтениеZipФайла во временный каталог.word/document.xml программно заменяются текстовые маркеры на значения реквизитов из базы 1С.ЗаписьZipФайла.