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