При формировании печатных форм на базе шаблонов Microsoft Word через COM-соединение часто возникает ситуация, когда один и тот же параметр (например, <Город>, <НомерДоговора> или <ФИО>) встречается в тексте документа несколько раз. По умолчанию метод Find.Execute заменяет только первое найденное совпадение, из-за чего разработчикам приходится дублировать строки кода. Разберем, как настроить автоматическую замену всех дублирующихся тегов за один вызов, а также рассмотрим важные технические ограничения и альтернативные способы заполнения шаблонов.
Проанализируем работу метода Execute объекта Find в объектной модели Microsoft Word. У этого метода есть 11-й по счету параметр — Replace. По умолчанию этот параметр принимает значение wdReplaceNone (равное 0) или wdReplaceOne (равное 1), если значение не передано явно. В результате Microsoft Word находит первое вхождение подстроки, производит замену и прекращает поиск.
Чтобы выполнить сквозную замену всех найденных вхождений, необходимо передать константу wdReplaceAll, численное значение которой равно 2.
Посмотрим на пример вызова метода, где в качестве 11-го параметра передается значение 2:
// Получаем объект поиска по всему содержимому документа
Замена = ДокументMSW.Content.Find;
// Очищаем форматирование перед поиском (рекомендуемая практика)
Замена.ClearFormatting();
Замена.Replacement.ClearFormatting();
// Выполняем замену всех вхождений тега
// 11-й параметр = 2 (wdReplaceAll)
Замена.Execute(
"<Город>", // 1: FindText
Ложь, // 2: MatchCase
Истина, // 3: MatchWholeWord
Ложь, // 4: MatchWildcards
, // 5: MatchSoundsLike
, // 6: MatchAllWordForms
Истина, // 7: Forward
, // 8: Wrap
Ложь, // 9: Format
СсылкаНаОбъект.Город, // 10: ReplaceWith
2 // 11: Replace (2 = wdReplaceAll)
);
Рассмотрим подробнее позиционные параметры в методе Execute:
"<Город>").Ложь).Истина).Ложь).Истина).0 — не заменять (wdReplaceNone), 1 — заменить одно вхождение (wdReplaceOne), 2 — заменить все вхождения (wdReplaceAll).При использовании COM-объекта Word и метода Execute необходимо учитывать несколько критических особенностей:
ReplaceWith не может превышать 255 символов. Если передать более длинный текст, платформа 1С выбросит исключение «Слишком длинный строковый параметр». Чтобы обойти это ограничение, поиск выполняют без автозамены (Replace = 0), после чего найденному диапазону присваивают значение через свойство Range.Text = "ДлинныйТекст" в цикле.Find запоминает параметры предыдущих вызовов. Если ранее выполнялся поиск с выделением жирным или другим стилем, это может повлиять на последующие замены. Поэтому всегда вызывайте Замена.ClearFormatting() и Замена.Replacement.ClearFormatting() перед поиском.ДокументMSW.Content охватывает только основное тело документа. Теги, расположенные в верхних или нижних колонтитулах (Headers, Footers) или внутри графических блоков (Shapes), не будут заменены. Для них поиск нужно вызывать отдельно по соответствующим коллекциям.Word.Application работает только под Windows с установленным MS Office. На серверах 1С под Linux этот код работать не будет. Кроме того, запуск Word на сервере может приводить к зависанию процессов WINWORD.EXE.Если проект развивается или планируется переход на серверную печать документов, разберем более надежные архитектурные альтернативы COM-замене:
DOCVARIABLE "Город". В 1С значения устанавливаются одной строкой: ДокументMSW.Variables.Item("Город").Value = "Москва";, после чего вызывается метод ДокументMSW.Fields.Update();. Все одноименные поля в документе (включая колонтитулы) обновляются одновременно без ограничений на длину текста..docx является ZIP-архивом. С помощью объектов 1С ЧтениеZipФайла и ЗаписьZipФайла можно извлечь файл word/document.xml, выполнить быструю замену строк функцией СтрЗаменить() и упаковать файл обратно. Этот метод работает на любых серверах (включая Linux), не требует установленного MS Office и выполняется в десятки раз быстрее COM.