Как объявить и инициализировать общую переменную в модуле управляемой формы 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Причина ошибки: контекст компиляции по умолчанию

Проанализируем классическую ошибку. Разработчик объявляет переменную в самом начале модуля формы обработки или документа без явного указания директив:


Перем ФайлПрочитан;

&НаКлиенте
Процедура Процедура1()
    Если Не ФайлПрочитан Тогда
        // Ошибка: Переменная не определена (ФайлПрочитан)
    КонецЕсли;
КонецПроцедуры;

Выясним причину такого поведения платформы. Если перед объявлением переменной или процедуры в модуле управляемой формы не указана директива компиляции, платформа по умолчанию считает ее серверной (&НаСервере). Таким образом, необъявленная явно переменная компилируется исключительно в серверном контексте. При попытке прочитать или изменить ее значение из клиентской процедуры &НаКлиенте система сообщает об ошибке, так как на тонком клиенте этой переменной попросту не существует.

Правильное объявление переменных модуля формы

Для того чтобы переменная была доступна процедурам нужного контекста, перед ключевым словом Перем необходимо явно указать соответствующую директиву компиляции. Посмотрим на корректный пример для клиентского контекста:


&НаКлиенте
Перем ФайлПрочитан;

&НаКлиенте
Процедура ПрочитатьФайл()
    ФайлПрочитан = Истина;
КонецПроцедуры;

Если логика требует наличия переменной как на клиенте, так и на сервере, разрешается объявить переменные с одинаковым именем под разными директивами:


&НаКлиенте
Перем ИдентификаторСессии;

&НаСервере
Перем ИдентификаторСессии;

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

Инициализация переменных в секции основной программы

Рассмотрим вопрос начального присвоения значений. Нередко разработчики пишут код инициализации в самом конце модуля — в секции так называемой «основной программы» (вне процедур и функций). Попытка применить здесь директивы компиляции приведет к синтаксической ошибке, поскольку директивы вроде &НаКлиенте предназначены исключительно для процедур, функций и объявлений Перем.

Для разделения кода инициализации в теле модуля используются инструкции препроцессора #Если Клиент Тогда и #Если Сервер Тогда. Разберем рабочий пример:


&НаКлиенте
Перем НачальноеЧисло;

&НаСервере
Перем НачальноеЧисло;

&НаСервере
Процедура ЗапуститьНаСервере()
    Сообщить(НачальноеЧисло);
КонецПроцедуры

&НаКлиенте
Процедура Запустить(Команда)
    Сообщить(НачальноеЧисло);
    ЗапуститьНаСервере();
КонецПроцедуры

#Если Клиент Тогда 
    НачальноеЧисло = 101;
#КонецЕсли

#Если Сервер Тогда 
    НачальноеЧисло = 202;
#КонецЕсли

При выполнении команды Запустить на экран будут последовательно выведены значения 101 (из клиентской переменной) и 202 (из серверной переменной).

Особенности жизненного цикла серверных переменных

Обратим особое внимание на критическое ограничение платформы 1С:Предприятие при работе с переменными формы:

  1. Клиентская переменная (&НаКлиенте) сохраняет свое состояние на протяжении всей работы открытой формы в памяти сеанса пользователя.
  2. Серверная переменная (&НаСервере) живет только в рамках одного серверного вызова! Как только контекстный серверный вызов завершается и управление возвращается клиенту, контекст сервера уничтожается. При следующем обращении к серверу переменная будет создана заново, а код инициализации в секции основной программы отработает повторно.
  3. В модулях управляемых форм запрещено использовать ключевое слово Экспорт при объявлении переменных.

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

Рекомендуемые способы хранения и инициализации данных

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

  1. Реквизиты формы: если значение должно быть доступно и на клиенте, и на сервере, а также сохранять свое состояние между вызовами, создайте реквизит формы на соответствующей вкладке редактора. Он доступен в любой процедуре через прямое обращение по имени и синхронизируется между клиентом и сервером автоматически.
  2. Инициализация в стандартных обработчиках: начальные значения для серверных данных рекомендуется задавать в предопределенном событии ПриСозданииНаСервере или ПриЧтенииНаСервере, а для клиентских данных — в событии формы ПриОткрытии.
  3. Временное хранилище: если между серверными вызовами необходимо сохранить сложный объект (например, ТаблицаЗначений или двоичные данные), который не требуется передавать на тонкий клиент, используйте метод ПоместитьВоВременноеХранилище() с передачей свойства УникальныйИдентификатор текущей формы. На клиенте в этом случае хранится только строка с адресом хранилища.
← На главную