Как выполнить поиск и замену текста в документе Word из 1С?

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

При формировании печатных форм договоров, коммерческих предложений или актов часто возникает необходимость заполнить готовый шаблон Microsoft Word данными из информационной базы 1С. Разберем основные способы реализации поиска и замены текстовых меток (тегов) через COM-соединение, рассмотрим особенности работы с колонтитулами и проанализируем частые ошибки при взаимодействии с офисными приложениями.

Вариант 1. Использование метода Range.Find (наиболее надежный способ)

Для стабильной работы программного кода рекомендуется выполнять поиск и замену не через курсор пользователя (Selection), а напрямую через диапазон документа (Range или Content). Это предотвращает сбои при потере документом фокуса или при работе в скрытом режиме.

Рассмотрим пример кода, открывающего внешний файл Word, выполняющего пакетную замену реквизитов и сохраняющего результат:


ИмяФайла = "C:\Work\Договор.docx";
НаименованиеКонтрагента = "ООО ""Торгуем всем""";
НомерДоговора = "№ 125/2026";

Попытка
    MSWord = Новый COMОбъект("Word.Application");
    MSWord.Visible = Ложь;
    MSWord.DisplayAlerts = 0; // Отключаем всплывающие предупреждения
    
    Документ = MSWord.Documents.Open(ИмяФайла);
    
    // Выполняем замену первого маркера в основном тексте
    Поиск = Документ.Content.Find;
    Поиск.ClearFormatting();
    Поиск.Replacement.ClearFormatting();
    
    // Параметры метода Execute:
    // Execute(FindText, MatchCase, MatchWholeWord, MatchWildcards, MatchSoundsLike, MatchAllWordForms, Forward, Wrap, Format, ReplaceWith, Replace)
    // Значение 2 в последнем параметре означает замену всех вхождений (wdReplaceAll)
    Поиск.Execute("[Контрагент]", Ложь, Истина, Ложь, , , Истина, 1, Ложь, НаименованиеКонтрагента, 2);
    
    // Замена следующего маркера
    Поиск.Execute("[НомерДоговора]", Ложь, Истина, Ложь, , , Истина, 1, Ложь, НомерДоговора, 2);
    
    Документ.Save();
    MSWord.Visible = Истина;
    MSWord.Activate();
Исключение
    Сообщить("Ошибка обработки документа Word: " + ОписаниеОшибки());
    Если Не MSWord = Неопределено Тогда
        MSWord.Quit();
    КонецЕсли;
КонецПопытки;

Если шаблон хранится в конфигурации как макет типа ActiveDocument или в виде файла шаблона (.dotx), алгоритм выглядит аналогично: мы создаем новый документ на основе шаблона методом Documents.Add и заполняем метки.

Вариант 2. Замена с явным указанием свойств объекта Selection

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


wrdApp = Новый COMОбъект("Word.Application");
wrdDoc = wrdApp.Documents.Open("C:\Work\Шаблон.docx");
wrdDoc.Activate();
wrdApp.Visible = Истина;

wrdApp.Selection.Find.ClearFormatting();
wrdApp.Selection.Find.Replacement.ClearFormatting();
wrdApp.Selection.Find.Text = "Contoso";
wrdApp.Selection.Find.Replacement.Text = "ООО ""Торгуем всем""";
wrdApp.Selection.Find.Forward = Истина;
wrdApp.Selection.Find.Wrap = 1; // wdFindContinue
wrdApp.Selection.Find.Format = Ложь;
wrdApp.Selection.Find.MatchCase = Ложь;
wrdApp.Selection.Find.MatchWholeWord = Ложь;
wrdApp.Selection.Find.MatchWildcards = Ложь;
wrdApp.Selection.Find.MatchSoundsLike = Ложь;
wrdApp.Selection.Find.MatchAllWordForms = Ложь;

// Вызов Execute без строковых параметров, так как они уже заполнены в свойствах
wrdApp.Selection.Find.Execute( , , , , , , , , , , 2);

wrdDoc.Save();

Вариант 3. Замена текста в колонтитулах документа

Свойство Документ.Content охватывает только основное тело документа. Если метки расположены в верхнем или нижнем колонтитуле, стандартный поиск их пропустит. Разберем, как обратиться к колонтитулам напрямую:


// Обращение к нижнему колонтитулу первой секции документа
Колонтитул = Документ.Sections(1).Footers(1); // 1 = wdHeaderFooterPrimary
ПоискВКолонтитуле = Колонтитул.Range.Find;
ПоискВКолонтитуле.ClearFormatting();
ПоискВКолонтитуле.Execute("[КолонтитулИнфо]", Ложь, Истина, Ложь, , , Истина, 1, Ложь, "Документ согласован", 2);

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


Для Каждого ДиапазонИстории Из Документ.StoryRanges Цикл
    Пока ДиапазонИстории <> Неопределено Цикл
        ДиапазонИстории.Find.Execute("[Метка]", Ложь, Истина, Ложь, , , Истина, 1, Ложь, "Значение", 2);
        // Переход к следующему связанному блоку (например, следующему колонтитулу)
        Попытка
            ДиапазонИстории = ДиапазонИстории.NextStoryRange;
        Исключение
            ДиапазонИстории = Неопределено;
        КонецПопытки;
    КонецЦикла;
КонецЦикла;

Важные нюансы и распространенные ошибки

  1. Ошибка «Microsoft Word: Данная команда недоступна»
    Часто возникает при использовании Selection.Find в новых версиях MS Office (2016, 2019, 2021), если окно Word свернуто, не активировано или находится в фоновом режиме. Для исправления переходите на использование диапазона: Документ.Range().Find или Документ.Content.Find. Также ошибка появляется, если файл заблокирован режимом «Защищенный просмотр» (Protected View) или при открытии появилось модальное системное окно.
  2. Ограничение длины строки поиска и замены в 255 символов
    Метод Find.Execute и свойство Replacement.Text не принимают значения длиннее 255 символов. Если необходимо вставить длинный фрагмент текста (например, подробные реквизиты, список номенклатуры или условия договора), разберем правильный алгоритм:
    
    // Ищем маркер без указания текста замены
    Поиск = Документ.Content.Find;
    Поиск.ClearFormatting();
    Если Поиск.Execute("[ДлинныйТекст]") Тогда
        // При успешном поиске сам диапазон схлопывается до найденного текста
        Поиск.Parent.Text = ТекстБолее255Символов;
    КонецЕсли;
    
  3. COM-соединение на стороне сервера 1С
    Инициализация COM-объектов MS Office на сервере 1С под управлением службы Windows официально не рекомендуется Microsoft: процессы WINWORD.EXE могут зависать в памяти и блокировать работу пользователей. Кроме того, COM-объекты не работают на серверах под Linux. При необходимости серверного формирования документов рекомендуется формировать файлы на клиенте либо использовать альтернативные механизмы (распаковка архива .docx через объекты ЧтениеZIPФайла и прямая модификация файла word/document.xml).
← На главную