Печать в DOCX средствами БСП работает без COM-объекта Word и без установленного Office. Механизм «Работа с макетами офисных документов» в общем модуле УправлениеПечатью распаковывает шаблон DOCX, находит в нем размеченные области и параметры, заполняет их данными и собирает новый файл. Всё выполняется на сервере, поэтому подходит для сервера 1С на Linux.
Описание ниже — по БСП 3.1.9; механизм есть и в более ранних версиях, но сигнатуры процедур в вашей версии стоит сверить с комментариями в модуле. Работает только формат DOCX: старые DOC-файлы нужно пересохранить.
Зачем отказываться от COM
Классическая печать в Word через Новый COMОбъект("Word.Application") создает проблемы:
| Проблема COM | Как решает механизм БСП |
|---|---|
| Нужен Windows и установленный Office на сервере или клиенте | Работает на любой ОС сервера 1С |
Зависшие процессы WINWORD.EXE, утечки памяти | Нет внешнего процесса, только файлы и XML |
| Лицензирование Office на сервере | Office не нужен |
| Печать на клиенте недоступна в веб-клиенте | Файл формируется на сервере и отдается пользователю |
| Медленно на больших пакетах документов | Работа с XML заметно быстрее запуска приложения |
На переводах серверов 1С на Linux это одна из первых доработок, которые я делаю: все печатные формы через COM нужно либо переписать на табличный документ, либо перевести на механизм офисных макетов БСП.
Разметка шаблона DOCX
Шаблон делается в Word или любом редакторе, сохраняющем DOCX. Логика та же, что у табличного макета 1С: области и параметры.
Параметры. В тексте пишется {v8 ИмяПараметра}. При заполнении передается структура, где ключ — имя параметра. Значение приводится к строке функцией Строка(), поэтому даты, суммы и количества форматируйте сами до передачи. Параметр можно поставить и в адрес гиперссылки.
Форматирование параметра определяется по оформлению начала метки. Если метку копировали из другого документа или выделили цветом только часть, результат будет неожиданным. Проще всего перепечатать метку вручную с нужным шрифтом.
Области. Фрагмент шаблона заключается в метки:
{v8 Область.Шапка}
Договор № {v8 Номер} от {v8 Дата}
{/v8 Область.Шапка}Правила, которые лучше соблюдать с первого раза:
- метки начала и конца области — в основной части документа, не внутри таблицы;
- метки и содержимое области — на разных строках, иначе содержимое не распознается;
- вложенные области не поддерживаются: распознается только внешняя;
- для таблицы шапка и строка таблицы размечаются отдельными областями, строка выводится многократно;
- для многоуровневого списка заранее готовится отдельная область на каждый уровень;
- разрыв страницы — это отдельная область, внутри которой стоит только разрыв.
Колонтитулы размечать не нужно, они являются областями сами по себе и имеют фиксированные имена:
| Имя области | Когда появляется |
|---|---|
ВерхнийКолонтитул, НижнийКолонтитул | Всегда; при особом титульном — для остальных страниц, при четных/нечетных — для нечетных |
ВерхнийТитульныйКолонтитул, НижнийТитульныйКолонтитул | Включен «Особый колонтитул для первой страницы» |
ВерхнийЧетныйКолонтитул, НижнийЧетныйКолонтитул | Включены «Разные колонтитулы для четных и нечетных страниц» |
Даже в пустом документе разбор находит область Абзац — фактически перевод строки. Ее удобно использовать как разделитель.

Процедуры модуля УправлениеПечатью
| Процедура | Назначение |
|---|---|
ИнициализироватьМакетОфисногоДокумента | Разбирает двоичные данные DOCX в структуру макета |
ИнициализироватьПечатнуюФорму | Создает пустую печатную форму на основе макета |
ОбластьМакета | Получает область по имени и типу |
ПрисоединитьОбласть | Выводит область без заполнения |
ЗаполнитьПараметры | Заполняет параметры области или всей формы |
ПрисоединитьОбластьИЗаполнитьПараметры | Выводит и сразу заполняет область |
ПрисоединитьИЗаполнитьКоллекцию | Выводит область для каждого элемента массива структур (типы «СтрокаТаблицы» и «Список») |
ВставитьРазрывНаНовуюСтроку | Вставляет перевод строки |
СформироватьДокумент | Собирает DOCX и возвращает адрес во временном хранилище |
ОчиститьСсылки | Удаляет временные файлы макета или печатной формы |
Тип области при получении указывается явно: Общая, СтрокаТаблицы, Список или имя колонтитула.
У нескольких процедур есть устаревшие параметры с префиксом Удалить. Они не используются, но не везде имеют значение по умолчанию, поэтому их места при вызове нужно оставлять пустыми через запятые.
Код формирования печатной формы
Весь код выполняется на сервере. Ниже функция, которая формирует договор с таблицей товаров и возвращает адрес готового файла.
// Формирует печатную форму договора в формате DOCX.
//
// Параметры:
// ДвоичныеДанныеМакета - ДвоичныеДанные - шаблон DOCX.
// ДанныеДоговора - Структура - параметры шапки.
// Товары - Массив из Структура - строки таблицы.
//
// Возвращаемое значение:
// Строка, Неопределено - адрес DOCX во временном хранилище.
//
Функция СформироватьДоговорDOCX(ДвоичныеДанныеМакета, ДанныеДоговора, Товары) Экспорт
Макет = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета, , );
Если Макет = Неопределено Тогда
ОбщегоНазначения.СообщитьПользователю(НСтр("ru = 'Не удалось прочитать шаблон DOCX.'"));
Возврат Неопределено;
КонецЕсли;
ПечатнаяФорма = Неопределено;
АдресДокумента = Неопределено;
Попытка
ПечатнаяФорма = УправлениеПечатью.ИнициализироватьПечатнуюФорму(, , Макет);
ОбластьШапка = УправлениеПечатью.ОбластьМакета(Макет, ОписаниеОбласти("Шапка", "Общая"));
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФорма, ОбластьШапка, ДанныеДоговора, Ложь);
ОбластьШапкаТаблицы = УправлениеПечатью.ОбластьМакета(Макет, ОписаниеОбласти("ШапкаТаблицы", "Общая"));
УправлениеПечатью.ПрисоединитьОбласть(ПечатнаяФорма, ОбластьШапкаТаблицы, Ложь);
ОбластьСтрока = УправлениеПечатью.ОбластьМакета(Макет, ОписаниеОбласти("СтрокаТовара", "СтрокаТаблицы"));
УправлениеПечатью.ПрисоединитьИЗаполнитьКоллекцию(ПечатнаяФорма, ОбластьСтрока, Товары, Ложь);
ОбластьПодвал = УправлениеПечатью.ОбластьМакета(Макет, ОписаниеОбласти("Подписи", "Общая"));
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФорма, ОбластьПодвал, ДанныеДоговора, Ложь);
АдресДокумента = УправлениеПечатью.СформироватьДокумент(ПечатнаяФорма);
Исключение
ЗаписьЖурналаРегистрации(НСтр("ru = 'Печать DOCX'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ОбщегоНазначения.СообщитьПользователю(НСтр("ru = 'Ошибка формирования документа, подробности в журнале регистрации.'"));
КонецПопытки;
// Временные файлы удаляем в любом случае: и после успеха, и после ошибки.
Если ПечатнаяФорма <> Неопределено Тогда
УправлениеПечатью.ОчиститьСсылки(ПечатнаяФорма);
КонецЕсли;
УправлениеПечатью.ОчиститьСсылки(Макет);
Возврат АдресДокумента;
КонецФункции
Функция ОписаниеОбласти(ИмяОбласти, ТипОбласти)
Возврат Новый Структура("ИмяОбласти, ТипОбласти", ИмяОбласти, ТипОбласти);
КонецФункцииДанные для строк таблицы — массив структур, ключи которых совпадают с параметрами области:
Товары = Новый Массив;
Для Каждого СтрокаТовара Из Документ.Товары Цикл
Товары.Добавить(Новый Структура("НомерСтроки, Номенклатура, Количество, Сумма",
СтрокаТовара.НомерСтроки,
Строка(СтрокаТовара.Номенклатура),
Формат(СтрокаТовара.Количество, "ЧДЦ=3; ЧН=0"),
Формат(СтрокаТовара.Сумма, "ЧДЦ=2; ЧН=0,00")));
КонецЦикла;Шаблон удобнее хранить как макет типа «Двоичные данные» и получать через УправлениеПечатью.МакетПечатнойФормы("Документ.Договор.ПФ_DOCX_Договор"): тогда пользователь сможет заменить его на свой в списке макетов печатных форм, не трогая конфигурацию.
Заполнение области и вывод отдельно
ЗаполнитьПараметры и ПрисоединитьОбласть можно вызывать раздельно, например когда параметры одной области собираются из нескольких структур. Но есть ловушка: если заполнить параметры в самой области макета, повторно использовать ее с другими значениями не выйдет — метки уже заменены. Для повторяющихся областей используйте ПрисоединитьОбластьИЗаполнитьПараметры или ПрисоединитьИЗаполнитьКоллекцию: они сначала выводят копию области в форму, а потом заполняют.
Картинки в DOCX
Картинка выводится в параметр. Рабочий способ — передать структуру с адресом двоичных данных во временном хранилище и, по желанию, размерами:
ОписаниеКартинки = Новый Структура;
ОписаниеКартинки.Вставить("АдресКартинки", ПоместитьВоВременноеХранилище(ДвоичныеДанныеПечати, Новый УникальныйИдентификатор));
ОписаниеКартинки.Вставить("Ширина", 40);
// Высоту можно не задавать: она рассчитается пропорционально.
ОбластьПечать = УправлениеПечатью.ОбластьМакета(Макет, ОписаниеОбласти("Печать", "Общая"));
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФорма, ОбластьПечать,
Новый Структура("ОттискПечати", ОписаниеКартинки), Ложь);Если передать в параметр просто адрес из временного хранилища без структуры, в БСП 3.1.9 картинка не выводится: процедура заполнения распознает картинку, но не создает описание размеров. Всегда оборачивайте адрес в структуру.
Подключение к подсистеме «Печать»
Чтобы DOCX открывался из стандартного подменю «Печать», в процедуре Печать менеджера объекта положите адрес файла в коллекцию печатных форм:
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
Если Не УправлениеПечатью.НуженМакетПечатнойФормы(КоллекцияПечатныхФорм, "ДоговорDOCX") Тогда
Возврат;
КонецЕсли;
ДвоичныеДанныеМакета = УправлениеПечатью.МакетПечатнойФормы("Документ.Договор.ПФ_DOCX_Договор");
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ДоговорDOCX");
ПечатнаяФорма.ОфисныеДокументы = Новый Соответствие;
Для Каждого Договор Из МассивОбъектов Цикл
Адрес = СформироватьДоговорDOCX(ДвоичныеДанныеМакета, ДанныеШапки(Договор), ДанныеТоваров(Договор));
Если Адрес <> Неопределено Тогда
ПечатнаяФорма.ОфисныеДокументы.Вставить(Адрес, СтрШаблон("Договор %1", Договор.Номер));
КонецЕсли;
КонецЦикла;
КонецПроцедурыСостав колонок коллекции печатных форм зависит от версии БСП, поэтому сверьтесь с комментарием к УправлениеПечатьюПереопределяемый в вашей конфигурации. Если печать вызывается из собственной команды, адрес можно передать на клиент и отдать файл через НачатьПолучениеФайлаССервера: асинхронный вариант с диалогом работает и в веб-клиенте без расширения работы с файлами.
Типичные ошибки
- Область не находится. Метки начала и конца стоят на одной строке с текстом или внутри таблицы.
- Внутренняя область пустая. Области вложены друг в друга — разбор видит только внешнюю.
- Все строки таблицы одинаковые. Параметры заполнены в самой области макета, а затем она выводится в цикле.
- Даты с временем «00:00:00». Значения не отформатированы до передачи, сработал
Строка(). - На сервере копятся временные каталоги. Не вызван
ОчиститьСсылкипосле ошибки. Очистку делайте вне блокаПопытка, как в примере. - Ошибка при вызове процедуры. Пропущены позиции устаревших параметров
Удалить....
Печатные формы, в том числе перевод с COM на серверную генерацию при миграции на Linux, я делаю в рамках услуг печатные формы 1С и 1С на Linux и PostgreSQL.
Коротко
- Печать в DOCX средствами БСП не требует Word и работает на сервере под Linux.
- Шаблон размечается метками
{v8 Параметр}и парами{v8 Область.Имя}/{/v8 Область.Имя}, колонтитулы — готовые области. - Последовательность: инициализировать макет, создать печатную форму, вывести области, сформировать документ, очистить ссылки.
- Картинки передаются структурой с
АдресКартинки, а не голым адресом. - Временные файлы очищайте всегда, в том числе после ошибки.




