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

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

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

Почему не работает глобальная переменная модуля формы

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

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

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

Решение 1. Использование невидимого реквизита формы

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

Если создать реквизит формы с типом ТаблицаЗначений, платформа автоматически трансформирует его в объект типа ДанныеФормыКоллекция, который доступен на сервере. Чтобы обработать такой реквизит как полноценную таблицу значений на сервере, применяют специализированные методы платформы:


&НаСервере
Процедура ЗаполнитьВнутреннююТаблицу()
    // Преобразуем реквизит формы в реальную ТаблицуЗначений
    Таблица = ДанныеФормыВЗначение(РеквизитВнутренняяТаблица, Тип("ТаблицаЗначений"));
    
    // Выполняем действия с таблицей
    НоваяСтрока = Таблица.Добавить();
    НоваяСтрока.Код = 1;
    НоваяСтрока.Наименование = "Тестовая позиция";
    
    // Загружаем результат обратно в данные формы
    ЗначениеВДанныеФормы(Таблица, РеквизитВнутренняяТаблица);
КонецПроцедуры

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

Решение 2. Временное хранилище (рекомендуемый способ)

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

Разберем по шагам, как реализовать этот подход при заполнении выпадающего списка:

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

Посмотрим на практический пример реализации:


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

&НаСервереБезКонтекста
Функция ПолучитьДанныеДляВыбора(ИдентификаторФормы)
    Таблица = Новый ТаблицаЗначений;
    Таблица.Колонки.Добавить("Ссылка");
    Таблица.Колонки.Добавить("ДополнительныеДанные");
    
    Список = Новый СписокЗначений;
    
    // Заполнение таблицы и списка выбора
    Для Индекс = 1 По 5 Цикл
        Стр = Таблица.Добавить();
        Стр.ДополнительныеДанные = "Данные " + Индекс;
        Список.Добавить(Индекс, "Вариант " + Индекс);
    КонецЦикла;
    
    // Помещаем таблицу во временное хранилище формы
    Адрес = ПоместитьВоВременноеХранилище(Таблица, ИдентификаторФормы);
    
    Возврат Новый Структура("Адрес, Список", Адрес, Список);
КонецФункции

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

Решение 3. Использование клиентских коллекций

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

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

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

← На главную