Как заполнить макет Word в 1С 8.3 на сервере и объединить несколько шаблонов в один документ

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

Переход с платформы 1С 8.2 на 8.3 часто сопровождается трудностями при работе с офисными документами. Старые методы, основанные на типе макета ActiveDocument, перестают работать в клиент-серверном варианте, так как на сервере, как правило, не установлен Microsoft Office. В этой статье мы подробно разберем, как адаптировать формирование документов Word под современные требования платформы, используя двоичные данные, библиотеку стандартных подсистем (БСП) и COM-технологии на стороне клиента.

Почему старый метод с Active Document выдает ошибку

Рассмотрим ситуацию: при попытке выполнить код Договор.Получить() на сервере система выдает ошибку. Проанализируем причину. Метод Получить() для макета типа Active Document инициирует запуск соответствующего COM-сервера (в данном случае Word). Если код выполняется на сервере, 1С пытается найти установленный MS Word именно на серверной машине. Важно помнить: Microsoft официально не рекомендует устанавливать пакет Office на серверные операционные системы для автоматизации, и в 1С 8.3 это становится критической преградой.

Чтобы решить эту задачу, нам необходимо либо перенести формирование документа на сторону клиента, либо использовать методы, не требующие запуска приложения Word на сервере (например, работу с XML или двоичными данными).

Вариант 1. Формирование документа на клиенте через временный файл

Если вам необходимо сохранить привычную логику работы с объектом Word.Application, но база работает в режиме клиент-сервер, следует использовать следующий алгоритм. Мы получаем двоичные данные макета на сервере, передаем их на клиент, сохраняем во временный файл и открываем его через COM-объект.

Разберем пример кода. Сначала создадим функцию на сервере для получения макета:


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

Затем на клиенте выполним инициализацию документа:


&НаКлиенте
Процедура Печать_Договора()
    // Создаем COM-объект на клиенте, где установлен Word
    Попытка
        Word = Новый COMОбъект("Word.Application");
    Исключение
        Сообщить("Microsoft Word не установлен на данном компьютере.");
        Возврат;
    КонецПопытки;

    // Получаем двоичные данные макета с сервера
    ДвоичныеДанныеМакета = ПолучитьМакетСервер("МойМакетWord");
    
    // Создаем временный файл
    ИмяФайла = ПолучитьИмяВременногоФайла("docx");
    ДвоичныеДанныеМакета.Записать(ИмяФайла);
    
    // Открываем документ как шаблон
    ДокументWord = Word.Documents.Add(ИмяФайла);
    Word.Visible = Истина;
    ДокументWord.Activate();
    
    // Дальнейшее заполнение закладок или поиск и замена текста
    // ...
КонецПроцедуры

Вариант 2. Использование механизмов БСП (УправлениеПечатью)

Современный стандарт разработки в 1С предполагает использование подсистемы "Печать" из состава БСП. Этот метод более надежен и позволяет гибко управлять областями документа, аналогично тому, как мы работаем с табличными документами 1С. В этом случае макет хранится как Двоичные данные, но внутри него размещаются специальные теги в фигурных скобках, например {НомерДоговора}.

Для работы нам понадобятся методы модуля УправлениеПечатьюКлиент или УправлениеПечатью. Проанализируем процесс инициализации:


// Инициализация макета
Макет = УправлениеПечатьюКлиент.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета, "DOC", "МакетДоговора");

// Создание печатной формы
ПечатнаяФорма = УправлениеПечатьюКлиент.ИнициализироватьПечатнуюФорму("DOC", Неопределено, Макет);

// Получение области и заполнение параметров
Область = УправлениеПечатьюКлиент.ОбластьМакета(Макет, "Шапка");
ДанныеЗаполнения = Новый Структура("НомерДоговора, ДатаДоговора", "123", ТекущаяДата());
УправлениеПечатьюКлиент.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФорма, Область, ДанныеЗаполнения);

Этот подход позволяет избежать прямого обращения к методам COM-объекта в прикладном коде, перекладывая рутину на стандартные функции библиотеки.

Сложное объединение нескольких макетов в один документ

Часто возникает задача вставить один документ (например, приложение к договору) в середину другого. Если мы используем БСП, то можем вызывать метод ПрисоединитьОбласть последовательно. Рассмотрим, как это реализовать, если приложения хранятся в разных макетах:

  1. Создаем основной макет (тело договора).
  2. Создаем дополнительные макеты (варианты приложений).
  3. В коде поочередно инициализируем области из разных макетов и добавляем их в итоговый объект ПечатнаяФорма.

Проанализируем пример, когда нужно вставить специфический блок в зависимости от условий:


// Выводим основную часть
ОбластьШапка = УправлениеПечатью.ОбластьМакета(МакетОсновной, "Заголовок");
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФорма, ОбластьШапка, СтруктураДанных);

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

Манипуляция XML-структурой для продвинутых задач

В некоторых случаях стандартных средств БСП может быть недостаточно, особенно если требуется динамическое изменение структуры таблиц. Документ .docx представляет собой ZIP-архив с XML-файлами. Мы можем программно изменять содержимое word/document.xml.

Посмотрим на пример из практики, когда нужно дублировать блоки текста в зависимости от коллекции данных:


// Сохраняем исходный текст XML области макета
ИсходныйТекстОбласти = Область.Текст; 

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

Рекомендации по хранению и правке макетов

Для удобства пользователей рекомендуется отказаться от хранения жестко заданных макетов в конфигураторе. Рассмотрим более гибкий вариант:

Это позволит администраторам или юристам самостоятельно вносить правки в текст договоров, не привлекая программиста для изменения конфигурации. Кроме того, при использовании БСП и формата .docx, вы обеспечиваете частичную совместимость с Linux-серверами, так как работа с двоичными данными и XML не зависит от наличия COM-интерфейсов Windows.

Таким образом, переход на двоичные данные и механизмы БСП является наиболее правильным путем развития системы. Это не только решает проблему отсутствия Office на сервере, но и делает код более чистым и масштабируемым.

← На главную