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