Как оптимизировать создание сложных печатных форм в формате Word и выбрать альтернативные методы в 1С?

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

При разработке сложных печатных форм в 1С программисты часто сталкиваются с необходимостью вывода данных в форматы офисных документов, таких как Word. Использование объектов COM для взаимодействия с Microsoft Word (Новый COMОбъект("Word.Application")) является одним из наиболее прямолинейных подходов, однако он обладает существенным недостатком – низкой производительностью. Для форм с большим количеством страниц, параметров или изображений время формирования может достигать нескольких минут, что неприемлемо для пользователей, ожидающих быструю работу программы.

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

1. Прямая работа с XML-структурой файлов Word (DOCX) без COM-объектов

Это один из наиболее производительных и гибких способов создания документов Word из 1С. Он позволяет полностью избежать запуска приложения Microsoft Word, что критически важно для серверных решений и обеспечения высокой скорости работы.

Как работает этот подход?

  1. DOCX как ZIP-архив: Файлы формата DOCX на самом деле представляют собой стандартные ZIP-архивы. Внутри такого архива хранятся XML-файлы, описывающие структуру, содержимое и форматирование документа, а также другие ресурсы, такие как изображения. Основное текстовое содержимое документа обычно находится в файле word/document.xml.
  2. Распаковка: На первом шаге мы распаковываем DOCX-файл, чтобы получить доступ к его внутренним XML-файлам. Для этого мы используем встроенные возможности 1С по работе с ZIP-архивами.
  3. Модификация XML: Далее мы читаем и модифицируем необходимые XML-файлы (прежде всего document.xml) с помощью объектов 1С для работы с XML (таких как ЧтениеXML, ПостроительDOM, ЗаписьDOM). На этом этапе происходит замена параметров, удаление ненужных элементов (например, закладок, строк таблиц), вставка изображений и другие манипуляции путем изменения узлов XML-дерева.
  4. Повторная упаковка: После всех изменений модифицированные файлы повторно упаковываются в новый DOCX-архив.

Преимущества метода:

Сложности метода:

Пример кода для прямой работы с XML:

Рассмотрим пошаговый пример реализации этого подхода в 1С:


// Шаг 1: Получаем двоичные данные макета Word
ДД = РеквизитФормыВЗначение("Объект").ПолучитьМакет(ИмяМакета);

// Шаг 2: Читаем двоичные данные в буфер и поток
Чтение = Новый ЧтениеДанных(ДД);
БуферДД = Чтение.ПрочитатьВБуферДвоичныхДанных();
Поток = Новый ПотокВПамяти(БуферДД);

// Шаг 3: Создаем временный каталог для распаковки
Каталог = КаталогВременныхФайлов() + "TempDocxProcessing";
СоздатьКаталог(Каталог);

// Шаг 4: Распаковываем ZIP-архив DOCX во временный каталог
ЗИП = Новый ЧтениеZipФайла(Поток);
ЗИП.ИзвлечьВсе(Каталог, РежимВосстановленияПутейФайловZIP.Восстанавливать);
ЗИП.Закрыть();
Поток.Закрыть();
Чтение.Закрыть();

// Шаг 5: Читаем основной XML-файл документа (word/document.xml)
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(Каталог + "\word\document.xml");

// Шаг 6: Строим DOM-дерево из XML для удобной навигации и модификации
Построитель = Новый ПостроительDOM;
Док = Построитель.Прочитать(ЧтениеXML);
ЧтениеXML.Закрыть();

// Шаг 7: Создаем разыменователь пространств имен для корректной работы с XPath
Разыменователь = Новый РазыменовательПространствИменDOM(Док);

// Шаг 8: Выполняем "магические заклинания" по замене параметров, удалению закладок и строк таблиц
// Здесь потребуется знание структуры WordprocessingML и использование XPath-выражений для поиска и модификации узлов.
// Например, для поиска текста:
// ВыражениеXPath = Док.СоздатьВыражениеXPath("//w:t[contains(text(), 'Параметр')]");
// Узлы = ВыражениеXPath.Вычислить(Док, Разыменователь);
// Для каждого УзелТекста Из Узлы Цикл
//     УзелТекста.ТекстовоеСодержимое = СтрЗаменить(УзелТекста.ТекстовоеСодержимое, "Параметр", "НовоеЗначение");
// КонецЦикла;

// Пример удаления закладки по имени (сложнее, так как закладки - это пара тегов w:bookmarkStart и w:bookmarkEnd)
// w:bookmarkStart и w:bookmarkEnd обычно являются дочерними элементами w:p (параграфа)
// Допустим, нам нужно удалить параграф, содержащий закладку 'УдаляемаяЗакладка'.
// ВыражениеXPath = Док.СоздатьВыражениеXPath("//w:bookmarkStart[@w:name='УдаляемаяЗакладка']/..");
// УзелПараграфаСЗакладкой = ВыражениеXPath.Вычислить(Док, Разыменователь).Получить(0);
// Если УзелПараграфаСЗакладкой <> Неопределено Тогда
//     УзелПараграфаСЗакладкой.Родитель.УдалитьДочерний(УзелПараграфаСЗакладкой);
// КонецЕсли;

// Шаг 9: Сохранение измененного DOM-дерева обратно в XML-файл
ЗаписьDOM = Новый ЗаписьDOM; 
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(Каталог + "\word\document.xml"); 
ЗаписьDOM.Записать(Док, ЗаписьXML); 
ЗаписьXML.Закрыть();

// Шаг 10: Повторная упаковка всех файлов во временном каталоге в новый ZIP-архив (DOCX)
Поток = Новый ПотокВПамяти();
ЗаписьZIP = Новый ЗаписьZipФайла(Поток,,,МетодСжатияZIP.Сжатие);                                  
ЗаписьZIP.Добавить(Каталог + "\*.*", РежимСохраненияПутейZIP.СохранятьОтносительныеПути, РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно); 
ЗаписьZIP.Записать();

// Шаг 11: Получаем двоичные данные готового DOCX-файла
ДД = Поток.ЗакрытьИПолучитьДвоичныеДанные();

// Шаг 12: Помещаем двоичные данные во временное хранилище (или сохраняем на диск)
АдресВременногоХранилища = ПоместитьВоВременноеХранилище(ДД, УникальныйИдентификатор);

// Шаг 13: Очищаем временный каталог
УдалитьФайлы(Каталог);

Использование БСП: Важно отметить, что в типовых конфигурациях 1С, использующих Библиотеку Стандартных Подсистем (БСП), существуют встроенные механизмы, которые значительно упрощают этот процесс. Функции из общих модулей типа УправлениеПечатью или ШаблоныПечатиОфисныхДокументов могут предоставлять готовые решения для заполнения DOCX-шаблонов без COM-объектов, что сокращает объем ручной работы и повышает надежность.

2. Табличный документ 1С (MXL) и "Форматированная строка"

Макеты в формате MXL являются нативным для 1С табличным документом, который во многом схож с электронной таблицей. Этот метод идеально подходит для создания большинства печатных форм в 1С.

Преимущества MXL:

Новые возможности "Форматированной строки" (с платформы 8.3.24+):

Исторически одной из главных сложностей MXL была невозможность применить различное форматирование к отдельным словам или символам внутри одной ячейки (например, сделать одно слово жирным, а другое — курсивом). Форматирование всегда применялось ко всей ячейке целиком. Однако, начиная с платформы 1С:Предприятие версии 8.3.24, появилась возможность использовать объект ФорматированнаяСтрока в ячейках табличного документа, в том числе и в макетах. Это открывает новые горизонты для создания сложных печатных форм:

Пример использования ФорматированнойСтроки:


// Создаем новый табличный документ
ТабДок = Новый ТабличныйДокумент;

// Создаем объект ФорматированнаяСтрока
ФорматированнаяСтрока = Новый ФорматированнаяСтрока;

// Добавляем текст с различным форматированием
// Первая часть - обычный текст
ФорматированнаяСтрока.Добавить("Это ");

// Вторая часть - жирный текст
ФорматированнаяСтрока.Добавить("очень важная", Новый ФорматТекста(Истина, Ложь, Ложь));

// Третья часть - курсив
ФорматированнаяСтрока.Добавить(" информация", Новый ФорматТекста(Ложь, Истина, Ложь));

// Четвертая часть - подчеркнутый текст
ФорматированнаяСтрока.Добавить(" для вас.", Новый ФорматТекста(Ложь, Ложь, Истина));

// Размещаем форматированную строку в ячейке табличного документа
Область = ТабДок.ПолучитьОбласть("R1C1");
Область.Текст = ФорматированнаяСтрока; // Теперь ячейка поддерживает сложное форматирование
ТабДок.Вывести(Область);

// Показываем табличный документ
ТабДок.Показать();

С помощью ФорматированнаяСтрока мы можем значительно улучшить внешний вид и читабельность MXL-форм, устраняя одно из давних ограничений табличного документа 1С.

3. Форматированный документ (встроенный объект 1С)

Объект ФорматированныйДокумент (FormattedDocument) — это внутренний объект 1С, предназначенный для работы с текстами, имеющими сложное форматирование, подобно тому, как это делается в Word, но непосредственно внутри интерфейса 1С.

Назначение и применение:

Сохранение и экспорт:

Сам объект ФорматированныйДокумент не сохраняется напрямую в файл в одном из стандартных офисных форматов. Однако его содержимое можно сохранить в ХранилищеЗначения для последующего восстановления или экспортировать в HTML/текстовый файл. Существуют подходы, позволяющие использовать HTML-представление ФорматированногоДокумента для последующей генерации Word-документа без COM-объектов, но это требует дополнительных шагов по конвертации.

4. Оптимизация использования шаблонов Word с закладками или полями DocVariable (через COM-объект)

Хотя этот метод признан самым медленным, в некоторых случаях он может быть единственно возможным, если требуется специфическая функциональность Microsoft Word, недоступная другими способами. Если вы вынуждены использовать COMОбъект("Word.Application"), мы можем предпринять шаги для минимальной оптимизации:

  1. Минимизация видимости: Самый простой способ немного ускорить работу — это скрыть окно приложения Word. Для этого установите свойство Visible объекта Word в Ложь (Word1C.Visible = Ложь;). Это не отменяет всех задержек, но визуально делает процесс менее "тяжелым" для пользователя.
  2. Работа с ActiveDocument: Если Word уже запущен или документ открыт, старайтесь работать с активным документом (Word1C.ActiveDocument) вместо того, чтобы каждый раз открывать новый, если это позволяет логика вашего решения.
  3. Группировка операций: По возможности группируйте операции. Вместо того чтобы вызывать COM-метод для каждого параметра по отдельности, старайтесь выполнить несколько замен или модификаций в рамках одной логической операции.

// Пример использования COM-объекта с минимальной оптимизацией
Попытка
    WordПриложение = Новый COMОбъект("Word.Application");
    WordПриложение.Visible = Ложь; // Скрываем окно Word
    
    ДокументWord = WordПриложение.Documents.Open("C:\Путь\К\Шаблону.docx");
    
    // Замена параметров через закладки (Bookmarks)
    Если ДокументWord.Bookmarks.Exists("НазваниеЗакладки") Тогда
        ДокументWord.Bookmarks("НазваниеЗакладки").Range.Text = "Новое значение";
    КонецЕсли;
    
    // Замена параметров через поля документа (DocVariables)
    // Необходимо, чтобы в шаблоне были созданы DocVariable
    // Или используйте Find.Replace для поиска и замены текста
    ДокументWord.Content.Find.Execute("<<Параметр1>>", Ложь, Ложь, Ложь, Ложь, Ложь, Истина, 1, Истина, "ЗначениеПараметра1", 2);
    
    // ... другие операции с документом
    
    ДокументWord.SaveAs("C:\Путь\К\ИтоговомуДокументу.docx");
    ДокументWord.Close();
    WordПриложение.Quit();
Исключение
    Сообщить("Ошибка при работе с Word: " + ОписаниеОшибки());
    Если WordПриложение <> Неопределено Тогда
        WordПриложение.Quit();
    КонецЕсли;
КонецПопытки;

Несмотря на эти оптимизации, основной минус — низкая скорость работы — остается, особенно при большом объеме данных или большом количестве заменяемых параметров, поскольку каждый вызов COM-метода требует взаимодействия с внешним приложением.

Заключение

Выбор оптимального метода для разработки сложных печатных форм в 1С критически важен для производительности и удобства пользователей. Мы должны анализировать конкретные требования и доступные возможности платформы:

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

← На главную