Часто перед разработчиком стоит задача сформировать сложную печатную форму в формате MS Word, которая должна содержать множество повторяющихся страниц. Например, это могут быть трудовые договоры на несколько сотрудников, пакеты актов или спецификаций. Типичная ошибка новичка — получение макета внутри цикла, что приводит к открытию десятков отдельных окон Word вместо одного структурированного документа. В этой статье мы подробно разберем, как правильно организовать вывод данных в один файл, используя методы COM-объектов MS Word.
Рассмотрим ситуацию, с которой столкнулся автор темы. При использовании кода Макет.Получить() внутри цикла 1С каждый раз инициализирует новый экземпляр документа из двоичных данных макета. Поскольку метод Получить() для макета типа Active Document по сути создает новый временный файл и открывает его, мы получаем столько окон Word, сколько итераций в нашем цикле. Наша задача — изменить этот алгоритм так, чтобы создать один целевой документ и последовательно "наполнять" его содержимым нашего шаблона.
Для начала определим основные этапы правильного формирования документа. Нам потребуется вынести инициализацию COM-объекта за пределы цикла. Проанализируем алгоритм:
Word.Application.Одним из самых простых и надежных способов дублирования оформления является использование методов Copy и Paste. Давайте разберем программный код, который позволит это реализовать. Нам важно правильно управлять объектом Selection, который представляет собой текущее выделение или позицию курсора.
// 1. Инициализируем Word
Word = Новый COMОбъект("Word.Application");
Word.Visible = Ложь; // Скрываем работу Word для ускорения процесса
// 2. Получаем шаблон
Макет = ПолучитьМакет("Договор");
ШаблонДокумент = Макет.Получить(); // Открываем шаблон
// 3. Создаем результирующий документ
ДокументРезультат = Word.Documents.Add();
// 4. Подготавливаем содержимое шаблона для копирования
ШаблонДокумент.Content.Copy();
Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
// Переходим в конец результирующего документа
Word.Selection.EndKey(6); // 6 — это константа wdStory (переход в самый конец)
// Вставляем содержимое из буфера обмена
Word.Selection.Paste();
// 5. Замена параметров в текущем вставленном фрагменте
// Мы ищем уникальные метки, например {ФИО}, и заменяем их
Поиск = Word.Selection.Find;
Поиск.Execute("{ФИО}", Ложь, Истина, Ложь, , , Истина, 1, Ложь, СтрокаДанных.ФИО, 2);
// 6. Вставка разрыва страницы (кроме последней итерации)
Если НомерСтроки < ТаблицаДанных.Количество() Тогда
Word.Selection.InsertBreak(7); // 7 — это константа wdPageBreak
КонецЕсли;
КонецЦикла;
// Закрываем шаблон без сохранения изменений
ШаблонДокумент.Close(0);
// Делаем результат видимым пользователю
Word.Visible = Истина;
Word.Activate();
В процессе работы с Word через COM мы используем числовые значения констант VBA. Выясним, что означают основные из них:
EndKey для перемещения курсора в самый конец всего документа. Это критически важно, иначе каждая новая вставка будет затирать предыдущую или происходить в начале файла.InsertBreak. Позволяет принудительно начать новый раздел с новой страницы. Без этого текста макеты "склеятся" друг с другом.Execute, который указывает, что нужно заменить все вхождения искомой строки в выделенном фрагменте.Иногда использование буфера обмена может быть нежелательным (например, если пользователь в этот момент сам что-то копирует). В таких случаях проанализируем использование свойства FormattedText. Этот метод позволяет передать текст вместе со всем форматированием напрямую из одного диапазона (Range) в другой.
Рассмотрим, как это выглядит в коде:
// Вместо Paste() используем прямое присвоение форматированного текста
ТекущийДиапазон = ДокументРезультат.Content;
ТекущийДиапазон.Collapse(0); // Схлопываем диапазон к концу (wdCollapseEnd = 0)
ТекущийДиапазон.FormattedText = ШаблонДокумент.Content.FormattedText;
Этот способ работает быстрее и стабильнее, так как не задействует системный буфер обмена Windows.
Работа с MS Word через COM-соединение — процесс довольно ресурсозатратный. Чтобы пользователь не ждал слишком долго, придерживаемся следующих правил:
Word.Visible = Ложь в начале формирования и только в самом конце переключаем в Истина. Это отключает перерисовку интерфейса Word при каждой вставке текста.Range вместо Selection там, где это возможно. Объект Selection заставляет Word постоянно обновлять положение курсора на экране, что замедляет работу.При работе с внешними приложениями всегда существует риск сбоя (Word может быть не установлен, документ может быть заблокирован). Мы рекомендуем оборачивать инициализацию в конструкцию Попытка...Исключение.
Попытка
Word = Новый COMОбъект("Word.Application");
Исключение
Сообщить("Не удалось запустить MS Word. Проверьте, установлена ли программа.");
Возврат;
КонецПопытки;
Не забывайте также корректно завершать процессы. Если в середине формирования кода произошла ошибка, объект Word.Application может остаться "висеть" в памяти процессах Windows. Хорошим тоном считается закрытие всех служебных документов (шаблонов) сразу после того, как данные из них были считаны.
Таким образом, комбинируя методы работы с диапазонами текста и управление разрывами страниц, мы можем создавать профессиональные многостраничные отчеты в MS Word, сохраняя при этом высокую скорость работы и удобство для конечного пользователя.