Работа с макетами Microsoft Word в 1С через COM-соединение — это классическая задача при формировании договоров, коммерческих предложений и других сложных печатных форм. Часто мы сталкиваемся с ситуацией, когда количество строк в документе заранее неизвестно (например, список товаров или услуг), и нам необходимо динамически расширять таблицу. В этой статье мы подробно разберем, как правильно добавлять строки, сохранять оформление макета и избегать досадных ошибок Microsoft Word.
Для начала рассмотрим стандартный механизм обращения к таблице. В 1С мы создаем объект Word.Application, открываем документ и обращаемся к коллекции Tables. Важно помнить, что индексация в Word начинается с единицы, а не с нуля, как в коллекциях 1С.
Рассмотрим базовый пример добавления строки, который часто используют разработчики:
WordПриложение = Новый COMОбъект("Word.Application");
Документ = WordПриложение.Documents.Open(ПутьКФайлу);
// Допустим, нам нужна третья таблица в документе
WordТаблица = Документ.Tables(3);
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
// Добавляем пустую строку в конец таблицы
НоваяСтрока = WordТаблица.Rows.Add();
// Заполняем ячейки
НоваяСтрока.Cells(1).Range.Text = СтрокаТЧ.НомерСтроки;
НоваяСтрока.Cells(2).Range.Text = СтрокаТЧ.Наименование;
// ... и так далее
КонецЦикла;
Метод Rows.Add() создает новую строку, но именно здесь начинаются первые трудности, связанные с оформлением и индексацией.
Один из самых частых вопросов: почему в макете шрифт 11-го размера, а новые строки создаются с 8-м размером или другим начертанием? Это происходит потому, что Rows.Add() часто наследует стиль «Обычный» или стиль последнего абзаца, который может не совпадать с оформлением вашей «эталонной» строки в макете.
Чтобы гарантированно сохранить форматирование (шрифты, границы, отступы), проанализируем и применим метод копирования строки-шаблона. Вместо создания пустой строки, мы будем копировать уже оформленную строку из макета и вставлять ее. Разберем этот алгоритм по шагам:
// Выбираем строку-шаблон (например, вторую)
СтрокаШаблон = WordТаблица.Rows(2);
СтрокаШаблон.Range.Copy(); // Копируем в буфер обмена
Для Каждого СтрокаТЧ Из ТаблицаТоваров Цикл
// Вставляем строку из буфера
WordТаблица.Rows(WordТаблица.Rows.Count).Range.Paste();
// Получаем последнюю вставленную строку для заполнения
ТекущаяСтрока = WordТаблица.Rows(WordТаблица.Rows.Count);
ТекущаяСтрока.Cells(1).Range.Text = СтрокаТЧ.Номенклатура;
// Данные сохранят шрифт из шаблона
КонецЦикла;
// В конце можно удалить саму строку-шаблон, если она осталась пустой
СтрокаШаблон.Delete();
При использовании метода Cell(Row, Column) часто возникает исключение: «Произошла исключительная ситуация (Microsoft Word): Запрашиваемый номер семейства не существует». Выясним причины этой ошибки.
Во-первых, это может быть связано с объединенными ячейками. Если в вашей таблице есть хоть одно объединение (например, шапка таблицы состоит из двух уровней), Word теряет возможность прямой индексации через Cell(). В таких случаях таблица перестает быть «прямоугольной» с точки зрения объектной модели.
Как решить:
Проанализируем структуру таблицы. Если избежать объединений нельзя, используйте навигацию через Selection или обращайтесь к ячейкам через Next, но лучше всего — проектируйте динамические таблицы максимально просто, без объединения колонок в тех строках, которые будут тиражироваться.
Во-вторых, проверьте границы индексов. Если вы пытаетесь обратиться к WordТаблица.Cell(i, 6), а в таблице всего 5 колонок, возникнет эта ошибка. Проверьте количество колонок программно:
Если WordТаблица.Columns.Count < 6 Тогда
// Возможно, нужно добавить колонку или перепроверить индекс
Сообщить("В таблице недостаточно колонок!");
КонецЕсли;
Заполнение больших таблиц через COM происходит медленно, так как Word перерисовывает документ после каждого изменения. Чтобы ускорить процесс в несколько раз, воспользуемся свойством ScreenUpdating. Проанализируем, как это встроить в код:
WordПриложение.Application.ScreenUpdating = Ложь; // Выключаем обновление экрана
Попытка
// Здесь идет основной цикл заполнения таблицы
// ...
Исключение
WordПриложение.Application.ScreenUpdating = Истина;
ВызватьИсключение;
КонецПопытки;
WordПриложение.Application.ScreenUpdating = Истина; // Включаем обратно
Это критически важно, если в вашей таблице более 50 строк. Пользователь не будет видеть «мелькание» текста, а формирование файла пройдет значительно быстрее.
Обращение к таблице по номеру Tables(3) крайне ненадежно. Если пользователь или администратор добавит в начало документа еще одну таблицу или даже просто пустую строку перед таблицей (в некоторых версиях), индекс может измениться. Рассмотрим более профессиональный подход — использование Закладок.
Выделите в макете Word всю таблицу и назначьте ей имя через «Вставка — Закладка» (например, ТоварнаяТаблица). Теперь в 1С вы можете обращаться к ней напрямую:
Попытка
WordТаблица = Документ.Bookmarks("ТоварнаяТаблица").Range.Tables(1);
Исключение
Сообщить("Таблица с закладкой 'ТоварнаяТаблица' не найдена в макете!");
КонецПопытки;
Не забывайте, что после формирования документа процесс WINWORD.EXE может остаться в памяти сервера или клиентского ПК, потребляя ресурсы. Необходимо правильно закрыть соединение:
Quit().Неопределено.
// Закрываем документ без сохранения изменений (если сохранили ранее в другой файл)
Документ.Close(0);
WordПриложение.Quit();
WordПриложение = Неопределено;
Используя эти методы — копирование строк-шаблонов, управление обновлением экрана и работу через закладки — вы сможете создавать надежные и быстрые механизмы формирования документов Word, которые сохранят идеальный внешний вид вне зависимости от объема выводимых данных.