При разработке печатных форм (Отладка внешних печатных форм и обработок) часто возникает задача сформировать единый документ Word, в котором данные по разным объектам (например, по разным организациям или договорам) располагаются на отдельных страницах. В Библиотеке стандартных подсистем (БСП) (Справочник по методам БСП (с примерами использования)) предусмотрены штатные механизмы для работы с макетами .docx, однако их использование имеет свои нюансы, отличные от привычных табличных документов .mxl. В этой статье мы подробно разберем, как правильно спроектировать макет и написать код для пакетного вывода данных в один файл.
Первое, что нам необходимо усвоить: принцип работы с макетом Word в БСП строится на использовании именованных областей. В отличие от MXL, где области задаются координатами строк и колонок, в Word области определяются специальными тегами. Разберем структуру типичного макета для вывода списка товаров по организации.
В тексте документа или внутри ячеек таблиц макета используются следующие конструкции:
{v8 Область.ИмяОбласти}{/v8 Область.ИмяОбласти}{ИмяПараметра}Важно понимать, что области могут быть вложенными. Например, вы можете создать общую область ДанныеОрганизации, внутри которой будет находиться шапка и таблица со своей собственной областью для строк СтрокаТаблицы. Главная ошибка начинающих разработчиков — создание множества одинаковых областей в макете для каждой страницы. На самом деле, нам достаточно одной группы областей, которую мы будем выводить в цикле столько раз, сколько потребуется.
Проанализируем структуру макета. Для корректного вывода нам понадобятся следующие логические блоки:
Создайте в Word документ и разместите теги примерно так:
{v8 Область.Шапка}
Отчет по организации {НазваниеОрганизации}
{/v8 Область.Шапка}
Затем вставьте таблицу, где строка с данными будет помечена как область:
{v8 Область.СтрокаТаблицы} {Номенклатура} | {Количество} | {Цена} {/v8 Область.СтрокаТаблицы}
Рассмотрим основной алгоритм работы в модуле менеджера объекта или в специализированной процедуре печати. Нам потребуется использовать функции общего модуля УправлениеПечатью. Основная идея заключается в том, чтобы инициализировать один печатный документ и в цикле "нанизывать" на него области макета.
Проанализируем пример кода, реализующий эту логику:
// 1. Инициализируем структуру печатной формы
ДанныеДляПечати = УправлениеПечатью.ИнициализироватьПечатнуюФормуMSWord(Макет, ИмяМакета);
Документ = ДанныеДляПечати.Документ;
// 2. Описываем области, которые будем использовать
// Для повышения производительности лучше описать структуры областей заранее
ОписаниеШапки = Новый Структура("ИмяОбласти, ТипОбласти", "Шапка", "СтрокаТаблицы");
ОбластьШапка = УправлениеПечатью.ОбластьМакета(ДанныеДляПечати.Макет, ОписаниеШапки);
ОписаниеСтроки = Новый Структура("ИмяОбласти, ТипОбласти", "СтрокаТаблицы", "СтрокаТаблицы");
ОбластьСтрока = УправлениеПечатью.ОбластьМакета(ДанныеДляПечати.Макет, ОписаниеСтроки);
ОписаниеПодвала = Новый Структура("ИмяОбласти, ТипОбласти", "Подвал", "СтрокаТаблицы");
ОбластьПодвал = УправлениеПечатью.ОбластьМакета(ДанныеДляПечати.Макет, ОписаниеПодвала);
// 3. Запускаем цикл по массиву объектов (например, организаций)
Для Каждого ОрганизацияСсылка Из МассивОбъектов Цикл
// Получаем данные для текущей итерации
ДанныеШапки = ПолучитьДанныеДляШапки(ОрганизацияСсылка);
ДанныеТаблицы = ПолучитьДанныеТаблицы(ОрганизацияСсылка); // Массив структур или ТЗ
// Присоединяем шапку и заполняем её параметры
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(Документ, ОбластьШапка, ДанныеШапки);
// Заполняем табличную часть. БСП сама размножит строку таблицы по коллекции данных
УправлениеПечатью.ПрисоединитьИЗаполнитьКоллекцию(Документ, ОбластьСтрока, ДанныеТаблицы);
// Определяем, нужен ли разрыв страницы.
// Обычно разрыв вставляется перед каждой новой страницей, кроме первой,
// либо после каждой, кроме последней.
ВставитьРазрыв = (ОрганизацияСсылка <> МассивОбъектов[МассивОбъектов.Количество() - 1]);
// Присоединяем подвал. Четвертый параметр отвечает за вставку разрыва страницы
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(Документ, ОбластьПодвал, ДанныеПодвала, ВставитьРазрыв);
КонецЦикла;
// 4. Завершаем формирование и получаем двоичные данные
ПечатнаяФорма = УправлениеПечатью.СформироватьПечатнуюФорму(ДанныеДляПечати);
Выясним причину, почему иногда разрыв страницы работает не так, как ожидается. В БСП есть два основных способа управления переносом на новый лист в Word:
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(..., Истина). Если передать Истина, БСП добавит символ разрыва раздела или страницы. Однако стоит помнить, что это может добавить пустой лист в конце документа, если не проверять, является ли текущая итерация последней.Ctrl + Enter. Назовите её ОбластьРазрыва. В коде выводите её просто методом УправлениеПечатью.ПрисоединитьОбласть(Документ, ОбластьРазрыва) в конце каждой итерации цикла. Это дает визуально более предсказуемый результат при редактировании макета.Рассмотрим подробнее метод УправлениеПечатью.ПрисоединитьИЗаполнитьКоллекцию. Это крайне полезная функция, которая избавляет нас от написания вложенных циклов по строкам товаров или услуг.
Чтобы метод отработал корректно, убедитесь, что:
СтрокаТаблицы) охватывает именно строку внутри таблицы (открывающий и закрывающий теги должны быть в ячейках одной строки).ДанныеТаблицы является Массивом Структур или ТаблицейЗначений, где имена ключей/колонок в точности совпадают с именами параметров в макете (например, {Номенклатура}).Проанализируем ситуацию, когда формирование документа занимает слишком много времени. Работа с COM-объектами Word (если сервер 1С использует их) довольно ресурсозатратна.
Совет 1: Если ваша версия БСП поддерживает работу с форматом .docx через XML (без использования установленного Word на сервере), обязательно используйте этот режим. Это ускоряет процесс в разы.
Совет 2: Не перегружайте макет сложной графикой внутри повторяющихся областей. Логотипы большого размера могут значительно увеличить итоговый файл, если они будут дублироваться на каждой из 100 страниц.
Совет 3: Обращайте внимание на колонтитулы. В рамках одного документа Word через стандартные методы БСП сложно менять содержимое колонтитулов для каждой страницы индивидуально (например, выводить там название текущей фирмы). Если это критично, данные организации лучше выводить в теле документа (в шапке области), а не в системных колонтитулах Word.
Следуя этим рекомендациям и используя приведенный выше программный код, вы сможете эффективно реализовать вывод сложных многостраничных отчетов в формате Word, полностью используя потенциал Библиотеки стандартных подсистем.