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