При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью передать большой объем данных (например, таблицу значений или результат импорта данных) из одной формы в другую. Поскольку тип ТаблицаЗначений не существует на клиенте, единственным надежным способом передачи остается использование временного хранилища. Однако на этом пути часто возникают ошибки: данные «пропадают», время жизни хранилища истекает раньше времени, или, что самое странное, объект таблицы внезапно превращается в строку с текстом "Таблица значений". Рассмотрим подробно, почему это происходит и как правильно организовать процесс передачи.
Проанализируем стандартный алгоритм: мы помещаем таблицу во временное хранилище на сервере, получаем адрес, передаем этот адрес в параметрах открытия формы и в принимающей форме извлекаем данные. Рассмотрим пример кода, который часто используется для этих целей:
&НаСервере
Функция ПолучитьАдресТаблицыЗначений()
// Выгружаем данные из реквизита формы (например, из списка товаров)
ТаблицаДляПередачи = Объект.Товары.Выгрузить();
// Помещаем во временное хранилище.
// Важно: использование УникальногоИдентификатора формы гарантирует,
// что данные не удалятся сразу после завершения серверного вызова.
АдресВХ = ПоместитьВоВременноеХранилище(ТаблицаДляПередачи, ЭтаФорма.УникальныйИдентификатор);
Возврат АдресВХ;
КонецФункции
&НаКлиенте
Процедура ОткрытьФормуПриемник(Команда)
Адрес = ПолучитьАдресТаблицыЗначений();
ПараметрыОткрытия = Новый Структура("АдресДанных", Адрес);
ОткрытьФорму("РегистрСведений.ГарантийныеСрокиТоваров.Форма.ФормаЗаполненияСпискаТоваров", ПараметрыОткрытия);
КонецПроцедуры
В форме-приемнике мы должны извлечь эти данные в обработчике ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("АдресДанных") Тогда
// Извлекаем объект из хранилища
ОбъектДанных = ПолучитьИзВременногоХранилища(Параметры.АдресДанных);
// Проверяем тип, чтобы убедиться в корректности передачи
Если ТипЗнч(ОбъектДанных) = Тип("ТаблицаЗначений") Тогда
// Дальнейшая логика обработки таблицы
ЗначениеВРеквизитФормы(ОбъектДанных, "ИмяТаблицыНаФорме");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Если при отладке вы видите, что ПолучитьИзВременногоХранилища() возвращает строку "Таблица значений", проанализируем следующие факторы:
ТаблицаТоваров), и этот реквизит имеет тип Строка, платформа может попытаться автоматически преобразовать объект ТЗ в строку при присваивании. Для контроля свойств реквизитов удобно использовать редактор форм в режиме предприятия.ТаблицаЗначений доступен только на сервере. Если вы попытаетесь вызвать ПолучитьИзВременногоХранилища на тонком клиенте, платформа не сможет создать объект ТЗ и либо выдаст ошибку, либо исказит данные.УникальныйИдентификатор формы, данные будут удалены автоматически при первом же переходе с сервера на клиент. К моменту открытия второй формы по этому адресу может быть пусто или находиться мусорное значение.Проанализируем ситуацию, когда код написан верно, но ошибка сохраняется. В практике разработки на 1С часто возникают проблемы с кэшем метаданных, особенно если вы используете расширения конфигурации. Если форма добавлена в расширение и вы активно меняете её структуру (добавляете реквизиты, меняете типы), локальный кэш конфигурации на компьютере пользователя может «рассинхронизироваться» с реальным состоянием базы на сервере.
Решение проблемы с кэшем: Если отладчик показывает правильный тип объекта до момента присваивания, но после присваивания тип меняется на строку без видимых причин, попробуйте почистить кэш. Самый простой способ — удалить базу из списка в стартере 1С и добавить её заново (это пересоздаст папку с кэшем для данного соединения).
Рассмотрим подробнее вопрос владения данными во временном хранилище. Посмотрим на важный нюанс: если форма-источник, которая поместила данные в хранилище, закрывается, данные могут быть удалены. Чтобы избежать этого при передаче между формами, рекомендуется использовать идентификатор целевой формы, если он известен, либо передавать данные без привязки к конкретному владельцу, но тогда очистку нужно производить вручную.
Однако наиболее надежный способ — передавать идентификатор текущей формы (источника) и следить за тем, чтобы форма-приемник открывалась как подчиненная или блокирующая, чтобы источник не закрылся раньше времени.
Если работа с временным хранилищем кажется нестабильной в конкретных условиях, разберем альтернативный вариант — сериализацию таблицы в строку XML. Этот метод гарантирует, что тип данных не будет искажен, так как передается обычная строка.
Пример упаковки данных:
&НаСервере
Функция СериализоватьТЗвСтроку(Таблица)
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Таблица);
Возврат ЗаписьXML.Закрыть();
КонецФункции
Пример распаковки данных в приемнике:
&НаСервере
Процедура РаспаковатьТЗ(СтрокаXML)
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
Таблица = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
КонецПроцедуры
Преимущество этого метода: вы передаете простую строку через параметры формы, что исключает любые проблемы с временем жизни временного хранилища. Однако помните, что для очень больших таблиц этот метод может быть медленнее из-за затрат на сериализацию и десериализацию.
Для успешной передачи таблицы значений между формами выполните следующие действия:
&НаСервере.Строка.УникальныйИдентификатор формы при вызове ПоместитьВоВременноеХранилище.СериализаторXDTO для передачи данных, если критична независимость от времени жизни контекста формы.