Как в управляемой форме 1С передать данные между разными серверными вызовами?

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

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

Почему теряется значение переменной? Ключевая концепция — Stateless сервер

Основная причина, по которой простая переменная модуля не сохраняет свое значение между вызовами, кроется в архитектуре клиент-серверного взаимодействия 1С. Сервер 1С является stateless, то есть "не хранит состояние". Это означает, что каждый вызов с клиента на сервер (любая процедура с директивой &НаСервере) — это изолированная, независимая операция.

Проанализируем жизненный цикл:

  1. Когда вы вызываете ПриСозданииНаСервере, на сервере создается контекст формы, выполняются ваши действия (например, МояПеременная = 15), и весь контекст (данные реквизитов формы) отправляется на клиент. После этого сервер "забывает" всё, что происходило в этом вызове, включая значения локальных и модульных переменных.
  2. Форма живет на клиенте. Пользователь что-то делает и нажимает "Записать".
  3. Клиент инициирует новый вызов на сервер, например, ПередЗаписьюНаСервере. Для этого он упаковывает данные реквизитов формы и отправляет их на сервер.
  4. Сервер получает эти данные, создает совершенно новый контекст для обработки этого вызова и выполняет код процедуры. Он ничего не знает о значении переменной МояПеременная, так как она не была частью данных, переданных с клиента.

Таким образом, для сохранения данных между серверными вызовами нужно использовать механизмы, которые платформа специально для этого предоставляет. Рассмотрим их подробно.

Решение 1: Реквизит формы (стандартный и рекомендуемый способ)

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

Как это сделать:

  1. Откройте форму в конфигураторе.
  2. Перейдите на вкладку "Реквизиты" в дереве элементов формы.
  3. Добавьте новый реквизит, например, с именем МойПараметр и нужным типом (например, "Число").
  4. Теперь этот реквизит доступен в любом месте модуля формы.

Посмотрим на пример кода. В процедуре создания формы присваиваем значение, а в процедуре записи — читаем его.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Присваиваем значение нашему новому реквизиту
    МойПараметр = 15;
    
КонецПроцедуры

&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Обращаемся к реквизиту формы и используем его значение
    Если МойПараметр = 15 Тогда
        Сообщить("Параметр успешно передан и прочитан!");
    КонецЕсли;
    
КонецПроцедуры

Важное замечание: Иногда разработчики опасаются создавать реквизиты из-за мнимой экономии памяти. В современных системах это опасение абсолютно необоснованно. Любой другой способ хранения данных также потребует ресурсов, а использование стандартного механизма реквизитов является наиболее производительным и надежным решением.

Решение 2: Программное создание реквизита

Если по каким-то причинам (например, для сохранения чистоты дерева реквизитов в конфигураторе или если реквизит нужен только при определенных условиях) вы не хотите добавлять реквизит статически, его можно создать программно при открытии формы.

Для этого используется метод формы ИзменитьРеквизиты().


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Создаем массив для новых реквизитов
    МассивНовыхРеквизитов = Новый Массив;
    
    // Создаем описание нового реквизита формы
    // Указываем имя "МойПараметр" и тип "Число"
    НовыйРеквизит = Новый РеквизитФормы("МойПараметр", Новый ОписаниеТипов("Число"));
    
    // Добавляем описание в массив
    МассивНовыхРеквизитов.Добавить(НовыйРеквизит);
    
    // Вызываем метод, который добавит реквизиты в форму
    ИзменитьРеквизиты(МассивНовыхРеквизитов);
    
    // Теперь мы можем работать с этим реквизитом как с обычным
    ЭтаФорма.МойПараметр = 15;
    
КонецПроцедуры

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

Решение 3: Временное хранилище (для сложных случаев)

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

Схема работы следующая:

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

Рассмотрим на подробном примере.


// В самом начале модуля объявляем клиентскую переменную для хранения адреса
&НаКлиенте
Перем АдресВременногоХранилища;

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    ПеременнаяДляПередачи = 15;
    
    // Помещаем значение в хранилище. 
    // Второй параметр - УникальныйИдентификатор формы. Это очень важно!
    // Он привязывает время жизни данных в хранилище ко времени жизни формы.
    // Когда форма закроется, данные будут автоматически удалены с сервера.
    АдресВременногоХранилища = ПоместитьВоВременноеХранилище(ПеременнаяДляПередачи, УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    
    // Перед записью вызываем специальную серверную процедуру
    // и передаем ей сохраненный адрес
    ПрочитатьДанныеНаСервере(АдресВременногоХранилища);
    
КонецПроцедуры

&НаСервере
Процедура ПрочитатьДанныеНаСервере(Адрес)

    // Получаем значение из хранилища по адресу
    ПолученноеЗначение = ПолучитьИзВременногоХранилища(Адрес);
    
    // Проверяем, что данные получены (они могли быть удалены по таймауту)
    Если ПолученноеЗначение <> Неопределено Тогда
        // Используем полученное значение
        Сообщить("Получено значение из временного хранилища: " + ПолученноеЗначение);
    КонецЕсли;

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

Этот метод более громоздкий, но и более мощный. Он дает полный контроль над передачей данных и является незаменимым инструментом для решения нетривиальных задач.

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

← На главную