При формировании печатных форм и отчетов во внешних файлах Microsoft Word нередко возникает задача динамического создания таблиц. Например, когда строки табличной части документа необходимо сгруппировать по датам или подразделениям, выводя для каждой группы отдельную таблицу с собственным заголовком и параметрами форматирования.
Разберем подробно, как реализовать такую логику через механизм COM-соединения, настроить параметры ширины колонок, выравнивание текста и избежать типичных ошибок при позиционировании элементов.
Частая ошибка при работе с объектом Word.Application — активное использование объекта Selection. При вставке новых блоков курсор может смещаться в начало документа или приводить к непредвиденному наложению текста. Чтобы элементы выводились строго друг за другом, надежнее управлять диапазонами с помощью объекта Range.
Рассмотрим по шагам алгоритм последовательного добавления заголовка и таблицы в конец документа:
Content.End.Посмотрим на пример кода:
// Создание COM-объекта Word
Ворд = Новый COMОбъект("Word.Application");
Ворд.Visible = Ложь;
Документ = Ворд.Documents.Add();
// Добавление текстового заголовка в конец документа
ПозицияТекста = Документ.Range(Документ.Content.End - 1, Документ.Content.End - 1);
ПозицияТекста.InsertAfter("Дата дежурства: 15.10.2023 (с 09:00 до 18:00)" + Символы.ПС);
// Определение новой позиции вставки для таблицы
ПозицияТаблицы = Документ.Range(Документ.Content.End - 1, Документ.Content.End - 1);
ЧислоСтрок = 3;
ЧислоКолонок = 4;
Таблица = Документ.Tables.Add(ПозицияТаблицы, ЧислоСтрок, ЧислоКолонок);
После добавления таблицы требуется задать читаемый вид: настроить ширину столбцов, а также горизонтальное и вертикальное выравнивание данных внутри ячеек.
Проанализируем основные свойства форматирования:
PreferredWidth для каждого столбца коллекции Columns.ParagraphFormat.Alignment. Значение 1 соответствует выравниванию по центру, 0 — по левому краю, 2 — по правому краю, 3 — по ширине.VerticalAlignment конкретной ячейки Cell или всего диапазона Cells. Константы: 0 — по верхнему краю, 1 — по центру, 3 — по нижнему краю.Посмотрим на пример настройки созданной таблицы:
// Горизонтальное выравнивание всего текста таблицы по центру
Таблица.Range.ParagraphFormat.Alignment = 1;
// Вертикальное выравнивание во всех ячейках по центру
Таблица.Range.Cells.VerticalAlignment = 1;
// Установка ширины конкретных колонок (в пунктах)
Таблица.Columns(1).PreferredWidth = 40; // № п/п
Таблица.Columns(2).PreferredWidth = 180; // ФИО сотрудника
Таблица.Columns(3).PreferredWidth = 100; // Должность
Таблица.Columns(4).PreferredWidth = 80; // Часы
// Заполнение ячейки шапки
Ячейка = Таблица.Cell(1, 1);
Ячейка.Range.Text = "№";
Ячейка.Range.Bold = Истина;
Если требуется сформировать динамическое количество таблиц (например, отдельная таблица на каждую дату), данные из табличной части документа удобно предварительно сгруппировать запросом с помощью конструкции ИТОГИ ПО.
Разберем пример обхода группировок запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЧ.ДатаВыхода КАК ДатаВыхода,
| ТЧ.НомерСтроки КАК НомерСтроки,
| ТЧ.Сотрудник.Наименование КАК Сотрудник,
| ТЧ.ЧасыРаботы КАК ЧасыРаботы
|ИЗ
| Документ.ГрафикДежурств.Состав КАК ТЧ
|ГДЕ
| ТЧ.Ссылка = &Ссылка
|ИТОГИ ПО
| ДатаВыхода";
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаПоДатам = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаПоДатам.Следующий() Цикл
// 1. Вставляем заголовок группы
ПозицияЗаголовка = Документ.Range(Документ.Content.End - 1, Документ.Content.End - 1);
ПозицияЗаголовка.InsertAfter("Дата: " + Формат(ВыборкаПоДатам.ДатаВыхода, "ДФ=dd.MM.yyyy") + Символы.ПС);
// 2. Создаем таблицу для текущей даты
ПозицияТаблицы = Документ.Range(Документ.Content.End - 1, Документ.Content.End - 1);
КоличествоСтрок = ВыборкаПоДатам.Количество() + 1; // +1 для строки заголовков
Таблица = Документ.Tables.Add(ПозицияТаблицы, КоличествоСтрок, 3);
// Заполняем шапку
Таблица.Cell(1, 1).Range.Text = "№";
Таблица.Cell(1, 2).Range.Text = "Сотрудник";
Таблица.Cell(1, 3).Range.Text = "Часы";
// 3. Заполняем строки детальными записями
ВыборкаДетали = ВыборкаПоДатам.Выбрать();
ИндексСтроки = 2;
Пока ВыборкаДетали.Следующий() Цикл
Таблица.Cell(ИндексСтроки, 1).Range.Text = Строка(ВыборкаДетали.НомерСтроки);
Таблица.Cell(ИндексСтроки, 2).Range.Text = Строка(ВыборкаДетали.Сотрудник);
Таблица.Cell(ИндексСтроки, 3).Range.Text = Строка(ВыборкаДетали.ЧасыРаботы);
ИндексСтроки = ИндексСтроки + 1;
КонецЦикла;
// Добавляем отступ после таблицы
ПозицияОтступа = Документ.Range(Документ.Content.End - 1, Документ.Content.End - 1);
ПозицияОтступа.InsertAfter(Символы.ПС);
КонецЦикла;
При использовании COM-объекта Word.Application важно учитывать следующие технические ограничения:
Ворд.Quit(), а также очистку переменных (Ворд = Неопределено;), чтобы исключить зависание фоновых процессов WINWORD.EXE.ТабличныйДокумент в 1С с последующим сохранением в формате DOCX с помощью метода ТабличныйДокумент.Записать("файл.docx", ТипФайлаТабличногоДокумента.DOCX);, что работает на сервере быстрее и без установки MS Office.