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

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

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

Разберем механизм передачи через временное хранилище

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


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

&НаКлиенте
Процедура ОткрытьФормуПриемник(Команда)
    Адрес = ПолучитьАдресТаблицыЗначений();
    ПараметрыОткрытия = Новый Структура("АдресДанных", Адрес);
    
    ОткрытьФорму("РегистрСведений.ГарантийныеСрокиТоваров.Форма.ФормаЗаполненияСпискаТоваров", ПараметрыОткрытия);
КонецПроцедуры

В форме-приемнике мы должны извлечь эти данные в обработчике ПриСозданииНаСервере:


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

Выясним причину ошибки: почему ТЗ превращается в строку?

Если при отладке вы видите, что ПолучитьИзВременногоХранилища() возвращает строку "Таблица значений", проанализируем следующие факторы:

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

Влияние кэша и расширений конфигурации

Проанализируем ситуацию, когда код написан верно, но ошибка сохраняется. В практике разработки на 1С часто возникают проблемы с кэшем метаданных, особенно если вы используете расширения конфигурации. Если форма добавлена в расширение и вы активно меняете её структуру (добавляете реквизиты, меняете типы), локальный кэш конфигурации на компьютере пользователя может «рассинхронизироваться» с реальным состоянием базы на сервере.

Решение проблемы с кэшем: Если отладчик показывает правильный тип объекта до момента присваивания, но после присваивания тип меняется на строку без видимых причин, попробуйте почистить кэш. Самый простой способ — удалить базу из списка в стартере 1С и добавить её заново (это пересоздаст папку с кэшем для данного соединения).

Использование идентификатора формы для стабильной передачи

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

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

Альтернативный метод: Сериализация через XDTO

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

Пример упаковки данных:


&НаСервере
Функция СериализоватьТЗвСтроку(Таблица)
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Таблица);
    Возврат ЗаписьXML.Закрыть();
КонецФункции

Пример распаковки данных в приемнике:


&НаСервере
Процедура РаспаковатьТЗ(СтрокаXML)
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
    Таблица = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
КонецПроцедуры

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

Подведем итоги

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

  1. Убедитесь, что получение данных из хранилища происходит строго в процедуре &НаСервере.
  2. Проверьте, что в форме-приемнике нет реквизитов с таким же именем, имеющих тип Строка.
  3. Всегда передавайте УникальныйИдентификатор формы при вызове ПоместитьВоВременноеХранилище.
  4. При возникновении необъяснимых ошибок типизации (особенно в расширениях) производите очистку кэша пользователя.
  5. Рассмотрите использование СериализаторXDTO для передачи данных, если критична независимость от времени жизни контекста формы.
← На главную