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