Как сохранить форматирование и размер шрифта при заполнении таблицы Word из 1С через буфер обмена?

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

При автоматизации формирования печатных форм и отчетов через COM-соединение с Microsoft Word разработчики нередко сталкиваются с проблемой: посимвольное или поячеечное заполнение таблицы занимает слишком много времени. Чтобы ускорить процесс, часто применяют групповую вставку строки данных через системный буфер обмена, разделяя значения символами табуляции. Однако при таком подходе возникает неприятный эффект — вставляемый текст сбрасывает заданный в шаблоне кегль (например, шрифт с 8,5 пунктов меняется на стандартный 12 pt), из-за чего разметка таблицы «плывет» и шаблон деформируется. Разберем причины такого поведения и рассмотрим надежные способы решения этой задачи.

Почему при вставке из буфера сбивается размер шрифта

Проанализируем механику работы Microsoft Word и COM-объекта:

  1. Игнорирование пользовательских настроек программы при вызове COM: параметры Word («Параметры — Дополнительно — Вырезание, копирование и вставка»), где указано «Сохранять только текст», влияют исключительно на действия пользователя в графическом интерфейсе. Метод COM-объекта Selection.Paste выполняет базовую системную вставку и не считывает эти флаги.
  2. Сброс локального форматирования ячеек: при передаче строки в формате обычного текста без тегов разметки Word не получает данных о стиле оформления. Если форматирование ячеек в шаблоне было задано вручную (прямое форматирование символов), при замене содержимого ячейки Word автоматически сбрасывает его до параметров базового стиля документа «Обычный» (Normal), в котором кегль по умолчанию обычно равен 11 или 12 пунктам.

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


Процедура ЗаполнитьПоКлеточкам(ОбъектВорд, ТекстПоиска, Строка) Экспорт
    Если ОбъектВорд.Bookmarks.Exists(ТекстПоиска) = True Тогда
        Закладка = ОбъектВорд.Bookmarks(ТекстПоиска);
        Закладка.Select;
    Иначе
        Возврат;
    КонецЕсли;

    Если Закладка.Column = Истина Тогда
        КолвоКлеточек = Закладка.Range.Columns.Count;
        ТекстДляВставки = СформироватьТекстДЛяВставкиСтроки(КолвоКлеточек, Строка);
        ОтправитьВБуфер(ТекстДляВставки);
        ОбъектВорд.Application.Selection.Paste;
    Иначе
        Таблица = ОбъектВорд.Application.Selection.Tables(1);
        СтолбцыТаб = Таблица.Columns.Count;
        СтрокиТаб = Таблица.Rows.Count;
        МассивСтрокДляВставки = СформироватьМассивСтрок(СтолбцыТаб, СтрокиТаб, Строка);
        Для ш = 0 По МассивСтрокДляВставки.Количество() - 1 Цикл
            ТекстДляВставки = МассивСтрокДляВставки[ш];
            СтрокаТаб = Таблица.Rows(ш + 1).Select;
            ОтправитьВБуфер(ТекстДляВставки);
            ОбъектВорд.Application.Selection.Paste;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Решение 1. Включение опции «Вписывать текст» в свойствах ячеек шаблона

Выясним самый простой способ обойти проблему без существенного изменения программного кода 1С. Если жесткие требования к кеглю шрифта отсутствуют, а ключевая задача — исключить деформацию границ таблицы и смещение полей, настроим шаблон Word:

  1. Выделим проблемную таблицу или целевые ячейки в файле шаблона.
  2. Откроем Свойства таблицы и перейдем на вкладку Ячейка.
  3. Нажмем кнопку Параметры....
  4. Установим флаг Вписывать текст.

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

Решение 2. Программное восстановление размера шрифта одной командой

Если визуального сжатия недостаточно и требуется строго заданный размер шрифта (например, 8,5 pt), восстановим размер программно. Перебирать каждую ячейку в цикле не нужно — достаточно выполнить форматирование всего диапазона за один COM-вызов сразу после вставки. Это действие выполняется практически мгновенно.

Рассмотрим, как изменить фрагмент кода в цикле вставки строк:


Для ш = 0 По МассивСтрокДляВставки.Количество() - 1 Цикл
    ТекстДляВставки = МассивСтрокДляВставки[ш];
    Таблица.Rows(ш + 1).Select();
    ОтправитьВБуфер(ТекстДляВставки);
    
    // Выполняем вставку данных
    ОбъектВорд.Application.Selection.Paste();
    
    // Принудительно возвращаем нужный кегль текущему выделению
    ОбъектВорд.Application.Selection.Font.Size = 8.5;
КонецЦикла;

Также можно вернуть размер шрифта целиком всей таблице однократно после завершения всех итераций цикла:

Таблица.Range.Font.Size = 8.5;

Решение 3. Использование метода PasteAndFormat вместо Paste

В объектной модели Word для объекта Selection доступен специализированный метод PasteAndFormat, который управляет правилами сопоставления стилей при программной вставке:


// Константа wdUseDestinationStylesRecovery (19) — сохранение стилей назначения
ОбъектВорд.Application.Selection.PasteAndFormat(19);

// Либо константа wdFormatPlainText (22) — вставка как простой текст с форматированием ячейки
ОбъектВорд.Application.Selection.PasteAndFormat(22);

Использование этого вызова вместо стандартного Selection.Paste указывает Word применить форматирование целевой ячейки к вставляемым данным.

Решение 4. Назначение именованного стиля ячейкам шаблона

Разберем фундаментальную причину сброса кегля: Word обращается к стилю «Обычный», если в ячейке не закреплен другой стиль. Создадим в шаблоне документа отдельный стиль оформления (например, с именем ТаблицаКлетки), в котором зададим шрифт 8,5 pt. Назначим этот стиль строкам таблицы шаблона. При программной вставке неразмеченного текста через буфер Word сохранит назначенный стиль ячейки, не возвращаясь к стилю «Обычный».

Ускорение работы через отключение визуальной перерисовки

При интенсивной работе с документом через COM-объект решающим фактором быстродействия является отключение перерисовки экрана. Постоянный пересчет макета страницы и отображение выделений ячеек замедляют выполнение алгоритма. Добавим отключение обновления экрана перед началом заполнения:


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

Попытка
    ЗаполнитьПоКлеточкам(ОбъектВорд, "ТекстЗакладки", СтрокаДанных);
Исключение
    ОбъектВорд.Application.ScreenUpdating = Истина;
    ВызватьИсключение;
КонецПопытки;

// Включаем отображение обратно
ОбъектВорд.Application.ScreenUpdating = Истина;

Ограничения использования буфера обмена и альтернативы

Заполнение таблиц через ClipboardData объекта ParentWindow имеет несколько серьезных ограничений:

  1. Зависимость от движка Internet Explorer: конструкция ЭлементыФормы.ПолеHTMLДокумента.Документ.ParentWindow.ClipboardData привязана к библиотеке MSHTML. Она не поддерживается на платформе Linux, в мобильном клиенте и веб-клиенте.
  2. Блокировки буфера обмена: буфер является разделяемым ресурсом операционной системы. Фоновые утилиты (история буфера обмена, антивирусы) могут заблокировать доступ к буферу во время выполнения цикла 1С, что приведет к ошибкам выполнения. Кроме того, этот механизм затирает пользовательские данные в буфере ОС.

Если требуется надежное формирование документов без COM и внешнего буфера, рекомендуется формировать макет средствами встроенного ТабличныйДокумент с последующим экспортом:

ТабличныйДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.DOCX);

Такой метод полностью независим от установленного на компьютере офисного пакета и гарантирует корректное сохранение геометрии таблицы и размеров шрифта.

← На главную