Разработка и Конфигурация · 10 мин
Контекст формы в 1С 8.3: что это и как с ним работать
Что такое контекст формы в 1С 8.3, из чего он состоит, как работать с реквизитами и элементами формы в модуле, типичные ошибки и проверка результата.
Контекст формы в 1С 8.3 — это программное окружение, в котором выполняется код модуля формы и из которого доступны её данные: реквизиты, элементы, команды, параметры и свойства самой формы. Когда разработчик пишет код в модуле формы, он обращается к объектам не «по имени из базы», а через контекст — через предопределённые свойства ЭтаФорма, Объект, Элементы, Параметры и другие. Без понимания контекста невозможно ни изменить данные на форме, ни обработать действия пользователя.
Практическая сложность темы в том, что контекст формы зависит от её типа: обычная форма и управляемая форма устроены по-разному, а код на клиенте и на сервере видит разный набор объектов. Ошибка «Переменная не определена» или «Поле объекта не обнаружено» почти всегда означает, что разработчик обратился к чему-то вне доступного контекста.
Ниже разобрано, из чего состоит контекст управляемой формы, чем отличаются клиентский и серверный контексты, как правильно обращаться к реквизитам и элементам, какие ошибки встречаются чаще всего и как проверить, что код отработал корректно.
Что такое контекст формы простыми словами
Форма в 1С — это не только картинка с полями, а объект с данными и поведением. Контекст — это «точка зрения» кода: какие переменные и объекты ему видны прямо сейчас. В модуле формы разработчик пишет обработчики событий (ПриОткрытии, ПередЗаписью и т.д.), и внутри них доступен строго определённый набор предопределённых свойств.
Ключевые свойства контекста управляемой формы:
ЭтаФорма— сама форма как объект, через неё доступны все её свойства и методы;Объект— основной реквизит формы, например редактируемый документ или элемент справочника (тип ДанныеФормыСтруктура);Элементы— коллекция элементов формы (поля, кнопки, таблицы);Реквизиты— данные формы, добавленные в дерево реквизитов;Параметры— параметры, переданные при открытии формы;Команды— коллекция команд формы;Запись— в формах записей регистров и констант.
Важно понимать: реквизит формы и элемент формы — разные вещи. Реквизит хранит данные, элемент — отображает их на экране. Поле ввода связано с реквизитом через свойство «ПутьКДанным». Изменение реквизита в коде автоматически обновляет связанный элемент, а вот обращение к элементу напрямую (Элементы.Поле1) даёт доступ только к его оформлению и видимости, но не к данным.
Клиентский и серверный контекст: в чём разница
Управляемая форма в 1С 8.3 физически существует в двух местах: на клиенте (тонкий клиент, веб-клиент) и на сервере. Код модуля размечается директивами компиляции, которые определяют, где будет выполняться процедура:
&НаКлиенте— выполняется на клиенте, доступны Элементы, интерактивные операции, но недоступны запросы и прямое чтение из базы;&НаСервере— выполняется на сервере, доступны запросы, менеджеры объектов, но недоступен интерактивный интерфейс;&НаСервереБезКонтекста— серверная процедура без доступа к данным формы (нет ЭтаФорма, Объект, Реквизиты);&НаКлиентеНаСервереБезКонтекста— общий код, доступен только ограниченный набор.
Типичная схема работы: клиентская процедура обрабатывает действие пользователя, при необходимости вызывает серверную, та выполняет запрос или изменяет данные и возвращает результат. Каждый вызов с клиента на сервер — это сетевое обращение, поэтому вызовы внутри цикла резко замедляют форму.
Как обращаться к данным формы в коде
Основные приёмы работы с контекстом в модуле управляемой формы:
&НаКлиенте
Процедура КомандаЗаполнить(Команда)
// Обращение к реквизиту формы
Комментарий = "Заполнено программно";
// Обращение к основному объекту (например, документу)
Объект.СуммаДокумента = 1000;
// Управление элементом
Элементы.ГруппаДополнительно.Видимость = Ложь;
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьНаСервере()
// Преобразование данных формы в прикладной объект
Док = РеквизитФормыВЗначение("Объект");
Док.ЗаполнитьПоУмолчанию();
ЗначениеВРеквизитФормы(Док, "Объект");
КонецПроцедуры
Методы РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы() — мост между контекстом формы и прикладными объектами. Данные формы (ДанныеФормыСтруктура) не являются объектом базы данных: у них нет методов Записать(), нельзя выполнить запрос по ним. Преобразование решает эту задачу, но стоит ресурсов, поэтому в циклах его не выполняют.
Для чтения данных других объектов в серверном контексте используют запросы или методы менеджеров (Справочники.Номенклатура.НайтиПоКоду()), а не обращение к чужим формам. Получить контекст другой открытой формы можно через ПолучитьФорму() или через оповещения, но прямое вмешательство в чужую форму считается плохой практикой.
Типичные ошибки при работе с контекстом
Отдельная группа проблем — обращение к реквизитам, которых нет в форме. Если реквизит объекта не добавлен в дерево реквизитов формы, обращение Объект.НекийРеквизит на клиенте вызовет ошибку. В форме объекта доступны только те данные, которые разработчик явно включил в состав реквизитов.
Ещё одна ошибка — попытка работать с контекстом формы из общего модуля без её передачи. Общий модуль не знает о форме ничего; форму нужно передавать параметром, причём в серверных вызовах передаётся сама УправляемаяФорма, а на клиенте — только ссылка или структура данных.
Как проверить, что код работает в нужном контексте
Диагностика контекстных ошибок строится на трёх шагах:
- Открыть модуль формы и проверить директиву компиляции процедуры — совпадает ли она с теми объектами, к которым идёт обращение.
- Проверить дерево реквизитов формы в конфигураторе: есть ли там нужный реквизит и правильно ли указан путь к данным у элемента.
- Запустить отладку (F5), поставить точку останова внутри процедуры и посмотреть в табло значения
ЭтаФорма,Объект,Элементы— доступны ли они и что содержат.
Как проверить результат
Совпадает с используемыми объектами (запросы — только &НаСервере)
Запрос в &НаКлиенте или ЭтаФорма в &НаСервереБезКонтекста
Реквизит присутствует, тип указан верно
Ошибка «Поле объекта не обнаружено» при обращении
Свойство ПутьКДанным ссылается на существующий реквизит
Поле на форме пустое, изменения в коде не отображаются
Значения реквизитов меняются, форма обновляется
Значения не видны или обнуляются после серверного вызова
Полезный приём: после серверного вызова проверить свойство Модифицированность формы. Если данные изменились, но флаг не взведён, пользователь может закрыть форму без предупреждения о сохранении — это признак некорректной работы с контекстом.
Обычные формы и внешние обработки: особенности контекста
В старых конфигурациях на обычных формах контекст устроен иначе: нет разделения на клиент и сервер, код выполняется целиком на клиенте (толстый клиент), и обращение к реквизитам объекта идёт напрямую, без преобразований. Директивы компиляции там не используются. Это проще, но не масштабируется на тонкий и веб-клиент.
Во внешних обработках с управляемой формой контекст работает так же, как в конфигурации, но есть нюанс: основной реквизит «Объект» имеет тип обработки, и обращение к её табличным частям идёт через Объект.ИмяТабличнойЧасти. При отладке внешней обработки убедитесь, что она открыта именно в режиме управляемого приложения — иначе форма просто не создастся.
Если серверная процедура должна вернуть несколько значений на клиент, соберите их в структуру и верните одним результатом. Это быстрее и чище, чем менять реквизиты формы по одному или делать несколько вызовов.
Когда контекста формы недостаточно
Не всю логику стоит размещать в модуле формы. Признаки того, что код нужно вынести:
- одна и та же логика нужна нескольким формам — выносите в общий модуль;
- сложные расчёты и запросы — переносите в модуль объекта или менеджера;
- обработка не зависит от интерфейса — используйте фоновые задания или серверные общие модули.
Правило простое: в модуле формы остаётся только то, что касается отображения и реакции на действия пользователя. Бизнес-логика в контексте формы затрудняет тестирование и переиспользование кода.
Что важно запомнить
Контекст формы — это доступные модулю формы объекты: ЭтаФорма, Объект, Реквизиты, Элементы, Параметры. В управляемой форме контекст делится на клиентский и серверный, данные меняют через реквизиты, а не элементы, а для работы с базой используют серверные процедуры и преобразование РеквизитФормыВЗначение.
Частые вопросы
Чем отличается реквизит формы от реквизита объекта?
Реквизит объекта — это поле в базе данных (например, «Комментарий» документа). Реквизит формы — данные, существующие только пока открыта форма. В форме объекта основной реквизит «Объект» содержит копию данных объекта, и через него доступны его реквизиты; дополнительные реквизиты формы добавляются разработчиком для служебных целей и в базу не сохраняются.
Почему возникает ошибка «Переменная не определена (ЭтаФорма)»?
Процедура скомпилирована с директивой &НаСервереБезКонтекста или находится в общем модуле, где контекст формы недоступен. Измените директиву на &НаСервере либо передайте форму в процедуру параметром.
Как из клиентской процедуры выполнить запрос к базе?
Напрямую — никак: на клиенте нет доступа к базе данных. Создайте процедуру с директивой &НаСервере, выполните запрос в ней и верните результат на клиент через возвращаемое значение (структуру, массив) или через реквизиты формы.
Что возвращает РеквизитФормыВЗначение("Объект")?
Прикладной объект — например, ДокументОбъект или СправочникОбъект, с которым можно работать как обычно: вызывать методы, обращаться к табличным частям, записывать. Изменения этого объекта не отображаются на форме, пока не выполнено обратное преобразование ЗначениеВРеквизитФормы().
Можно ли обратиться к контексту другой открытой формы?
Технически — через ПолучитьФорму() или параметр Источник в оповещениях, но это хрупкое решение. Правильнее использовать механизм Оповестить()/ОбработкаОповещения() или передавать данные через параметры при открытии формы.
Почему после серверного вызова данные на форме сбрасываются?
Чаще всего потому, что в серверной процедуре выполнено ЗначениеВРеквизитФормы() с объектом, перечитанным из базы, — он перезаписал несохранённые изменения пользователя. Перед перечитыванием сохраняйте текущие данные формы или обновляйте только нужные реквизиты.