Как вывести каждую строку табличной части 1С в отдельный макет Word через ActiveDocument?

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

При разработке печатных форм часто возникает задача выгрузки данных в Microsoft Word. Одной из специфических проблем является вывод данных из табличной части: когда на каждую строку таблицы нужно сформировать либо отдельный файл Word, либо новую страницу в рамках одного общего документа. Рассмотрим, как это реализовать правильно, учитывая особенности клиент-серверной архитектуры 1С.

Особенности архитектуры при работе с MS Word

Прежде всего проанализируем ситуацию: Microsoft Word является внешним COM-объектом, который должен быть установлен на компьютере пользователя. Это накладывает важное ограничение — работа с объектом Word.Application возможна только в контексте &НаКлиенте. При этом данные для заполнения документа (запросы, выборки из базы) должны формироваться &НаСервере. Наша задача — эффективно передать данные с сервера на клиент и организовать цикл печати.

Вариант 1: Формирование отдельного документа для каждой строки (базовый метод)

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

Шаг 1. Получение данных на сервере. Сначала нам необходимо собрать все данные из табличной части в структуру или массив, который можно передать на клиент. Мы не можем передать сами объекты (ссылки), так как обращение к их реквизитам на клиенте вызовет лишние серверные вызовы.


&НаСервере
Функция ПолучитьДанныеДляПечати()
    // Создаем массив, в который поместим структуры с данными каждой строки
    МассивДанных = Новый Массив;
    
    // Предположим, Объект - это наш документ с табличной частью "Должники"
    Для Каждого Стр Из Объект.Должники Цикл
        ДанныеСтроки = Новый Структура;
        ДанныеСтроки.Вставить("ИОДолжник", Стр.Должник.Наименование);
        ДанныеСтроки.Вставить("СуммаЗадолженности", Стр.Сумма);
        ДанныеСтроки.Вставить("АдресДомаДолжника", Стр.Адрес);
        // Добавьте другие необходимые поля
        
        МассивДанных.Добавить(ДанныеСтроки);
    КонецЦикла;
    
    Возврат МассивДанных;
КонецФункции

Шаг 2. Организация цикла печати на клиенте. Теперь разберем клиентскую процедуру, которая будет инициализировать Word и заполнять макеты.


&НаКлиенте
Процедура ПечатьУведомлений(Команда)
    
    ДанныеДляПечати = ПолучитьДанныеДляПечати();
    
    Попытка
        ОбъектВорд = Новый COMОбъект("Word.Application");
    Исключение
        Сообщить("Microsoft Word не установлен!");
        Возврат;
    КонецПопытки;
    
    ПутьКШаблону = "\\serv8\ftp\Шаблоны\Уведомление.docx";
    
    Для Каждого СтрДанных Из ДанныеДляПечати Цикл
        
        // Создаем новый документ на основе шаблона
        Док = ОбъектВорд.Documents.Add(ПутьКШаблону);
        
        // Заполнение закладок (Bookmarks)
        ЗаполнитьЗакладку(Док, "ИОДолжник", СтрДанных.ИОДолжник);
        ЗаполнитьЗакладку(Док, "СуммаЗадолженности", СтрДанных.СуммаЗадолженности);
        ЗаполнитьЗакладку(Док, "АдресДомаДолжника", СтрДанных.АдресДомаДолжника);
        
        // Делаем документ видимым
        ОбъектВорд.Visible = Истина;
        
    КонецЦикла;
    
    // Активируем последнее окно
    ОбъектВорд.Activate();
    
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьЗакладку(ДокументВорд, ИмяЗакладки, Значение)
    Если ДокументВорд.Bookmarks.Exists(ИмяЗакладки) Тогда
        ДокументВорд.Bookmarks(ИмяЗакладки).Select();
        ДокументВорд.Application.Selection.TypeText(Строка(Значение));
    КонецЕсли;
КонецПроцедуры

Вариант 2: Объединение всех строк в один многостраничный документ

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

Разберем алгоритм склейки:

  1. Создаем один основной документ.
  2. В цикле открываем временный документ-шаблон.
  3. Заполняем его данными текущей строки.
  4. Копируем содержимое временного документа и вставляем в конец основного.
  5. Вставляем разрыв страницы wdPageBreak (константа равна 7).

&НаКлиенте
Процедура ПечатьВЕдиныйФайл(Команда)
    
    ДанныеДляПечати = ПолучитьДанныеДляПечати();
    ОбъектВорд = Новый COMОбъект("Word.Application");
    ПутьКШаблону = "C:\Templates\Notice.docx";
    
    // Основной итоговый документ
    ИтоговыйДок = ОбъектВорд.Documents.Add();
    
    Для Каждого СтрДанных Из ДанныеДляПечати Цикл
        
        // Открываем временный документ для заполнения
        ВременныйДок = ОбъектВорд.Documents.Add(ПутьКШаблону);
        
        // Заполняем метки (в данном примере через поиск и замену)
        ЗаменитьТекстВДокументе(ВременныйДок, "[ФИО]", СтрДанных.ИОДолжник);
        ЗаменитьТекстВДокументе(ВременныйДок, "[Сумма]", СтрДанных.СуммаЗадолженности);
        
        // Копируем содержимое заполненного шаблона
        ВременныйДок.Range().Copy();
        
        // Переходим в конец основного документа и вставляем
        ИтоговыйДок.Range(ИтоговыйДок.Range().End - 1).Paste();
        
        // Добавляем разрыв страницы, если это не последняя строка
        Если ДанныеДляПечати.Индекс(СтрДанных) <> ДанныеДляПечати.Количество() - 1 Тогда
            // 7 - это константа wdPageBreak
            ИтоговыйДок.Range(ИтоговыйДок.Range().End - 1).InsertBreak(7);
        КонецЕсли;
        
        // Закрываем временный шаблон без сохранения
        ВременныйДок.Close(0);
        
    КонецЦикла;
    
    ОбъектВорд.Visible = Истина;
    
КонецПроцедуры

&НаКлиенте
Процедура ЗаменитьТекстВДокументе(Док, ЧтоМеняем, НаЧтоМеняем)
    FindObject = Док.Content.Find;
    FindObject.Execute(ЧтоМеняем, Ложь, Истина, Ложь, , , Истина, 1, , Строка(НаЧтоМеняем), 2);
КонецПроцедуры

Оптимизация и важные советы

Проанализируем типичные ошибки, которые могут замедлить работу или привести к сбоям:

Выясним еще один момент: если вам нужно просто вывести таблицу данных внутри одного документа Word, используйте коллекцию Tables. Вы можете найти таблицу в шаблоне по индексу (например, Док.Tables(1)) и программно добавлять в нее строки методом Таблица.Rows.Add(). Это гораздо эффективнее, чем копировать целые блоки текста для простых списочных данных.

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

← На главную