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