При разработке печатных форм в управляемом приложении 1С часто возникает задача выводить различные секции (области) макета в зависимости от выбранного пользователем параметра. Начинающие разработчики сталкиваются с ошибками вида «Переменная не определена» или «Поле объекта не обнаружено» при попытке обратиться к значениям элементов формы непосредственно из модуля менеджера.
В этой статье разберем причину возникновения таких ошибок, проанализируем разницу в контекстах выполнения кода и рассмотрим правильные варианты реализации динамического вывода областей макета.
Проанализируем ситуация, когда на форме документа добавлен переключатель (тумблер), связанный с реквизитом документа ЛокальнаяСетевая (например, со значениями 1 — Локальная, 2 — Сетевая). При попытке обратиться к этому переключателю напрямую в модуле менеджера возникает ошибка.
Причины такого поведения платформы следующие:
Элементы) и контекст объекта (переменная ЭтотОбъект).Рассмотрим стандартный способ формирования печатной формы в модуле менеджера. Чтобы получить значение реквизита документа, необходимо добавить его в текст запроса, обследовать результат выборки и выбрать соответствующую область макета.
Разберем пример кода алгоритма печати:
// 1. Получаем макет документа
Макет = УправлениеПечатью.МакетПечатнойФормы("Документ.МойДокумент.ПФ_MXL_ПечатнаяФорма");
// 2. Формируем запрос для получения данных документа
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| МойДокумент.Ссылка КАК Ссылка,
| МойДокумент.ЛокальнаяСетевая КАК ЛокальнаяСетевая
|ИЗ
| Документ.МойДокумент КАК МойДокумент
|ГДЕ
| МойДокумент.Ссылка В(&МассивДокументов)";
Запрос.УстановитьПараметр("МассивДокументов", МассивОбъектов);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// 3. Выбираем нужную область макета на основе полученного значения
Если Выборка.ЛокальнаяСетевая = 1 Тогда
ОбластьМакета = Макет.ПолучитьОбласть("Обл1");
Иначе
ОбластьМакета = Макет.ПолучитьОбласть("Обл2");
КонецЕсли;
// Заполняем параметры области и выводим в табличный документ
ТабличныйДокумент.Вывести(ОбластьМакета);
КонецЦикла;
Посмотрим на более лаконичный вариант. Если имена областей в макете имеют четкую структуру с числовыми или строковыми окончаниями (например, Обл1, Обл2), то вызывать метод ПолучитьОбласть() можно динамически с помощью конкатенации строк.
Плюсом этого метода является отсутствие громоздких конструкций Если... ИначеЕсли, особенно когда вариантов переключателя много.
Пример динамического обращения к области макета:
Пока Выборка.Следующий() Цикл
// Имя области формируется динамически: "Обл" + 1 или "Обл" + 2
ИмяОбласти = "Обл" + Строка(Выборка.ЛокальнаяСетевая);
ОбластьМакета = Макет.ПолучитьОбласть(ИмяОбласти);
ТабличныйДокумент.Вывести(ОбластьМакета);
КонецЦикла;
Чтобы избежать ошибок при выводе печатных форм и сделать код надежным, учтем следующие правила:
Число (1, 2, 3) для обозначения режимов работы не рекомендуется. Создайте объект метаданных ПеречислениеRef (например, ТипыПодключения со значениями Локальная и Сетевая). Это защитит код от случайных ошибок при сравнении значений.Выборка.Следующий() перед обращением к полям выборки запроса. Без этого вызов Выборка.ЛокальнаяСетевая вызовет ошибку обращения к значению.ПараметрыПечати.