При автоматизации документооборота в 1С часто возникает задача программного наложения печати или факсимиле на сформированный документ Microsoft Word. Типичная проблема, с которой сталкиваются разработчики при использовании COM-соединения: после программной вставки изображения и попытки установить режим обтекания «За текстом», картинка непредсказуемо «улетает» в самое начало документа. В этой статье мы подробно разберем, почему это происходит и как правильно управлять позиционированием графических объектов в Word.
Для начала проанализируем ситуацию. В объектной модели Word существует два основных типа графических объектов:
Когда мы используем метод AddPicture, Word по умолчанию создает объект InlineShape. Чтобы сделать его прозрачным для текста, мы должны преобразовать его в Shape с помощью метода ConvertToShape. Именно в этот момент чаще всего происходит сбой позиционирования, так как «свободная» фигура обязана иметь привязку (Anchor) к конкретному абзацу, и если координаты не заданы явно, Word сбрасывает их к значениям по умолчанию.
Рассмотрим стандартный подход к решению задачи. Нам необходимо найти в тексте определенный маркер (например, «М.П.» или строку подписи) и заменить его картинкой. Разберем программный код на стороне 1С:
// Создаем объект Word и открываем документ
Word = Новый COMОбъект("Word.Application");
Документ = Word.Documents.Open(ПутьКФайлу);
// Настраиваем поиск маркера в документе
Замена = Документ.Content.Find;
Замена.ClearFormatting();
Замена.Text = "[МестоПечати]"; // Строка-шаблон в документе
Если Замена.Execute() Тогда
// Получаем диапазон, где был найден текст
Область = Замена.Parent;
// Вставляем картинку как InlineShape
ИмяФайла = "C:\Temp\Stamp.png";
КартинкаИнлайн = Область.InlineShapes.AddPicture(ИмяФайла);
// Преобразуем во флотирующий объект Shape
КартинкаСвободная = КартинкаИнлайн.ConvertToShape();
// Устанавливаем режим обтекания "За текстом" (wdWrapBehind = 5)
КартинкаСвободная.WrapFormat.Type = 5;
КонецЕсли;
Основная причина резкого перемещения объекта при смене WrapFormat.Type заключается в смене системы координат. Как только объект становится Shape, он привязывается к ближайшему абзацу. Если в документе включен режим ограниченной функциональности (совместимость со старыми версиями .doc), движок отрисовки может некорректно обрабатывать привязки.
Чтобы гарантированно зафиксировать картинку в нужном месте, проанализируем свойства RelativeVerticalPosition и RelativeHorizontalPosition. Мы должны явно указать Word, что координаты картинки считаются относительно строки или абзаца, где находился маркер поиска.
Добавим уточняющие настройки позиционирования в наш код:
// После конвертации в Shape задаем привязки
КартинкаСвободная = КартинкаИнлайн.ConvertToShape();
// Устанавливаем вертикальную привязку к строке (wdRelativeVerticalPositionLine = 3)
// или к абзацу (wdRelativeVerticalPositionParagraph = 0)
КартинкаСвободная.RelativeVerticalPosition = 3;
КартинкаСвободная.Top = -20; // Смещение вверх относительно строки (подбирается опытным путем)
// Устанавливаем горизонтальную привязку (wdRelativeHorizontalPositionColumn = 2)
КартинкаСвободная.RelativeHorizontalPosition = 2;
КартинкаСвободная.Left = 0;
// Устанавливаем тип обтекания
КартинкаСвободная.WrapFormat.Type = 5;
// Запрещаем картинке "прыгать" при редактировании текста (фиксация привязки)
КартинкаСвободная.LockAnchor = Истина;
Иногда использование режима За текстом (Type = 5) вызывает сложности с выделением объекта мышкой в дальнейшем. Проанализируем другой подход: использование формата PNG с прозрачным фоном и режима Перед текстом (wdWrapFront = 4). В этом случае печать будет визуально накладываться на текст, не перекрывая его за счет прозрачности самого файла изображения.
Для реализации этого метода необходимо подготовить изображение печати в формате PNG-32 с альфа-каналом. Это позволит избежать белого прямоугольника вокруг оттиска.
Выясним еще одну важную причину странного поведения графики. Если ваш шаблон сохранен в старом формате Word 97-2003 (.doc), то современный Word открывает его в режиме совместимости. В этом режиме используются старые алгоритмы VML-графики, которые работают нестабильно через COM-соединение.
Рекомендация: Пересохраните шаблон документа в современный формат .docx. Это обновляет графический движок до стандарта DrawingML, где позиционирование Shapes работает значительно точнее и предсказуемее.
Если структура документа сложная, рассмотрим метод размещения маркера внутри ячейки таблицы. Таблицы в Word создают жесткий каркас, который ограничивает «полет» свободных фигур. Если поместить текст для поиска в ячейку таблицы с фиксированной высотой и шириной, то вставленный и преобразованный объект Shape будет привязан к этой ячейке и не сможет покинуть её пределы даже при смене режима обтекания.
WrapFormat.Type = 5 картинка останется внутри координат ячейки.В сложных документах, где уже есть другие подложки или фоновые изображения, полезно явно управлять слоем объекта. Используем метод ZOrder:
КартинкаСвободная.ZOrder(5); // msoSendBehindText — принудительно отправить за текст.
Это гарантирует, что печать не перекроет буквы, даже если настройки обтекания отработали не до конца корректно.
Рассмотрим более профессиональный способ определения места вставки. Вместо ненадежного поиска подстроки через Find.Execute, лучше заранее расставить в шаблоне закладки.
Преимущества работы с закладками:
Bookmarks работает быстрее.Область = Документ.Bookmarks("МестоПечати").Range;.Подведем итог: для успешного размещения картинки под текстом необходимо перевести документ в современный формат, преобразовать InlineShape в Shape, после чего обязательно задать свойства RelativeVerticalPosition и Top для компенсации автоматического сдвига координат.