При автоматизации формирования печатных форм и отчетов через COM-соединение с Microsoft Word разработчики нередко сталкиваются с проблемой: посимвольное или поячеечное заполнение таблицы занимает слишком много времени. Чтобы ускорить процесс, часто применяют групповую вставку строки данных через системный буфер обмена, разделяя значения символами табуляции. Однако при таком подходе возникает неприятный эффект — вставляемый текст сбрасывает заданный в шаблоне кегль (например, шрифт с 8,5 пунктов меняется на стандартный 12 pt), из-за чего разметка таблицы «плывет» и шаблон деформируется. Разберем причины такого поведения и рассмотрим надежные способы решения этой задачи.
Проанализируем механику работы Microsoft Word и COM-объекта:
Selection.Paste выполняет базовую системную вставку и не считывает эти флаги.Посмотрим на исходный пример процедуры, в которой происходит заполнение ячеек через буфер обмена:
Процедура ЗаполнитьПоКлеточкам(ОбъектВорд, ТекстПоиска, Строка) Экспорт
Если ОбъектВорд.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С. Если жесткие требования к кеглю шрифта отсутствуют, а ключевая задача — исключить деформацию границ таблицы и смещение полей, настроим шаблон Word:
В этом случае Word при вставке оставляет формальный размер шрифта, но визуально пропорционально сжимает отображаемые символы так, чтобы они строго укладывались в физические границы ячейки. Таблица перестает растягиваться по ширине и высоте.
Если визуального сжатия недостаточно и требуется строго заданный размер шрифта (например, 8,5 pt), восстановим размер программно. Перебирать каждую ячейку в цикле не нужно — достаточно выполнить форматирование всего диапазона за один COM-вызов сразу после вставки. Это действие выполняется практически мгновенно.
Рассмотрим, как изменить фрагмент кода в цикле вставки строк:
Для ш = 0 По МассивСтрокДляВставки.Количество() - 1 Цикл
ТекстДляВставки = МассивСтрокДляВставки[ш];
Таблица.Rows(ш + 1).Select();
ОтправитьВБуфер(ТекстДляВставки);
// Выполняем вставку данных
ОбъектВорд.Application.Selection.Paste();
// Принудительно возвращаем нужный кегль текущему выделению
ОбъектВорд.Application.Selection.Font.Size = 8.5;
КонецЦикла;
Также можно вернуть размер шрифта целиком всей таблице однократно после завершения всех итераций цикла:
Таблица.Range.Font.Size = 8.5;
В объектной модели Word для объекта Selection доступен специализированный метод PasteAndFormat, который управляет правилами сопоставления стилей при программной вставке:
// Константа wdUseDestinationStylesRecovery (19) — сохранение стилей назначения
ОбъектВорд.Application.Selection.PasteAndFormat(19);
// Либо константа wdFormatPlainText (22) — вставка как простой текст с форматированием ячейки
ОбъектВорд.Application.Selection.PasteAndFormat(22);
Использование этого вызова вместо стандартного Selection.Paste указывает Word применить форматирование целевой ячейки к вставляемым данным.
Разберем фундаментальную причину сброса кегля: Word обращается к стилю «Обычный», если в ячейке не закреплен другой стиль. Создадим в шаблоне документа отдельный стиль оформления (например, с именем ТаблицаКлетки), в котором зададим шрифт 8,5 pt. Назначим этот стиль строкам таблицы шаблона. При программной вставке неразмеченного текста через буфер Word сохранит назначенный стиль ячейки, не возвращаясь к стилю «Обычный».
При интенсивной работе с документом через COM-объект решающим фактором быстродействия является отключение перерисовки экрана. Постоянный пересчет макета страницы и отображение выделений ячеек замедляют выполнение алгоритма. Добавим отключение обновления экрана перед началом заполнения:
// Отключаем обновление экрана Word для ускорения работы
ОбъектВорд.Application.ScreenUpdating = Ложь;
Попытка
ЗаполнитьПоКлеточкам(ОбъектВорд, "ТекстЗакладки", СтрокаДанных);
Исключение
ОбъектВорд.Application.ScreenUpdating = Истина;
ВызватьИсключение;
КонецПопытки;
// Включаем отображение обратно
ОбъектВорд.Application.ScreenUpdating = Истина;
Заполнение таблиц через ClipboardData объекта ParentWindow имеет несколько серьезных ограничений:
ЭлементыФормы.ПолеHTMLДокумента.Документ.ParentWindow.ClipboardData привязана к библиотеке MSHTML. Она не поддерживается на платформе Linux, в мобильном клиенте и веб-клиенте.Если требуется надежное формирование документов без COM и внешнего буфера, рекомендуется формировать макет средствами встроенного ТабличныйДокумент с последующим экспортом:
ТабличныйДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.DOCX);
Такой метод полностью независим от установленного на компьютере офисного пакета и гарантирует корректное сохранение геометрии таблицы и размеров шрифта.