Как из 1С вставить текстовое поле на каждую страницу документа Word через COM-соединение?

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

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

В данной статье мы разберем, как реализовать эту задачу с помощью COM-соединения (OLE) между 1С и MS Word, рассмотрим способы навигации по страницам и выясним, как правильно позиционировать элементы, чтобы они не «разваливали» текст.

Инициализация подключения и открытие документа

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

Рассмотрим пример инициализации:


// Создаем объект приложения Word
Попытка
    WordApp = Новый COMОбъект("Word.Application");
Исключение
    Сообщить("MS Word не установлен на данном компьютере!");
    Возврат;
КонецПопытки;

// Отключаем видимость и обновление экрана для ускорения
WordApp.Visible = Ложь;
WordApp.ScreenUpdating = Ложь;

// Открываем документ
Документ = WordApp.Documents.Open(ПутьКФайлу);

Как точно определить количество страниц в документе

Проблема многих разработчиков заключается в том, что свойство Information(3) (текущая страница) часто возвращает 1, если документ только что открыт и Word еще не успел выполнить фоновую разметку (pagination). Чтобы получить актуальные данные, мы должны принудительно заставить Word пересчитать страницы.

Проанализируем метод ComputeStatistics, который позволяет получить точное количество страниц:


// Принудительно обновляем разметку документа
Документ.Repaginate();

// Получаем количество страниц (константа 2 соответствует wdStatisticPages)
КоличествоСтраниц = Документ.ComputeStatistics(2);
Сообщить("Всего страниц для обработки: " + КоличествоСтраниц);

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

Алгоритм перебора страниц и навигации

Для того чтобы вставить объект именно на нужную страницу, нам нужно переместить курсор (объект Selection) в начало каждой страницы. Рассмотрим использование метода GoTo, который является наиболее надежным способом перемещения внутри COM-модели Word.

Для вызова GoTo нам понадобятся числовые значения констант VBA:


Для НомерСтраницы = 1 По КоличествоСтраниц Цикл
    // Перемещаем курсор на начало текущей страницы
    WordApp.Selection.GoTo(1, 1, НомерСтраницы);
    
    // Здесь будет код вставки объекта
    // ...
КонецЦикла;

Вставка текстового поля (Shape) с обтеканием

Вместо использования сложных "Строительных блоков" (Building Blocks), которые зависят от версии и языка Office (например, "Simple Text Box" против "Простая надпись"), мы воспользуемся методом прямого создания объекта Shapes.AddTextbox. Это гарантирует работоспособность кода в любой локализации Word.

Разберем параметры вставки: нам нужно задать координаты (отступ слева и сверху), ширину и высоту поля. Чтобы надпись была "прозрачной" для основного текста и находилась поверх него, мы настроим параметры обтекания.


// Настраиваем параметры вставки (в пунктах, 1 см ≈ 28.35 пунктов)
ОтступСлева = 400; // Позиция по горизонтали
ОтступСверху = 700; // Позиция по вертикали
Ширина = 150;
Высота = 50;

// Вставляем текстовое поле
Надпись = Документ.Shapes.AddTextbox(1, ОтступСлева, ОтступСверху, Ширина, Высота);

// Устанавливаем текст и форматирование
Надпись.TextFrame.TextRange.Text = "Штамп: ОДОБРЕНО";
Надпись.TextFrame.TextRange.Font.Size = 10;
Надпись.TextFrame.TextRange.Font.Name = "Arial";

// Настраиваем обтекание (5 - перед текстом, 3 - сквозь текст)
Надпись.WrapFormat.Type = 5; 

// Устанавливаем относительное позиционирование, чтобы поле не "уплыло"
Надпись.RelativeHorizontalPosition = 1; // Относительно страницы
Надпись.RelativeVerticalPosition = 1;   // Относительно страницы

Альтернативное решение: Использование колонтитулов

Если задача состоит в том, чтобы одна и та же надпись отображалась на каждой странице в одном и том же месте, перебор всех страниц в цикле через COM — не самый эффективный путь. Работа через OLE происходит медленно из-за межпроцессного взаимодействия. Проанализируем более быстрый вариант — использование колонтитулов (Header/Footer).

Преимущество: Объект, вставленный в колонтитул с абсолютным позиционированием, визуально может находиться в любой части страницы, но при этом Word будет отрисовывать его автоматически на каждом листе без необходимости цикла.


// Работаем с первым разделом документа
Раздел = Документ.Sections(1);

// Получаем основной колонтитул
Колонтитул = Раздел.Headers(1); // 1 - wdHeaderFooterPrimary

// Вставляем поле прямо в диапазон колонтитула
Надпись = Колонтитул.Shapes.AddTextbox(1, 450, 750, 100, 30);
Надпись.TextFrame.TextRange.Text = "Экземпляр №1";

// Если в документе включены разные колонтитулы для первой страницы
Если Раздел.PageSetup.DifferentFirstPageHeaderFooter Тогда
    КолонтитулПервой = Раздел.Headers(2); // wdHeaderFooterFirstPage
    // Дублируем вставку для первой страницы
КонецЕсли;

Оптимизация и завершение работы

После завершения всех манипуляций крайне важно вернуть настройки приложения в исходное состояние и корректно закрыть соединение, чтобы процесс WINWORD.EXE не остался "висеть" в памяти сервера или клиентского ПК.

  1. Включаем отрисовку: WordApp.ScreenUpdating = Истина;
  2. Сохраняем документ: Документ.Save(); или Документ.SaveAs(НовыйПуть);
  3. Закрываем приложение: WordApp.Quit();
  4. Освобождаем переменные: Присваиваем Неопределено всем COM-объектам.

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

Используя предложенные методы (ComputeStatistics для расчета страниц и Shapes.AddTextbox для вставки), вы сможете надежно управлять структурой документа Word из 1С, создавая профессиональные печатные формы с необходимыми элементами маркировки.

← На главную