Как вывести параметры в объекты «Надпись» (Shapes) документа Word из 1С?

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

При формировании печатных форм в формате Microsoft Word программисты 1С часто сталкиваются с ситуацией, когда стандартный механизм поиска и замены текста (через объект Content.Find) успешно обрабатывает основной массив текста, но полностью игнорирует данные, находящиеся внутри специальных объектов — «Надписей» (Text Boxes). Это происходит потому, что в объектной модели Word «Надписи» относятся к коллекции Shapes, которая существует отдельно от основного текстового слоя (Content).

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

Метод 1: Использование коллекции Shapes и прямое обращение к тексту

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

Рассмотрим пример кода, который автоматизирует этот процесс:


// Инициализация приложения Word
мWord = Новый COMОбъект("Word.Application");
мWord.Visible = Ложь; // Скрываем окно для ускорения работы

// Открытие шаблона
мДок = мWord.Documents.Add(ПутьКШаблону);

// Получаем количество фигур в документе
КоличФигур = мДок.Shapes.Count;

Для й = 1 По КоличФигур Цикл
    мДокФигура = мДок.Shapes.Item(й);
    
    // Проверяем, есть ли у фигуры текстовая рамка
    Попытка
        Если мДокФигура.TextFrame.HasText <> 0 Тогда
            // Получаем доступ к диапазону текста внутри надписи
            ТекстНадписи = мДокФигура.TextFrame.TextRange.Text;
            
            // Выполняем замену параметров
            // Обратите внимание: прямая замена через .Text может сбросить форматирование
            мДокФигура.TextFrame.TextRange.Text = СтрЗаменить(ТекстНадписи, "[НомерДКП]", НомерДок);
            мДокФигура.TextFrame.TextRange.Text = СтрЗаменить(мДокФигура.TextFrame.TextRange.Text, "[Дата]", Формат(ДатаДок, "ДЛФ=DD"));
        КонецЕсли;
    Исключение
        // Фигура может не поддерживать TextFrame (например, линия или простая картинка)
        Продолжить;
    КонецПопытки;
КонецЦикла;

мWord.Visible = Истина; // Показываем результат пользователю

Проанализируем этот код. Мы используем свойство HasText, чтобы убедиться, что фигура является контейнером для текста. Основной недостаток прямого присваивания TextRange.Text = "Новый текст" заключается в том, что если внутри надписи часть слов была выделена жирным шрифтом или имела другой цвет, это оформление может быть утеряно. Чтобы этого избежать, рекомендуется использовать метод Find.Execute непосредственно к объекту TextRange надписи.

Метод 2: Поиск и замена с сохранением форматирования

Для того чтобы сохранить стили оформления внутри надписи, мы применим метод Execute к диапазону текста фигуры. Это позволит заменить только вхождение строкового маркера, не затрагивая параметры шрифта остального содержимого.

Рассмотрим улучшенный алгоритм:


Для й = 1 По мДок.Shapes.Count Цикл
    мДокФигура = мДок.Shapes.Item(й);
    Попытка
        RangeНадписи = мДокФигура.TextFrame.TextRange;
        
        // Настройка параметров поиска внутри конкретной надписи
        RangeНадписи.Find.Execute("[НомерДКП]", , , , , , , , , НомерДок, 2); // 2 = wdReplaceAll
        RangeНадписи.Find.Execute("[Дата]", , , , , , , , , Формат(ДатаДок, "ДЛФ=DD"), 2);
    Исключение
        // Пропускаем фигуры без текста
    КонецПопытки;
КонецЦикла;

В данном примере использование метода Execute гарантирует, что структура документа останется неизменной, а замена произойдет максимально корректно.

Метод 3: Работа со сгруппированными фигурами

Часто дизайнеры шаблонов группируют надписи с логотипами или другими элементами оформления. В этом случае цикл по мДок.Shapes не увидит вложенные надписи, так как группа для Word — это один объект типа msoGroup.

Выясним, как обработать такие ситуации. Нам потребуется проверить свойство Type объекта Shape. Если тип соответствует значению 6 (группа), необходимо запустить вложенный цикл по коллекции GroupItems.


Процедура ОбработатьФигуры(КоллекцияФигур)
    Для Каждого Фигура Из КоллекцияФигур Цикл
        Если Фигура.Type = 6 Тогда // msoGroup
            ОбработатьФигуры(Фигура.GroupItems);
        Иначе
            Попытка
                Если Фигура.TextFrame.HasText <> 0 Тогда
                    Фигура.TextFrame.TextRange.Find.Execute("[Параметр]", , , , , , , , , "Значение", 2);
                КонецЕсли;
            Исключение
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

Метод 4: Использование закладок (Bookmarks)

Если структура вашего документа стабильна, вместо перебора всех фигур можно использовать механизм «Закладок». Выделите текст внутри надписи в Word, перейдите в меню «Вставка» -> «Закладка» и присвойте ей уникальное имя (например, ИмяКлиента).

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


Если мДок.Bookmarks.Exists("ИмяКлиента") Тогда
    мДок.Bookmarks.Item("ИмяКлиента").Range.Text = КонтрагентНазвание;
КонецЕсли;

Важный нюанс: при записи текста в Range.Text закладки, сама закладка в Word удаляется (заменяется текстом). Если вам нужно повторное заполнение, придется программно пересоздавать закладку вокруг вставленного текста.

Проблема «съезжающих» надписей при росте таблиц

Посмотрим на ситуацию, описанную в сообщении №16 форума: при заполнении табличной части данными, текст в Word смещается вниз, и «Надписи» начинают перекрывать текст или уезжать за границы страницы. Это происходит из-за неправильной привязки (Anchor) объекта Shape.

Чтобы избежать этой проблемы, проанализируем настройки привязки в Word:

  1. Нажмите правой кнопкой мыши на рамку надписи.
  2. Выберите «Размер и положение».
  3. На вкладке «Положение» убедитесь, что объект привязан к странице (по вертикали и горизонтали), а не к абзацу, если вам нужно фиксированное положение.
  4. Если надпись должна двигаться вместе с определенным текстом, используйте привязку к абзацу, но следите за тем, чтобы «Якорь» стоял в нужном месте.

Альтернатива: Работа через XML (DOCX как ZIP)

Для высоконагруженных систем или серверов, где не установлен Microsoft Office, использование COMObject невозможно. В этом случае документ .docx рассматривается как ZIP-архив, содержащий XML-файлы. Текст надписей обычно хранится внутри word/document.xml в тегах <w:txbxContent>.

Хотя этот метод значительно сложнее в реализации (требует парсинга XML), он работает в десятки раз быстрее и не зависит от внешних приложений. Однако для простых задач автоматизации в 1С «Обычные формы» COM-соединение остается наиболее доступным и гибким инструментом.

Подводя итог, можно сказать, что работа с надписями в Word из 1С требует более детального подхода, чем работа с обычным текстом. Использование коллекции Shapes, проверка TextFrame и правильная обработка групп объектов позволяют создавать профессионально оформленные документы любой сложности.

← На главную