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

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

Как обращаться к реквизитам формы в 1С

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

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

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

Материал ориентирован на платформу 1С:Предприятие 8.3 с управляемыми формами — именно они используются в современных конфигурациях. Отдельно разобраны особенности обычных форм и работа с табличными частями, поскольку там синтаксис заметно отличается.

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

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

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

Типовая ошибка новичка — попытаться прочитать значение через элемент: Значение = Элементы.Контрагент.ТекстРедактирования;. Такой приём работает нестабильно и зависит от состояния редактирования. Правильно читать данные из реквизита: Значение = Объект.Контрагент;.

Обращение к реквизитам в управляемой форме

В модуле управляемой формы доступен контекст ЭтаФорма (в английском синтаксисе — ThisForm). К любому реквизиту формы можно обратиться двумя способами: напрямую по имени или через ЭтаФорма. Оба варианта равнозначны:

// Два эквивалентных обращения

СуммаИтого = СуммаДокумента;

СуммаИтого = ЭтаФорма.СуммаДокумента;

// Присвоение значения реквизиту

КомментарийПользователя = "Проверено";

ЭтаФорма.ФлагОтправки = Истина;

Обращение по имени короче, но явное ЭтаФорма. делает код понятнее при чтении — сразу видно, что это реквизит формы, а не локальная переменная. В серверных процедурах с директивой &НаСервере синтаксис тот же, контекст формы доступен полностью.

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

Работа с основным реквизитом Объект

Основной реквизит формы документа, справочника или задачи называется Объект. Его тип — «ДанныеФормыСтруктура» на основе соответствующего объекта конфигурации. Через него читают и изменяют реквизиты редактируемого элемента:

// Чтение реквизитов объекта

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

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

// Изменение реквизита объекта

Объект.Комментарий = "Согласовано";

// Ссылка на объект в базе

ТекущаяСсылка = Объект.Ссылка;

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

&НаСервере

Процедура ВызватьМетодОбъекта()

ДокументОбъект = РеквизитФормыВЗначение("Объект");

ДокументОбъект.ЗаполнитьПоУмолчанию();

ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");

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

Обращение к табличным частям и таблицам значений

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

// Перебор строк табличной части

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

СтрокаТовара.Сумма = СтрокаТовара.Цена * СтрокаТовара.Количество;

КонецЦикла;

// Первая строка и её поле

Если Объект.Товары.Количество() > 0 Тогда

ПерваяНоменклатура = Объект.Товары[0].Номенклатура;

КонецЕсли;

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

Текущую строку таблицы, выделенную пользователем, получают через элемент формы: Элементы.Товары.ТекущиеДанные (в клиентском контексте) или Элементы.Товары.ТекущаяСтрока (идентификатор строки, работает и на сервере). Это один из немногих случаев, когда обращение к элементу для получения данных оправдано.

Как получить данные выделенной строки таблицы
  1. 1
    В клиентской процедуре обратитесь к Элементы.ИмяТаблицы.ТекущиеДанные
  2. 2
    Проверьте, что результат не Неопределено (строка может быть не выбрана)
  3. 3
    Читайте поля строки: ТекущиеДанные.Номенклатура, ТекущиеДанные.Количество
  4. 4
    Для серверной обработки передайте Элементы.ИмяТаблицы.ТекущаяСтрока и получите строку через Объект.Товары.НайтиПоИдентификатору()

Клиент и сервер: ограничения контекста

В управляемых формах код делится директивами компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста. Реквизиты формы доступны в клиентском и серверном контексте формы, но не доступны в процедурах БезКонтекста — там нет ЭтаФорма и данных формы вообще. Именно поэтому попытка обратиться к Объект.Номер в серверной процедуре без контекста даёт ошибку компиляции.

Тонкий клиент и веб-клиент поддерживают не все типы. Например, на клиенте нельзя создать ТаблицаЗначений или выполнить запрос — такие операции выносят на сервер, а реквизит формы используют как транспорт: заполнили на сервере, отобразили на клиенте. При вызове серверной процедуры из клиентской данные формы сериализуются и передаются автоматически, если процедура объявлена с контекстом формы.

Частая проблема производительности — лишние серверные вызовы в цикле. Если нужно обработать сто строк табличной части, не вызывайте серверную процедуру для каждой строки: соберите данные в массив или обработайте всю таблицу одним вызовом &НаСервере.

Контексты выполнения в форме

&НаКлиенте

Доступны реквизиты формы и Элементы. Нельзя: запросы, прямое обращение к базе, многие серверные типы.

&НаСервере

Полный доступ к реквизитам формы, запросам, РеквизитФормыВЗначение. Нельзя: интерактивные диалоги, Элементы ограниченно.

&НаСервереБезКонтекста

Нет доступа к реквизитам формы вообще. Данные передаются только через параметры и возвращаемые значения.

Обычные формы и обращение извне

В обычных формах (режим совместимости, старые конфигурации) синтаксис проще и другой: реквизиты объекта доступны напрямую по имени без Объект., потому что модуль формы имеет расширение объекта. Например, в форме документа пишут просто Контрагент = Справочники.Контрагенты.НайтиПоКоду("001");. Табличные части доступны так же по имени: Товары.Добавить().

Обращение к реквизитам формы извне — из другой формы или общего модуля — требует получения самой формы. В управляемом интерфейсе это делается через ПолучитьФорму() или через параметры оповещения:

// Из модуля, где есть ссылка на форму-владельца

ФормаДокумента = ПолучитьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента");

ФормаДокумента.ДополнительныйКомментарий = "Заполнено программно";

ФормаДокумента.Открыть();

Более корректный способ взаимодействия между уже открытыми формами — оповещения: Оповестить("ИзмененКонтрагент", Параметры, ЭтаФорма) в одной форме и обработчик ОбработкаОповещения в другой. Прямое изменение чужих реквизитов работает, но создаёт жёсткую связанность форм и усложняет сопровождение.

Типовые ошибки и их диагностика

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

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

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

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

Проверка результата и FAQ

Убедиться, что обращение к реквизиту написано правильно, проще всего через отладчик: поставьте точку останова, откройте «Табло» и введите выражение ЭтаФорма.ИмяРеквизита — если значение вычисляется, путь верный. Дополнительно проверьте, что после изменения реквизита элементы формы обновились: управляемая форма перерисовывает связанные элементы автоматически, и если поле на экране не изменилось, скорее всего изменён не тот реквизит, на который ссылается «ПутьКДанным» элемента.

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

Как проверить корректность обращения

Выражение в табло отладчика
Норма

Значение вычисляется и совпадает с отображаемым в форме

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

Ошибка «Поле объекта не обнаружено» или Неопределено

Изменение реквизита из кода
Норма

Поле на форме обновилось сразу после выполнения строки

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

На экране старое значение — изменён другой реквизит или элемент

Сохранение объекта
Норма

После записи и повторного открытия данные на месте

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

Данные пропали — изменялся вспомогательный реквизит, а не Объект

Чем отличается ЭтаФорма.Реквизит от просто Реквизит?

Функционально ничем — оба обращения ведут к одному реквизиту формы. Явное ЭтаФорма улучшает читаемость, так как сразу показывает, что это реквизит формы, а не локальная переменная процедуры. В обычных формах синтаксис ЭтаФорма тоже доступен.

Как обратиться к реквизиту формы из внешней обработки?

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

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

Некоторые типы реквизитов не передаются на тонкий или веб-клиент — например, ТаблицаЗначений в старых версиях платформы или реквизиты с типами, не сериализуемыми для клиента. Проверьте тип реквизита и при необходимости замените его на поддерживаемый (например, ДанныеФормыКоллекция) либо обрабатывайте данные только на сервере.

Как программно добавить реквизит формы и обратиться к нему?

На сервере вызовите ИзменитьРеквизиты() с массивом объектов ДобавляемыйРеквизит, затем создайте связанный элемент через Элементы.Добавить(). Обращение к такому реквизиту стандартное — ЭтаФорма.ИмяРеквизита. Учтите, что метод ИзменитьРеквизиты нельзя вызывать в обработчике ПриСозданииНаСервере повторно при тех же именах — будет ошибка дублирования.

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

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

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

Да. Основной реквизит формы списка — динамический список, доступный как Список (или ЭтаФорма.Список). Через него настраивают отбор: Список.Отбор.Элементы, порядок и группировку. Текущая строка списка — Элементы.Список.ТекущаяСтрока, она содержит ссылку на выделенный объект.

Итог

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

Данные формы хранятся в реквизитах, элементы только отображают их. К реквизитам обращаются по имени или через ЭтаФорма, к данным объекта — через Объект.ИмяРеквизита. Учитывайте контекст выполнения: в &НаСервереБезКонтекста реквизиты формы недоступны, а на клиенте ограничен набор типов.