Как объединить несколько макетов Word (Active Document) в один документ в 1С?

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

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

Способ 1. Объединение через буфер обмена (Copy / Paste)

Наиболее универсальный подход для произвольного (N-ного) количества страниц и макетов заключается в последовательном копировании содержимого каждого макета в базовый документ. Для этого открываем основной документ, а затем в цикле получаем очередной макет, копируем его содержимое в буфер обмена и вставляем в конец основного документа через разрыв страницы.

Рассмотрим пример реализации на встроенном языке 1С:


// Создаем экземпляр MS Word через COM
WordApp = Новый COMОбъект("Word.Application");
WordApp.Visible = Ложь;

Попытка
    // Создаем результирующий документ
    ИтоговыйДокумент = WordApp.Documents.Add();
    
    // Получаем массив нужных макетов в зависимости от условий
    СписокМакетов = Новый Массив;
    СписокМакетов.Добавить("Макет1");
    Если ТребуетсяВтораяСтраница Тогда
        СписокМакетов.Добавить("Макет2");
    КонецЕсли;
    
    wdCollapseEnd = 0;
    wdPageBreak   = 7;
    wdDoNotSaveChanges = 0;
    
    Для Индекс = 0 По СписокМакетов.Количество() - 1 Цикл
        ИмяМакета = СписокМакетов[Индекс];
        МакетОбъект = ПолучитьМакет(ИмяМакета);
        
        // Получаем временный COM-документ из макета
        ВременныйDoc = МакетОбъект.Получить();
        
        // Сначала выполняем автозамену параметров в изолированном макете
        Замена = ВременныйDoc.Content.Find;
        Замена.Execute("<Контрагент>", Ложь, Истина, Ложь, , , Истина, , Ложь, СокрЛП(СсылкаНаОбъект.Контрагент.НаименованиеПолное));
        
        Если Индекс > 0 Тогда
            // Переходим в конец итогового документа и вставляем разрыв страницы
            Диапазон = ИтоговыйДокумент.Content;
            Диапазон.Collapse(wdCollapseEnd);
            Диапазон.InsertBreak(wdPageBreak);
            Диапазон.Collapse(wdCollapseEnd);
        Иначе
            Диапазон = ИтоговыйДокумент.Content;
        КонецЕсли;
        
        // Копируем содержимое заполненного макета и вставляем в итоговый
        ВременныйDoc.Content.Copy();
        Диапазон.Paste();
        
        // Закрываем временный документ без сохранения
        ВременныйDoc.Close(wdDoNotSaveChanges);
    КонецЦикла;
    
    // Показываем готовый сформированный документ пользователю
    WordApp.Visible = Истина;
    WordApp.Activate();
    
Исключение
    WordApp.Quit(0);
    WordApp = Неопределено;
    ВызватьИсключение "Ошибка при формировании документа Word: " + ОписаниеОшибки();
КонецПопытки;

Способ 2. Объединение с помощью метода InsertFile

Второй вариант заключается в выгрузке каждого макета во временный файл на диск с последующей вставкой в результирующий документ через метод InsertFile объекта Range. Этот метод особенно удобен, когда макеты содержат сложные колонтитулы, таблицы или внедренную графику.

Разберем алгоритм по шагам:

  1. Выгружаем первый макет во временный файл через ПолучитьИмяВременногоФайла("docx") и открываем его как базовый документ.
  2. Заполняем реквизиты в первом документе через автозамену.
  3. Для каждого последующего макета сохраняем его во временный файл, открываем, производим замену параметров, сохраняем изменения и закрываем.
  4. В базовом документе смещаем курсор в конец с помощью Range.Collapse(0), добавляем разрыв страницы и вызываем Range.InsertFile(ИмяФайла).
  5. После завершения объединения удаляем временные файлы с диска с помощью процедуры УдалитьФайлы().

Способ 3. Использование составных макетов

Если вариантов вывода немного (например, строго «Страница 1», «Страница 2» или «Страница 1 + Страница 2»), самым простым и производительным решением будет подготовка трех готовых макетов:

  1. Макет1 — только первый лист;
  2. Макет2 — только второй лист;
  3. Макет_ОбаЛиста — двухстраничный документ с уже настроенными разрывами и форматированием.

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

Важные технические нюансы при работе с Word COM

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

  1. Ограничение длины строки в Find.Execute: Параметр ReplaceWith метода Execute ограничен длиной в 255 символов. Если реквизит (например, полный адрес или реквизиты договора) длиннее, возникнет ошибка COM-объекта. Для длинных строк безопаснее использовать закладки (Bookmarks) либо прямую замену текста найденного диапазона Range.Text.
  2. Разрыв страницы против разрыва раздела: Если разные макеты имеют разную ориентацию (например, первая страница книжная, а вторая альбомная) или различные поля, стандартный разрыв страницы wdPageBreak (значение 7) применит параметры первого листа ко всему документу. В этом случае необходимо использовать разрыв раздела с новой страницы: wdSectionBreakNextPage (значение 2).
  3. Очистка процессов WINWORD.EXE: Любое необработанное исключение оставляет фоновый процесс Word в оперативной памяти. Обязательно обрамляйте COM-вызовы в конструкцию Попытка ... Исключение, в блоке Исключение принудительно вызывайте WordApp.Quit(0) и очищайте переменную (WordApp = Неопределено).
  4. Клиент-серверное окружение: Технология ActiveDocument и COM-соединение с Word работают исключительно на клиенте под управлением ОС Windows с установленным пакетом MS Office. На сервере 1С под управлением Linux данный механизм не поддерживается.

Альтернатива: перевод на ТабличныйДокумент

Если печатную форму требуется формировать универсально (в веб-клиенте, на сервере или под Linux), рекомендуется перевести макет на стандартный ТабличныйДокумент 1С. В нем объединение листов выполняется штатным методом ТабличныйДокумент.ВывестиГоризонтальныйРазделительСтраниц(), а готовый результат можно сохранить в PDF или DOCX без использования внешних офисных приложений.

← На главную