Работа с документами Microsoft Word через механизм COM-соединения является классической задачей для разработчика 1С. Однако часто возникают ситуации, когда написанный код кажется абсолютно логичным и рабочим, отладчик подтверждает выполнение команд, но итоговый результат в документе остается неизменным. Одной из таких проблем является программное добавление строк в таблицу, которое "проходит" в коде, но не отображается визуально.
В данной статье мы разберем, почему так происходит, проанализируем типичные ошибки при работе с коллекцией Tables и рассмотрим наиболее надежные способы автоматизации Word.
Рассмотрим ситуацию, с которой столкнулся автор темы. Программный код успешно создает объект Word, открывает документ и в цикле выполняет метод Rows.Add(). При проверке в отладчике свойство Таблица.Rows.Count показывает увеличение количества строк, но в открытом окне Word пользователь видит пустой шаблон с исходным количеством строк. Проанализируем фрагмент кода, приводящий к такой ситуации:
&НаСервере
Процедура ПечатьНаСервере()
// Получаем макет и создаем временный файл
Макет = ВернутьМакет();
НазваниеФайла = ПолучитьИмяВременногоФайла("doc");
Макет.Записать(НазваниеФайла);
mWordObject = Новый COMObject("Word.Application");
Попытка
КомОбъект = mWordObject.Documents.Add(НазваниеФайла);
Исключение
Возврат;
КонецПопытки;
КомОбъект.Application.Visible = Истина;
// Попытка обращения к первой таблице
Таблица = КомОбъект.Tables(1);
Для СтрокаЦикла = 1 По 5 Цикл
Таблица.Rows.Add();
КонецЦикла;
КомОбъект.Fields.Update();
КонецПроцедуры
Причина странного поведения кроется в особенностях структуры документа Word. Выясним причину: в коллекции Tables объекта Document содержатся вообще все таблицы, которые есть в файле. К ним относятся не только те, что мы видим в тексте, но и:
В рассматриваемом случае оказалось, что визуально видимая пользователю таблица имела индекс 3, в то время как код модифицировал таблицу с индексом 1, которая была либо скрыта, либо находилась в другой части документа. Именно поэтому Rows.Count увеличивался, но визуальных изменений не было.
Чтобы не гадать, какой индекс присвоит Word той или иной таблице при редактировании шаблона, самым надежным способом является использование закладок. Рассмотрим, как это реализовать:
1. Откройте ваш шаблон .dot или .docx в Microsoft Word.
2. Выделите всю таблицу, с которой планируете работать.
3. Перейдите на вкладку Вставка -> Закладка и дайте ей имя, например, Товары.
4. В коде 1С обращайтесь к таблице через эту закладку.
Проанализируем обновленный пример кода:
// Использование закладки гарантирует выбор нужной таблицы
ИмяЗакладки = "Товары";
Если КомОбъект.Bookmarks.Exists(ИмяЗакладки) Тогда
// Получаем диапазон закладки и первую таблицу в этом диапазоне
Таблица = КомОбъект.Bookmarks(ИмяЗакладки).Range.Tables(1);
Для Каждого СтрокаДанных Из ТЗ_Данные Цикл
НоваяСтрока = Таблица.Rows.Add();
// Заполнение ячеек
НоваяСтрока.Cells(1).Range.Text = СтрокаДанных.Наименование;
НоваяСтрока.Cells(2).Range.Text = СтрокаДанных.Количество;
КонецЦикла;
КонецЕсли;
Метод Rows.Add() работает достаточно медленно, так как при каждом вызове Word пересчитывает геометрию всей страницы. Если вам нужно вставить сотни строк, выполнение обработки может затянуться на минуты. Разберем по шагам более быстрый метод — копирование эталонной строки.
Алгоритм действий:
// Пример копирования строки для сохранения форматирования
ЭталоннаяСтрока = Таблица.Rows(2); // Допустим, вторая строка — образец
ЭталоннаяСтрока.Range.Copy(); // Копируем в буфер
Для НомерСтроки = 1 По 10 Цикл
Таблица.Rows.Add(); // Добавляем новую строку
Таблица.Rows(Таблица.Rows.Count).Range.Paste(); // Вставляем форматирование
КонецЦикла;
Для максимально быстрой работы профессионалы рекомендуют формировать данные в виде текста с разделителями (табуляция и перевод строки) и использовать метод ConvertToTable(). Это позволяет "выплюнуть" весь массив данных в Word одним действием.
В исходном коде автора используется директива &НаСервере. Это критически важный момент для стабильности системы. Рассмотрим основные правила работы с COM-объектами на сервере:
1. Интерактивный режим: Microsoft официально не рекомендует использовать Word на стороне сервера. Процесс WINWORD.EXE может ожидать реакции пользователя (например, уведомление об обновлении или ошибке), что приведет к "зависанию" потока 1С.
2. Очистка памяти: Если вы создали Новый COMObject, вы обязаны его закрыть. В противном случае ваш сервер через неделю превратится в "кладбище" запущенных процессов Word, которые съедят всю оперативную память. Всегда используйте конструкцию Попытка...Исключение и закрывайте приложение в конце:
Попытка
// Код заполнения документа
КомОбъект.SaveAs(ПутьКФайлу);
Настолько
// Обработка ошибок
КонецПопытки;
// Обязательное завершение работы!
mWordObject.Quit();
mWordObject = Неопределено;
3. Права доступа: Служба "1С:Предприятие" обычно работает под системной учетной записью. Чтобы Word мог инициализироваться, в системе должны существовать папки Desktop. Пути для их создания (в зависимости от разрядности системы):
C:\Windows\System32\config\systemprofile\DesktopC:\Windows\SysWOW64\config\systemprofile\DesktopЕсли ваша задача — простая вставка данных в таблицу без сложного форматирования, мы рекомендуем рассмотреть отказ от COM-соединения в пользу прямого изменения XML-структуры файла. Формат .docx — это ZIP-архив с XML-файлами внутри. Используя штатные средства 1С для работы с архивами и XML, вы сможете формировать документы в десятки раз быстрее, а главное — без необходимости устанавливать Microsoft Office на сервер.
Преимущества работы через XML:
Подводя итог, можно сказать: если вы столкнулись с тем, что строки не появляются в таблице Word — проверьте реальное количество таблиц в документе через КомОбъект.Tables.Count или перейдите на использование закладок. Это сэкономит ваше время и сделает код более устойчивым к изменениям в шаблоне документа.