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

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

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

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

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

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

Ниже разобраны рабочие способы чтения реквизитов формы на встроенном языке 1С: прямое обращение, перебор через структуру формы, чтение реквизитов основного объекта, а также типичные ошибки и ограничения тонкого клиента.

Где хранятся реквизиты формы и чем они отличаются от реквизитов объекта

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

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

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

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

&НаКлиенте

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

// Чтение реквизитов формы по имени

ТекущийПериод = ПериодОтчета; // реквизит типа Дата

Признак = ПоказыватьДетали; // реквизит типа Булево

Сообщить("Период: " + ТекущийПериод + ", детали: " + Признак);

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

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

// Из другой формы или модуля

ФормаВладелец = ЭтаФорма.ВладелецФормы;

Если ФормаВладелец <> Неопределено Тогда

ЗначениеОтбора = ФормаВладелец.ТекущийОтбор;

КонецЕсли;

При внешнем обращении проверяйте, что форма ещё открыта: обращение к реквизиту закрытой формы вызовет ошибку. Надёжный признак — проверка Форма.Открыта() перед чтением.

bsl
&НаКлиенте
Процедура ПрочитатьРеквизит(Команда)
    Значение = ЭтаФорма.ИмяРеквизита; // прямое чтение реквизита формы
    Сообщить(Значение);
КонецПроцедуры

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

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

&НаСервере

Процедура ВывестиРеквизитыФормы()

Реквизиты = ЭтаФорма.ПолучитьРеквизиты(); // все реквизиты верхнего уровня

Для Каждого Реквизит Из Реквизиты Цикл

Сообщить(Реквизит.Имя + " : " + Реквизит.ТипЗначения);

КонецЦикла;

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

Метод принимает необязательный параметр — путь к родительскому реквизиту. Так можно получить, например, список колонок таблицы значений, которая сама является реквизитом формы: ПолучитьРеквизиты("ТаблицаТоваров"). Это удобно для динамического обхода колонок без жёсткого перечисления имён.

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

Чтение реквизитов основного объекта формы

В формах документов, справочников и других объектных данных основной реквизит (обычно «Объект») имеет тип «ДанныеФормыСтруктура». Через него читаются все реквизиты самого объекта базы данных:

&НаКлиенте

Процедура ПроверитьЗаполнение(Команда)

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

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

// Табличная часть — тоже через Объект

Для Каждого Строка Из Объект.Товары Цикл

Сообщить(Строка.Номенклатура);

КонецЦикла;

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

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

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

&НаСервере

Функция ПолучитьКомментарийИзБазы()

Возврат Объект.Ссылка.Комментарий; // чтение из БД, а не из формы

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

Чтение реквизитов в обычных формах

В обычных формах (режим обычного приложения) механика проще: нет разделения на клиент и сервер, и реквизиты формы доступны напрямую по имени в любом месте модуля формы. Реквизиты объекта читаются через переменную объекта, которая в модуле формы обычно доступна напрямую или через ЭтотОбъект.

// Обычная форма

Процедура КнопкаНажатие(Элемент)

ЗначениеРеквизита = РеквизитФормы1; // реквизит формы

КонтрагентДок = Контрагент; // реквизит объекта напрямую

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

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

Управляемая vs обычная форма

Управляемая форма

Реквизиты читаются по имени на клиенте и сервере; ПолучитьРеквизиты() — только на сервере; объект через Объект.Имя

Обычная форма

Всё доступно напрямую без разделения контекстов; перебор реквизитов формы штатно не поддержан

Внешнее обращение

Через ПолучитьФорму() или ВладелецФормы с обязательной проверкой, что форма открыта

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

В управляемых формах реквизиты автоматически сериализуются при серверных вызовах: если серверная процедура изменила реквизит формы, клиент увидит новое значение после возврата. Это работает и в обратную сторону — серверная процедура читает актуальные клиентские значения реквизитов.

Ограничение касается типов: на тонком клиенте недоступны некоторые серверные типы (например, «ТаблицаЗначений» как самостоятельный объект вне реквизита формы, запросы, СОМ-объекты). Если реквизит формы имеет такой тип, читать и менять его можно только на сервере. Директивы компиляции &НаСервере и &НаКлиенте должны соответствовать реальному месту чтения.

&НаКлиенте

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

РассчитатьНаСервере(); // сервер читает и меняет реквизиты

Сообщить(РезультатРасчета); // клиент читает уже обновлённый реквизит

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

&НаСервере

Процедура РассчитатьНаСервере()

РезультатРасчета = Объект.Товары.Итог("Сумма");

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

Типичные ошибки
01
Обращение к несуществующему реквизиту — ошибка «Поле объекта не обнаружено»; проверяйте точное имя в дереве реквизитов редактора формы
02
Вызов ПолучитьРеквизиты() на клиенте — метод доступен только на сервере
03
Чтение реквизита закрытой формы извне — сначала проверяйте Открыта()
04
Путаница между реквизитом формы и реквизитом объекта: Объект.Имя и просто Имя — это разные данные
05
Чтение реквизита мутабельного типа (таблица) на клиенте, когда тип доступен только на сервере

Отладка: как быстро посмотреть значения реквизитов

В конфигураторе при отладке формы реквизиты видны через «Табло» или «Вычислить выражение» (Shift+F9): достаточно ввести имя реквизита или ЭтаФорма и раскрыть дерево свойств. Для реквизитов-таблиц удобно вычислять Объект.Товары.Количество() и смотреть отдельные строки по индексу.

Программно для диагностики полезен временный вывод структуры формы в журнал регистрации или в сообщения — особенно когда форма собирается динамически и состав реквизитов зависит от настроек. Комбинация ПолучитьРеквизиты() на сервере и прямого чтения по имени покрывает практически все диагностические задачи.

Контрольные точки

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

Чтение реквизита в модуле формы
Норма

Значение возвращается без ошибки и соответствует типу

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

«Поле объекта не обнаружено» — имя не совпадает или реквизит не создан

Перебор через ПолучитьРеквизиты()
Норма

Возвращён массив с описаниями всех реквизитов

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

Ошибка метода — код выполняется на клиенте

Чтение данных объекта
Норма

Объект.ИмяРеквизита возвращает значение из формы

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

Пустое значение при заполненном документе — читается из БД устаревшая ссылка вместо данных формы

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

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

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

Почему ПолучитьРеквизиты() выдаёт ошибку «Метод объекта не обнаружен»?

Метод доступен только в серверном контексте управляемой формы. Если процедура помечена директивой &НаКлиенте, перенесите вызов в серверную процедуру или перечислите нужные реквизиты вручную по известным именам.

Чем отличается реквизит формы от элемента формы?

Реквизит — это данные (значение), элемент — визуальный контрол (поле ввода, кнопка, таблица), который отображает реквизит. Читать данные нужно из реквизита, а не из элемента: элемент может быть скрыт или вовсе удалён, а реквизит при этом сохраняет значение.

Можно ли прочитать реквизит формы, не открывая её?

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

Как прочитать колонки таблицы значений, которая является реквизитом формы?

На сервере вызовите ПолучитьРеквизиты("ИмяТаблицы") — метод вернёт описания колонок. Для чтения данных строк используйте индексацию: ТаблицаФормы[0].ИмяКолонки или цикл Для Каждого Строка Из ТаблицаФормы.

Почему на клиенте реквизит объекта пустой, хотя в базе он заполнен?

Вероятно, вы читаете значение из базы через ссылку (Объект.Ссылка.Имя), а пользователь изменил поле на форме, но ещё не записал документ. Данные формы и данные базы в этот момент различаются — читайте через Объект.Имя, чтобы получить актуальное редактируемое значение.

Итог

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

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