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