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

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

Контекст формы в 1С 8.3: что это и как с ним работать

Что такое контекст формы в 1С 8.3, из чего он состоит, как работать с реквизитами и элементами формы в модуле, типичные ошибки и проверка результата.

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

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

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

Что такое контекст формы простыми словами

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

Ключевые свойства контекста управляемой формы:

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

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

Клиентский и серверный контекст: в чём разница

Управляемая форма в 1С 8.3 физически существует в двух местах: на клиенте (тонкий клиент, веб-клиент) и на сервере. Код модуля размечается директивами компиляции, которые определяют, где будет выполняться процедура:

  • &НаКлиенте — выполняется на клиенте, доступны Элементы, интерактивные операции, но недоступны запросы и прямое чтение из базы;
  • &НаСервере — выполняется на сервере, доступны запросы, менеджеры объектов, но недоступен интерактивный интерфейс;
  • &НаСервереБезКонтекста — серверная процедура без доступа к данным формы (нет ЭтаФорма, Объект, Реквизиты);
  • &НаКлиентеНаСервереБезКонтекста — общий код, доступен только ограниченный набор.

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

Как обращаться к данным формы в коде

Основные приёмы работы с контекстом в модуле управляемой формы:

&НаКлиенте

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

// Обращение к реквизиту формы

Комментарий = "Заполнено программно";

// Обращение к основному объекту (например, документу)

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

// Управление элементом

Элементы.ГруппаДополнительно.Видимость = Ложь;

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

&НаСервере

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

// Преобразование данных формы в прикладной объект

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

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

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

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

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

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

Типичные ошибки при работе с контекстом

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

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

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

Как проверить, что код работает в нужном контексте

Диагностика контекстных ошибок строится на трёх шагах:

  1. Открыть модуль формы и проверить директиву компиляции процедуры — совпадает ли она с теми объектами, к которым идёт обращение.
  2. Проверить дерево реквизитов формы в конфигураторе: есть ли там нужный реквизит и правильно ли указан путь к данным у элемента.
  3. Запустить отладку (F5), поставить точку останова внутри процедуры и посмотреть в табло значения ЭтаФорма, Объект, Элементы — доступны ли они и что содержат.
Контрольные точки

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

Директива компиляции процедуры
Норма

Совпадает с используемыми объектами (запросы — только &НаСервере)

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

Запрос в &НаКлиенте или ЭтаФорма в &НаСервереБезКонтекста

Реквизит в дереве формы
Норма

Реквизит присутствует, тип указан верно

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

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

Путь к данным у элемента
Норма

Свойство ПутьКДанным ссылается на существующий реквизит

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

Поле на форме пустое, изменения в коде не отображаются

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

Значения реквизитов меняются, форма обновляется

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

Значения не видны или обнуляются после серверного вызова

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

Обычные формы и внешние обработки: особенности контекста

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

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

Если серверная процедура должна вернуть несколько значений на клиент, соберите их в структуру и верните одним результатом. Это быстрее и чище, чем менять реквизиты формы по одному или делать несколько вызовов.
ПЗ
Практическое замечание

Когда контекста формы недостаточно

Не всю логику стоит размещать в модуле формы. Признаки того, что код нужно вынести:

  • одна и та же логика нужна нескольким формам — выносите в общий модуль;
  • сложные расчёты и запросы — переносите в модуль объекта или менеджера;
  • обработка не зависит от интерфейса — используйте фоновые задания или серверные общие модули.

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

Итог

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

Контекст формы — это доступные модулю формы объекты: ЭтаФорма, Объект, Реквизиты, Элементы, Параметры. В управляемой форме контекст делится на клиентский и серверный, данные меняют через реквизиты, а не элементы, а для работы с базой используют серверные процедуры и преобразование РеквизитФормыВЗначение.

Частые вопросы

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

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

Почему возникает ошибка «Переменная не определена (ЭтаФорма)»?

Процедура скомпилирована с директивой &НаСервереБезКонтекста или находится в общем модуле, где контекст формы недоступен. Измените директиву на &НаСервере либо передайте форму в процедуру параметром.

Как из клиентской процедуры выполнить запрос к базе?

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

Что возвращает РеквизитФормыВЗначение("Объект")?

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

Можно ли обратиться к контексту другой открытой формы?

Технически — через ПолучитьФорму() или параметр Источник в оповещениях, но это хрупкое решение. Правильнее использовать механизм Оповестить()/ОбработкаОповещения() или передавать данные через параметры при открытии формы.

Почему после серверного вызова данные на форме сбрасываются?

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