К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как получить реквизит формы в 1С

Как получить реквизит формы в 1С: обращение по имени, ЭтаФорма, реквизиты объекта и динамические реквизиты. Примеры кода, типичные ошибки и проверка результата.

Получение реквизита формы — одна из базовых операций при разработке на платформе 1С:Предприятие. Реквизиты формы хранят данные, которые отображаются на экране: значения полей, таблицы, служебные параметры. Способ обращения зависит от типа формы (управляемая или обычная), контекста выполнения кода (клиент или сервер) и того, откуда именно вы пытаетесь получить значение — из модуля самой формы, из другой формы или из внешнего кода.

Основная сложность у начинающих разработчиков — путаница между реквизитом формы, реквизитом объекта (например, документа) и элементом формы. Это три разные сущности: реквизит формы — данные в памяти формы, реквизит объекта — поле данных прикладного объекта, а элемент формы — визуальный контрол, который лишь отображает значение. Получить значение можно через любой из этих уровней, но правильный путь — через реквизит, а не через элемент.

Ниже разобраны рабочие способы получения реквизита формы с примерами кода, условиями выбора подхода и типичными ошибками, которые приводят к падению кода или получению устаревших значений.

Как устроены реквизиты формы и чем они отличаются от элементов

Реквизит формы — это именованное значение, которое форма хранит в памяти в течение сеанса работы с ней. Реквизиты создаются в конфигураторе на закладке «Реквизиты» редактора формы или добавляются программно методом ИзменитьРеквизиты(). У каждого реквизита есть имя, тип и, при необходимости, признак «Ключевой» или связь с данными объекта.

Элемент формы — это визуальный объект: поле ввода, надпись, таблица. Элемент привязывается к реквизиту через свойство ПутьКДанным. Один реквизит может отображаться несколькими элементами, а может не отображаться вовсе — например, служебный реквизит «АдресВоВременномХранилище» обычно не выводят на форму.

Практический вывод: читать и писать данные нужно через реквизит, а не через элемент. Обращение к элементу ради значения (Элементы.Поле1.Значение) — признак ошибочного подхода в управляемых формах: у большинства элементов нет свойства «Значение», и код просто не выполнится.

Получение реквизита внутри модуля формы

Самый частый случай — код находится в модуле той же формы, где объявлен реквизит. В управляемой форме реквизиты доступны как свойства объекта формы, поэтому достаточно обратиться по имени:

&НаКлиенте

Процедура ПоказатьСкидку(Команда)

ТекущаяСкидка = Скидка; // реквизит формы "Скидка"

Сообщить("Текущая скидка: " + ТекущаяСкидка);

КонецПроцедуры

Если имя реквизита заранее неизвестно и формируется динамически (например, «Поле_1», «Поле_2» и так далее), используют обращение через строковый индекс:

Значение = ЭтаФорма["Поле_" + НомерПоля];

Такой приём типичен для форм с программно создаваемыми реквизитами. Перед обращением стоит убедиться, что реквизит существует, иначе получите ошибку «Поле объекта не обнаружено». Проверить наличие можно перебором массива, возвращаемого методом ПолучитьРеквизиты():

Функция РеквизитСуществует(ИмяРеквизита)

Для Каждого Рекв Из ПолучитьРеквизиты() Цикл

Если Рекв.Имя = ИмяРеквизита Тогда

Возврат Истина;

КонецЕсли;

КонецЦикла;

Возврат Ложь;

КонецФункции

Получение реквизита основного объекта формы

У формы документа, справочника или записи регистра есть основной реквизит, обычно с именем «Объект». Через него обращаются к реквизитам самого прикладного объекта:

НомерДокумента = Объект.Номер;

КонтрагентДокумента = Объект.Контрагент;

СуммаПоТабличнойЧасти = Объект.Товары.Итог("Сумма");

Здесь важно понимать разницу: Объект.Контрагент — это данные редактируемого документа, а не реквизит формы. Меняя Объект.Контрагент, вы меняете данные объекта в буфере формы, и при записи они уйдут в базу. Если же вы создали отдельный реквизит формы «КонтрагентОтбор» для отбора списка, он с данными объекта никак не связан и при записи документа никуда не сохранится.

На клиенте тип основного реквизита — ДанныеФормыСтруктура, поэтому недоступны серверные методы объекта (например, Объект.Записать() или обращение к менеджеру объекта). Если нужна логика объекта — выносите её в серверную процедуру.

Разница между клиентским и серверным контекстом

В управляемой форме код делится на клиентский и серверный, и это прямо влияет на способ получения реквизитов. Чтение простого реквизита (число, строка, ссылка) работает одинаково в обоих контекстах. Проблемы начинаются там, где данные существуют только на одной стороне.

На сервере доступны: преобразование формы в объект через РеквизитФормыВЗначение("Объект"), методы ПолучитьРеквизиты(), ИзменитьРеквизиты(), обращение к базе данных. На клиенте доступны: элементы формы, интерактивные действия, диалоги. Если процедура с директивой &НаКлиенте пытается вызвать серверный метод — получите ошибку компиляции модуля.

Типичный рабочий шаблон: клиентская процедура собирает значения реквизитов формы и передаёт их параметрами в серверную процедуру, которая выполняет запросы и возвращает результат:

&НаКлиенте

Процедура Рассчитать(Команда)

РезультатРасчета = РассчитатьНаСервере(Количество, Цена);

КонецПроцедуры

&НаСервере

Функция РассчитатьНаСервере(Количество, Цена)

Возврат Количество * Цена;

КонецФункции

Получение реквизита динамически созданной формы

Когда реквизиты добавляются программно через ИзменитьРеквизиты(), обращение к ним идёт теми же способами, но есть нюансы. Метод ИзменитьРеквизиты() работает только на сервере, обычно его вызывают в ПриСозданииНаСервере или по команде:

&НаСервере

Процедура ДобавитьРеквизит()

Добавляемые = Новый Массив;

Добавляемые.Добавить(Новый РеквизитФормы("КомментарийРасчета",

Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(200))));

ИзменитьРеквизиты(Добавляемые);

КонецПроцедуры

После добавления реквизит доступен как ЭтаФорма["КомментарийРасчета"]. Чтобы пользователь его увидел, нужно ещё программно создать элемент формы и привязать его к реквизиту через ПутьКДанным. Без элемента реквизит существует, но невидим — это нормально для служебных данных.

Помните: динамически добавленные реквизиты не сохраняются между сеансами открытия формы. При переоткрытии формы их нужно создавать заново, а значения — восстанавливать из своего источника (хранилища настроек, параметров, базы данных).

Как получить значение из другой формы

Прямое обращение к реквизитам чужой формы — антипаттерн: форма может быть закрыта, её реквизиты могут измениться, а связь кода становится хрупкой. Платформа предлагает штатные механизмы обмена данными между формами.

Первый способ — параметры при открытии. Значения передаются в ОткрытьФорму() и читаются в ПриСозданииНаСервере через Параметры.ИмяПараметра. Второй способ — возврат значения: форма открывается методом ОткрытьФорму с описанием оповещения, а при закрытии вызывает Закрыть(Результат), и результат приходит в обработчик оповещения вызывающей формы.

&НаКлиенте

Процедура ВыбратьКонтрагента(Команда)

Оповещение = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтаФорма);

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", , ЭтаФорма, , , ,

Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

КонецПроцедуры

&НаКлиенте

Процедура ПослеВыбораКонтрагента(Результат, ДопПараметры) Экспорт

Если Результат <> Неопределено Тогда

Контрагент = Результат; // записали в реквизит формы

КонецЕсли;

КонецПроцедуры

Третий способ — Оповестить() и ОбработкаОповещения() для связи уже открытых форм. Выбирайте по ситуации: параметры — для передачи «на вход», оповещение о закрытии — для возврата результата выбора, Оповестить — для синхронизации открытых окон.

Маршрут решения

Как выбрать способ

Код в модуле той же формы, имя известноОбращайтесь по имени: ИмяРеквизита или Объект.ИмяРеквизита
Имя реквизита формируется в кодеИспользуйте ЭтаФорма[ИмяСтрокой] с предварительной проверкой существования
Нужно значение из другой формы при её открытииПередавайте через параметры ОткрытьФорму
Нужен результат выбора из дочерней формыИспользуйте ОписаниеОповещения и Закрыть(Результат)
Нужно значение объекта как прикладного типаНа сервере вызовите РеквизитФормыВЗначение(ИмяОбъекта)

Типичные ошибки и проверка результата

Самая частая ошибка — «Поле объекта не обнаружено». Причины: опечатка в имени реквизита, попытка обратиться к реквизиту объекта без «Объект.», обращение к динамическому реквизиту до его создания. Проверяйте точное имя в редакторе формы и момент создания реквизита.

Вторая группа ошибок — контекстные: вызов ПолучитьРеквизиты() на клиенте, передача ЭтаФормы в серверную процедуру, обращение к Элементам формы на сервере без необходимости. Диагностируется по тексту ошибки компиляции модуля или исполнения.

Третья группа — логические: чтение реквизита до того, как он заполнен (например, в ПриСозданииНаСервере значение из параметров ещё не перенесено в реквизит), или чтение устаревшего значения после изменения данных другой формой без оповещения.

Типичные ошибки
01
Обращение к элементу формы вместо реквизита — код падает, так как у поля ввода нет свойства Значение
02
Чтение реквизита до его заполнения в ПриСозданииНаСервере — получаете пустое значение
03
Передача ЭтаФормы на сервер — ошибка сериализации, передавайте только значения
04
Опечатка в строковом имени при ЭтаФорма[Имя] — ошибка обнаруживается только в момент выполнения
05
Прямое обращение к реквизитам чужой формы — код ломается при закрытии или изменении той формы
Контрольные точки

Как проверить результат

Значение реквизита после чтения
Норма

Переменная содержит ожидаемое значение нужного типа

Тревожный признак

Неопределено, пустая строка или значение другого типа

Работа в отладчике
Норма

Точка останова показывает реквизит в табло с корректным значением

Тревожный признак

Ошибка Поле объекта не обнаружено

Поведение после записи объекта
Норма

Данные объекта сохраняются в базе

Тревожный признак

Изменения теряются — значит, меняли реквизит формы, а не Объект

Передача между клиентом и сервером
Норма

Серверная процедура получает параметры и возвращает результат

Тревожный признак

Ошибка сериализации или компиляции модуля

Часто задаваемые вопросы

Как получить список всех реквизитов формы программно?

На сервере вызовите ЭтаФорма.ПолучитьРеквизиты() — вернётся массив объектов РеквизитФормы со свойствами Имя, ТипЗначения, Путь. Метод недоступен на клиенте, поэтому список формируют в серверной процедуре и при необходимости передают на клиент, например, массивом имён.

Почему ЭтаФорма.ИмяРеквизита и просто ИмяРеквизита работают одинаково?

В модуле управляемой формы реквизиты доступны как неявные свойства контекста, поэтому оба варианта корректны. Явное ЭтаФорма.ИмяРеквизита улучшает читаемость и помогает отладчику, а для строкового имени обязателен синтаксис ЭтаФорма[ИмяСтрокой].

Как получить реквизит табличной части объекта на форме?

Через основной реквизит: Объект.ИмяТабличнойЧасти — это коллекция строк. Текущую строку на клиенте берут из элемента таблицы: Элементы.Товары.ТекущиеДанные. Итоги считают методом Итог("ИмяКолонки") на сервере или перебором строк на клиенте.

Можно ли получить реквизит формы из внешней обработки или общего модуля?

Напрямую — нет, если у вас нет ссылки на объект формы. Если форма передана как параметр (УправляемаяФорма), обращение идёт через Форма.ИмяРеквизита или Форма[ИмяСтрокой], но такая связь допустима только между связанными формами и требует аккуратности: форма может быть уже закрыта.

Чем отличается РеквизитФормыВЗначение от прямого чтения реквизита?

Прямое чтение даёт значение в формате данных формы (ДанныеФормыСтруктура), где недоступны методы прикладного объекта. РеквизитФормыВЗначение("Объект") создаёт на сервере полноценный объект (например, ДокументОбъект), у которого можно вызывать методы и который можно записать. Обратное преобразование — ЗначениеВРеквизитФормы.

Почему после ИзменитьРеквизиты обращение к новому реквизиту даёт ошибку?

Чаще всего обращение происходит в другом контексте или до завершения вызова ИзменитьРеквизиты. Убедитесь, что добавление и чтение выполняются в одной серверной процедуре либо чтение идёт после возврата из неё, и что имя при обращении совпадает с именем, заданным в конструкторе РеквизитФормы, символ в символ.

Итог

Что важно запомнить

Внутри формы реквизит читают по имени или через ЭтаФорма[ИмяСтрокой], данные объекта — через Объект.ИмяРеквизита. Между клиентом и сервером передают только значения, а не саму форму. Данные между формами передают параметрами и оповещениями, а не прямым доступом к чужим реквизитам. Перед динамическим обращением проверяйте существование реквизита.