В практике разработки в среде 1С:Предприятие часто возникает задача вывода данных табличной части документа не сплошным списком, а в виде отдельных независимых карточек. Это могут быть ценники, этикетки, мини-накладные, технологические карты или талоны. Особую сложность для начинающих разработчиков представляет компоновка таких элементов на одном листе формата А4 в виде сетки (например, по 3 карточки в ряд), чтобы экономно расходовать бумагу и облегчить последующую резку листа.
В рамках этой статьи мы подробно разберем, как правильно построить алгоритм вывода сетки карточек, используя механизмы табличного документа 1С, исправим типичные ошибки позиционирования и заполнения параметров, а также рассмотрим профессиональные приемы оптимизации компоновки.
Для управления выводом областей макета в результирующий табличный документ используются два основных метода: Вывести() и Присоединить(). Понимание разницы между ними критически важно для построения правильной сетки.
Вывести(<Область>) — этот метод добавляет указанную область макета в табличный документ снизу, всегда начиная вывод с новой строки (с левого края листа).Присоединить(<Область>) — этот метод пытается разместить указанную область справа от уже выведенной области в той же самой строке. Если область физически помещается по ширине листа, она будет добавлена горизонтально.Для того чтобы получить сетку карточек (например, 3 колонки в ряд и неограниченное количество строк вниз), нам необходимо комбинировать эти методы. Первую карточку в строке мы должны выводить, а последующие две — присоединять. После вывода третьей карточки цикл повторяется, и четвертая карточка снова выводится с новой строки.
При реализации подобного вывода начинающие программисты часто совершают ошибку, приводящую к тому, что все выведенные карточки заполняются данными одной и той же (обычно последней) строки табличной части. Давайте проанализируем фрагмент ошибочного кода:
Для каждого стр из ТаблицаВыполнения Цикл
// ... логика выбора Вывести/Присоединить ...
Для Каждого ТекСтрокаТаблица Из ТаблицаВыполнения Цикл
ОбластьТаблица.Параметры.Заполнить(ТекСтрокаТаблица);
КонецЦикла;
// ... вывод области ...
КонецЦикла;
В чем причина ошибки? Здесь присутствует классический цикл в цикле. Во внешнем цикле мы обходим строки таблицы. Однако перед выводом каждой карточки мы запускаем внутренний цикл, который повторно обходит ВСЮ таблицу от начала до конца и перезаписывает параметры области макета данными каждой строки по очереди. В итоге в параметрах области всегда остаются данные самой последней строки таблицы. Внутренний цикл здесь абсолютно лишний. Заполнение параметров должно происходить строго текущей строкой внешнего цикла стр.
Для реализации корректного вывода мы используем счетчик колонок. Посмотрим на правильный алгоритм работы процедуры печати:
Процедура Печать(Элемент)
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Макет");
// Получаем области макета
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьТаблица = Макет.ПолучитьОбласть("Таблица");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
СчетчикКолонок = 1; // Счетчик для контроля горизонтального вывода
Для Каждого Стр Из ТаблицаВыполнения Цикл
// Заполняем параметры области данными текущей строки
ОбластьТаблица.Параметры.Заполнить(Стр);
// Ручное заполнение реквизитов с несовпадающими именами
ОбластьТаблица.Параметры.Номер = Стр.ДецимальныйНомер;
ОбластьТаблица.Параметры.Изделие = Стр.ПринадлежностьКТипу;
// Определяем, куда выводить карточку: вниз или вбок
Если СчетчикКолонок = 1 Тогда
// Первая карточка в ряду - выводим с новой строки
ТабДок.Вывести(ОбластьЗаголовок);
ТабДок.Вывести(ОбластьШапка);
ТабДок.Вывести(ОбластьТаблица);
ТабДок.Вывести(ОбластьПодвал);
Иначе
// Вторая и третья карточки - присоединяем справа
ТабДок.Присоединить(ОбластьЗаголовок);
ТабДок.Присоединить(ОбластьШапка);
ТабДок.Присоединить(ОбластьТаблица);
ТабДок.Присоединить(ОбластьПодвал);
КонецЕсли;
// Увеличиваем счетчик колонок
СчетчикКолонок = СчетчикКолонок + 1;
// Если вывели 3 карточки в ряд, сбрасываем счетчик для перехода на новую строку
Если СчетчикКолонок > 3 Тогда
СчетчикКолонок = 1;
КонецЕсли;
КонецЦикла;
// Настройки отображения результирующего документа
ТабДок.ОтображатьСетку = Ложь;
ТабДок.Защита = Ложь;
ТабДок.ТолькоПросмотр = Ложь;
ТабДок.Показать();
КонецПроцедуры
Хотя базовый алгоритм успешно решает задачу вывода сетки, в реальных коммерческих задачах вы столкнетесь с дополнительными требованиями к качеству и стабильности печатной формы. Рассмотрим, как сделать вывод карточек по-настоящему профессиональным.
Если в табличной части вашего документа содержится, например, 15 строк, алгоритм сформирует 5 рядов карточек по 3 штуки в каждом. При отправке на печать принтер может разорвать страницу А4 прямо посередине четвертого ряда. Чтобы избежать этого, перед выводом каждого нового ряда карточек необходимо программно оценивать, поместится ли он по высоте на текущий лист.
Давайте разберем, как применить метод ПроверитьВывод():
// Перед началом вывода первой карточки нового ряда проверяем высоту
Если СчетчикКолонок = 1 Тогда
// Формируем массив областей, составляющих полный ряд (в данном случае для одной карточки)
МассивОбластей = Новый Массив;
МассивОбластей.Добавить(ОбластьЗаголовок);
МассивОбластей.Добавить(ОбластьШапка);
МассивОбластей.Добавить(ОбластьТаблица);
МассивОбластей.Добавить(ОбластьПодвал);
// Проверяем, поместится ли эта группа областей на текущую страницу
Если Не ТабДок.ПроверитьВывод(МассивОбластей) Тогда
// Принудительно переносим печать на следующий лист А4
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
КонецЕсли;
Когда вы используете метод Присоединить() для областей сложной структуры (содержащих объединенные ячейки, рамки или разные шрифты), 1С пытается сопоставить ширину колонок исходного макета и результирующего документа. Это часто приводит к деформации и "расползанию" сетки.
Чтобы ширина колонок в каждой присоединенной карточке оставалась неизменной и не зависела от соседних элементов, используйте метод СоздатьФорматСтрок() после вывода каждого полного ряда карточек. Этот метод фиксирует и изолирует форматирование колонок в рамках текущей строки табличного документа:
Если СчетчикКолонок = 1 Тогда
ТабДок.Вывести(ОбластьЗаголовок);
// ... вывод остальных областей ...
Иначе
ТабДок.Присоединить(ОбластьЗаголовок);
// ... присоединение остальных областей ...
КонецЕсли;
// Если ряд завершен (вывели 3 карточки) или это последняя запись в таблице
Если (СчетчикКолонок = 3) Или (ИндексСтроки = ТаблицаВыполнения.Количество() - 1) Тогда
// Изолируем формат колонок для выведенной строки
ТабДок.СоздатьФорматСтрок();
КонецЕсли;
Для того чтобы готовый лист А4 было удобно разрезать на отдельные карточки канцелярским ножом или ножницами, рекомендуется заранее подготовить макет. Задайте внешним границам областей в макете тонкую пунктирную линию серого цвета. При выводе сетки эти линии состыкуются и образуют аккуратную разметку для реза.
Также обязательно включайте свойство автоматического масштабирования табличного документа, чтобы избежать случайного обрезания правых полей принтером:
ТабДок.АвтоМасштаб = Истина;
Применение этого свойства гарантирует, что вся сетка карточек пропорционально ужмется и идеально впишется в установленные поля печати любого принтера.