Как сохранить Таблицу Значений (ТЗ) и Дерево Значений (ДЗ) в управляемой форме 1С?

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

При разработке на платформе 1С часто возникает стандартная задача: перед открытием формы мы делаем ресурсоемкий запрос к базе данных и получаем данные в виде Таблицы Значений (ТЗ) или Дерева Значений (ДЗ). Эти данные в дальнейшем нужны для выполнения других команд на форме (например, при нажатии кнопки "Сформировать"). Возникает логичный вопрос — как и где сохранить эти данные, чтобы не выполнять тяжелый запрос к БД повторно?

Многие начинающие разработчики пытаются поместить серверные объекты в реквизит формы с типом ХранилищеЗначения, но сталкиваются с исключением Ошибка преобразования данных XDTO. Разберем по шагам, почему это происходит и проанализируем правильные способы решения этой задачи.

Почему возникает ошибка преобразования данных XDTO?

Для начала выясним причину возникновения ошибки сериализации. Типы данных ТаблицаЗначений, ДеревоЗначений, а также ХранилищеЗначения являются исключительно серверными объектами. Платформа 1С не умеет передавать их на тонкий или веб-клиент в чистом виде.

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

Способ 1. Использование Временного хранилища (Оптимальный вариант)

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

Посмотрим на пример реализации данного подхода. При создании на сервере мы помещаем наши данные в хранилище и сохраняем полученный адрес в строковый реквизит формы:


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

Затем, когда пользователь нажимает кнопку "Сформировать", мы извлекаем данные обратно:


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

Важный нюанс: многие опасаются, что системный администратор может "очистить кэш", и данные потеряются. Это заблуждение. Если Временное Хранилище создано с привязкой к УникальныйИдентификатор формы, оно физически хранится в оперативной памяти или сеансовых данных рабочего процесса сервера 1С, а не в локальном кэше на диске пользователя. Данные будут жить гарантированно ровно столько, сколько открыта сама форма.

Способ 2. Использование реквизитов формы

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

  1. Создайте реквизит формы с типом "ТаблицаЗначений" (например, КэшТЗ).
  2. При первичном обращении к базе данных получите серверную ТЗ и сконвертируйте ее в реквизит формы с помощью глобального метода: ЗначениеВРеквизитФормы(МояТЗ, "КэшТЗ").
  3. В команде "Сформировать" (на сервере) соберите данные обратно в серверный объект: МояТЗ = РеквизитФормыВЗначение("КэшТЗ").

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

Способ 3. Сериализация в XML или JSON

Если нужно сохранить неконтекстные данные без временного хранилища, ТЗ и ДЗ можно превратить в обычный текст (строку). Создайте строковый реквизит формы неограниченной длины. На сервере используйте СериализаторXDTO.ЗаписатьXML() для преобразования таблицы в текст и сохранения в этот реквизит.

При выполнении команды этот текст извлекается и десериализуется обратно в полноценную ТЗ. Строки без проблем передаются между клиентом и сервером. Этот вариант полезен в специфических сценариях интеграции или передачи параметров.

Способ 4. Хранилище общих настроек (для разных сеансов)

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


// Сохранение данных
ХранилищеОбщихНастроек.Сохранить("МоиНастройки", "КлючДанных", ТаблицаДанных);

// Чтение данных в другом месте
ТаблицаДанных = ХранилищеОбщихНастроек.Загрузить("МоиНастройки", "КлючДанных");

Этот метод не требует реквизитов формы, но следует учитывать консистентность данных. Если данные в БД изменились, закэшированная в настройках таблица устареет. Применимость таких фокусов зависит от контекста вашей задачи.

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

← На главную