Разработка и Конфигурация · 10 мин
Как обратиться к реквизиту формы в 1С
Как обратиться к реквизиту формы в 1С из модуля формы, команды и другой формы: ЭтаФорма, Элементы, Объект, типовые ошибки и примеры кода для управляемых форм.
Реквизит формы в 1С — это данные, которые хранятся внутри формы и не записываются напрямую в базу данных, если речь не идёт об основном реквизите объекта. К ним обращаются из модуля той же формы, из команд, из обработчиков событий и иногда из других форм. Способ обращения зависит от контекста: клиентская или серверная процедура, обычная или управляемая форма, свой реквизит или чужой.
Основная ошибка новичков — путать реквизит формы, реквизит объекта и элемент формы. Реквизит формы хранит значение, элемент формы лишь отображает его на экране, а реквизит объекта (справочника, документа) доступен через свойство Объект. Понимание этой тройки снимает большинство вопросов вида «почему поле не находится».
Ниже разобраны рабочие способы обращения к реквизитам формы в управляемом приложении, показаны примеры кода, типичные ошибки и способы проверки результата.
Чем реквизит формы отличается от элемента формы и реквизита объекта
Перед обращением важно определить, к какому именно сущности вы хотите обратиться. В управляемой форме сосуществуют три разных набора данных, и у каждого свой путь доступа.
Реквизит формы — переменная формы, созданная разработчиком в дереве реквизитов. Она живёт, пока открыта форма. Реквизит объекта — поле прикладного объекта (документа, справочника), доступное через свойство Объект, если объект является основным реквизитом формы. Элемент формы — визуальный контрол (поле ввода, надпись, таблица), связанный с реквизитом через свойство ПутьКДанным.
Три вида данных на форме
Обращение: ЭтаФорма.ИмяРеквизита или просто ИмяРеквизита. Хранится только в форме, в базу не пишется.
Обращение: Объект.ИмяРеквизита. Сохраняется в базе при записи объекта.
Обращение: Элементы.ИмяЭлемента. Управляет отображением: видимость, доступность, заголовок.
Практическое следствие: чтобы изменить значение, меняют реквизит, а не элемент. Чтобы скрыть поле или поменять его заголовок, обращаются к элементу.
Обращение к реквизиту из модуля своей формы
Самый частый сценарий — обращение к реквизиту внутри модуля той формы, где он создан. В управляемой форме реквизиты доступны как свойства объекта УправляемаяФорма, поэтому достаточно указать имя реквизита.
&НаКлиенте
Процедура РассчитатьСумму(Команда)
// Прямое обращение по имени реквизита
СуммаДокумента = Количество * Цена;
// Эквивалент через ЭтаФорма
ЭтаФорма.СуммаДокумента = ЭтаФорма.Количество * ЭтаФорма.Цена;
КонецПроцедуры
Оба варианта равнозначны. Явное указание ЭтаФорма полезно, когда имя реквизита совпадает с именем локальной переменной или когда код читают разработчики с разным опытом — явность снижает риск ошибки.
Если реквизит имеет составной тип или является таблицей значений, обращение идёт по тому же принципу, а дальше используются методы коллекции:
&НаСервере
Процедура ДобавитьСтрокуНаСервере()
НоваяСтрока = ТаблицаТоваров.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("000001");
КонецПроцедуры
Обращение к реквизиту основного объекта через Объект
Когда форма принадлежит документу или справочнику, её основной реквизит доступен через свойство Объект. Через него читают и меняют реквизиты самого прикладного объекта, которые потом будут записаны в базу.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Не ЗначениеЗаполнено(Объект.Ответственный) Тогда
Сообщить("Не заполнен ответственный");
КонецЕсли;
КонецПроцедуры
Важный нюанс клиент-серверного разделения: на клиенте Объект имеет тип ДанныеФормыСтруктура, и часть серверных методов объекта там недоступна. Для серверной логики (запросы, обращения к менеджерам объектов) объект преобразуют:
&НаСервере
Процедура ЗаполнитьНаСервере()
ДокументОбъект = РеквизитФормыВЗначение("Объект");
ДокументОбъект.Заполнить(Неопределено);
ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры
Обращение к элементам формы и программное создание реквизитов
Иногда нужно не значение реквизита, а его визуальное представление: скрыть поле, сделать недоступным, поменять заголовок. Для этого обращаются к коллекции Элементы:
&НаКлиенте
Процедура УправлениеВидимостью()
Элементы.ПолеСкидка.Видимость = (СуммаДокумента > 100000);
Элементы.ПолеСкидка.Заголовок = "Скидка, %";
КонецПроцедуры
Реквизиты формы можно создавать программно через метод ИзменитьРеквизиты. Это делается только на сервере, обычно в обработчике ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Добавляемые = Новый Массив;
Добавляемые.Добавить(Новый РеквизитФормы("ДинамическийПризнак",
Новый ОписаниеТипов("Булево"), "", "Признак"));
ИзменитьРеквизиты(Добавляемые);
ЭтаФорма.ДинамическийПризнак = Истина;
КонецПроцедуры
Обращение к реквизиту другой формы
Обращаться к реквизитам чужой формы напрямую — плохая практика: форма может быть закрыта, а её структура может измениться. Тем не менее технически это возможно, если у вас есть ссылка на форму, например при открытии формы с получением результата.
Правильные способы обмена данными между формами:
- Передача параметров при открытии через структуру параметров и обработка их в ПриСозданииНаСервере;
- Оповещения — Оповестить() в одной форме и ОбработкаОповещения() в другой;
- ОписаниеОповещения при открытии формы в модальном или асинхронном режиме;
- Через владельца формы — свойство ВладелецФормы, если форма открыта из другой формы.
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ВыбранТовар" Тогда
ТекущийТовар = Параметр.Номенклатура;
КонецЕсли;
КонецПроцедуры
Как выбрать способ передачи данных
Контекст выполнения: клиент, сервер и директивы компиляции
Доступность реквизитов зависит от директивы компиляции процедуры. Реквизиты формы доступны и на клиенте, и на сервере, но операции над ними различаются. На клиенте нельзя выполнять запросы и обращаться к менеджерам объектов; на сервере недоступны некоторые интерактивные возможности (предупреждения, диалоги).
Директива &НаСервереБезКонтекста означает, что процедура не имеет доступа к данным формы, включая реквизиты. Такие процедуры используют для вспомогательных функций, которым данные передают параметрами:
&НаСервереБезКонтекста
Функция ПолучитьЦену(Номенклатура)
// Объект и реквизиты формы здесь НЕ доступны
Возврат РегистрыСведений.Цены.ПолучитьПоследнее(ТекущаяДатаСеанса(),
Новый Структура("Номенклатура", Номенклатура)).Цена;
КонецФункции
Как проверить, что обращение работает
После написания кода проверьте результат до передачи изменений в рабочую базу. Базовая проверка занимает несколько минут и отлавливает большинство ошибок.
- Откройте модуль формы в конфигураторе и выполните проверку синтаксиса модуля (кнопка с галочкой) — она отловит обращения к несуществующим реквизитам при явном синтаксисе.
- Запустите базу в режиме отладки, поставьте точку останова в обработчике и посмотрите значение реквизита через табло (Shift+F9).
- Проверьте поведение в обоих контекстах, если процедура вызывается и с клиента, и с сервера.
- Убедитесь, что элемент формы связан с реквизитом: свойство ПутьКДанным элемента должно указывать на имя реквизита, иначе изменение реквизита не отобразится на экране.
Как проверить результат
После изменения реквизита поле на форме сразу показывает новое значение
Значение в отладчике изменилось, а на форме старое — элемент не связан с реквизитом
Проверка модуля проходит без ошибок
Ошибка 'Переменная не определена' — опечатка в имени или реквизит не создан
Процедура &НаСервере видит реквизиты формы
Ошибка доступа — процедура объявлена БезКонтекста
Что важно запомнить
Реквизит формы доступен по имени или через ЭтаФорма, данные объекта — через Объект, визуальные контролы — через Элементы. Серверные преобразования делаются через РеквизитФормыВЗначение только на сервере, а между формами данные передают параметрами и оповещениями, а не прямым обращением.
Частые вопросы
Как обратиться к реквизиту формы по имени, заданному строкой?
Через квадратные скобки: ЭтаФорма["ИмяРеквизита"]. Такой способ удобен, когда имя реквизита формируется динамически, например в цикле по однотипным полям. Учтите, что опечатка в строке обнаружится только в момент выполнения.
Почему реквизит формы виден в отладчике, но не отображается на форме?
Реквизит и элемент формы — разные сущности. Проверьте, что на форме создан элемент (поле ввода) и в его свойстве ПутьКДанным указано имя вашего реквизита. Без привязки элемента значение существует в памяти, но пользователю не показывается.
Можно ли обратиться к реквизиту формы из общего модуля?
Напрямую нет — общий модуль не знает о существовании конкретной формы. Передайте форму или нужные значения параметром в процедуру общего модуля. Если параметром передана форма, к её реквизитам можно обращаться по имени, но такая связность усложняет поддержку кода.
Чем отличается ЭтаФорма от ЭтотОбъект в модуле формы?
В модуле управляемой формы используется ЭтаФорма — это объект типа УправляемаяФорма с доступом к реквизитам, элементам и командам. ЭтотОбъект в модуле формы объекта (внешней обработки) ссылается на сам объект обработки, а не на форму, и реквизитов формы через него не видно.
Как получить реквизит формы списка, например отбор динамического списка?
Основной реквизит формы списка — динамический список, обращение идёт по его имени: Список.Отбор.Элементы. Через коллекцию элементов отбора добавляют или изменяют условия. Настройки компоновки доступны через Список.КомпоновщикНастроек.
Почему после ИзменитьРеквизиты пропали значения реквизитов формы?
Вызов ИзменитьРеквизиты перестраивает дерево реквизитов и может сбросить текущие значения изменённых реквизитов. Если нужно сохранить данные, запомните их в переменные до вызова метода и восстановите после. По возможности выполняйте изменение структуры один раз — в ПриСозданииНаСервере.