Разработка и Конфигурация · 11 мин
Как передать таблицу значений в управляемой форме 1С
Как передать таблицу значений между управляемыми формами 1С: через временное хранилище, параметры формы и реквизиты. Примеры кода, ошибки и проверка результата.
Передача таблицы значений между управляемыми формами — одна из самых частых задач при доработке конфигураций: подбор товаров в документ, передача отобранных строк в обработку, обмен данными между основной формой и диалогом настроек. Проблема в том, что таблицу значений нельзя просто положить в параметр формы — платформа накладывает ограничения на типы, которые сериализуются при передаче между клиентом и сервером.
Рабочих способа три: передача через временное хранилище (ВременноеХранилище / ПоместитьВоВременноеХранилище), преобразование таблицы в массив структур и передача через реквизит формы типа «ТаблицаЗначений» с динамическим созданием колонок. Каждый подходит для своего сценария, и выбор зависит от того, куда передаются данные — в другую форму, на сервер или в фоновое задание.
Ниже разобраны все три подхода с кодом, ограничениями и типичными ошибками, которые приводят к потере данных или ошибкам сериализации.
Почему таблицу значений нельзя передать напрямую
Управляемая форма работает в режиме разделения клиента и сервера: вся передача данных между ними идёт через сериализацию. Тип «ТаблицаЗначений» — это несериализуемый объект произвольной структуры, поэтому платформа не позволяет указать его в параметрах формы или вернуть из серверной процедуры на тонкий клиент.
Если попытаться передать таблицу значений в параметрах ОткрытьФорму(), разработчик получит либо ошибку о недопустимом типе параметра, либо молчаливую потерю данных. То же относится к попытке вернуть таблицу из серверной функции, вызванной с клиента, — платформа сообщит о невозможности передачи значения.
Кроме того, параметры формы допускают только ограниченный набор типов: примитивы, ссылки, стандартные даты и некоторые системные типы. Поэтому любая нетривиальная структура данных требует обходного пути — хранилища или преобразования в сериализуемый формат.
Способ 1: передача через временное хранилище
Это основной и рекомендуемый способ для таблиц любого размера. Идея: таблица помещается на сервере во временное хранилище, а в открываемую форму передаётся только адрес — обычная строка, которая проходит сериализацию без ограничений.
Код на стороне вызывающей формы:
&НаКлиенте
Процедура ОткрытьПодбор(Команда)
АдресХранилища = ПоместитьТаблицуВХранилище();
ПараметрыФормы = Новый Структура("АдресТаблицы", АдресХранилища);
ОткрытьФорму("Обработка.Подбор.Форма.ФормаПодбора", ПараметрыФормы, ЭтотОбъект);
КонецПроцедуры
&НаСервере
Функция ПоместитьТаблицуВХранилище()
ТЗ = Объект.Товары.Выгрузить();
Возврат ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификатор);
КонецФункции
Код на стороне открываемой формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("АдресТаблицы") Тогда
ТЗ = ПолучитьИзВременногоХранилища(Параметры.АдресТаблицы);
// дальше — загрузка в реквизит формы или обработка
КонецЕсли;
КонецПроцедуры
Второй параметр ПоместитьВоВременноеХранилище — УникальныйИдентификатор формы — привязывает данные к времени жизни формы. Это важно: без привязки хранилище живёт до конца сеанса и накапливает мусор в памяти сервера.
Способ 2: возврат таблицы из формы через ОповеститьОВыборе
Обратная задача — вернуть таблицу из открытой формы подбора обратно в документ. Здесь адрес хранилища передаётся через структуру результата в методе ОповеститьОВыборе() или через Закрыть() с параметром.
Шаблон выглядит так: форма подбора при завершении работы выгружает свою таблицу, помещает её в хранилище (с привязкой к УникальныйИдентификатор родительской формы) и возвращает адрес:
&НаКлиенте
Процедура ПеренестиВДокумент(Команда)
АдресРезультата = ПоместитьРезультатВХранилище();
ОповеститьОВыборе(Новый Структура("АдресРезультата", АдресРезультата));
КонецПроцедуры
&НаСервере
Функция ПоместитьРезультатВХранилище()
ТЗ = ТаблицаПодбора.Выгрузить();
Возврат ПоместитьВоВременноеХранилище(ТЗ, ВладелецХранилища);
КонецФункции
В родительской форме результат обрабатывается в событии ОбработкаВыбора, где таблица извлекается из хранилища и загружается в табличную часть. Идентификатор родительской формы удобно передать в форму подбора через параметры при открытии.
- 1При открытии подбора передайте в параметрах УникальныйИдентификатор родительской формы
- 2В подборе выгрузите таблицу и поместите её в хранилище с привязкой к переданному идентификатору
- 3Вызовите ОповеститьОВыборе() со структурой, содержащей адрес хранилища
- 4В родительской форме в ОбработкаВыбора получите таблицу через ПолучитьИзВременногоХранилища()
- 5Загрузите таблицу в табличную часть и установите Модифицированность = Истина
Способ 3: передача массивом структур
Для небольших таблиц (десятки, максимум сотни строк) допустимо преобразовать таблицу в массив структур — этот тип сериализуется свободно. Способ проще: не нужно управлять временем жизни хранилища, данные сразу доступны в параметрах.
Преобразование выполняется вручную, поскольку штатного метода ТаблицаЗначений → МассивСтруктур нет:
Функция ТаблицаВМассивСтруктур(ТЗ)
Результат = Новый Массив;
ИменаКолонок = "";
Для Каждого Колонка Из ТЗ.Колонки Цикл
ИменаКолонок = ИменаКолонок + ?(ИменаКолонок = "", "", ",") + Колонка.Имя;
КонецЦикла;
Для Каждого СтрокаТЗ Из ТЗ Цикл
СтруктураСтроки = Новый Структура(ИменаКолонок);
ЗаполнитьЗначенияСвойств(СтруктураСтроки, СтрокаТЗ);
Результат.Добавить(СтруктураСтроки);
КонецЦикла;
Возврат Результат;
КонецФункции
Ограничения способа существенные: имена колонок должны быть допустимыми идентификаторами (без пробелов и спецсимволов), значения в ячейках — только сериализуемых типов, а объём данных ограничен разумными пределами передачи между клиентом и сервером. Для больших таблиц этот способ заметно медленнее хранилища и может привести к ошибкам при передаче.
Сравнение способов передачи
Подходит для таблиц любого размера и сложных типов в ячейках. Требует контроля времени жизни хранилища и двух серверных вызовов.
Простая реализация, данные сразу в параметрах. Ограничен малым объёмом, сериализуемыми типами значений и корректными именами колонок.
Для передачи внутри одной формы между клиентом и сервером. Колонки должны быть созданы заранее в конфигураторе или динамически через ИзменитьРеквизиты().
Работа с реквизитом формы типа «ТаблицаЗначений»
Когда таблица нужна непосредственно на форме для отображения и редактирования, её размещают в реквизите формы. Если колонки известны заранее, реквизит создаётся в конфигураторе. Если структура таблицы динамическая (например, произвольный отчёт), колонки добавляются программно методом ИзменитьРеквизиты().
После получения таблицы из хранилища её загружают в реквизит через ЗначениеВРеквизитФормы():
ТЗ = ПолучитьИзВременногоХранилища(Параметры.АдресТаблицы);
ЗначениеВРеквизитФормы(ТЗ, "ТаблицаНаФорме");
Обратное преобразование — РеквизитФормыВЗначение("ТаблицаНаФорме") — возвращает объект ТаблицаЗначений для серверной обработки. Помните, что оба метода работают только в серверном контексте формы.
Проверка результата и отладка
После внедрения передачи убедитесь, что данные доходят полностью. Минимальная проверка — сравнить количество строк в исходной таблице и после ПолучитьИзВременногоХранилища(). Значение Неопределено вместо таблицы почти всегда означает, что хранилище уже очищено из-за закрытия формы-владельца.
Проверяйте типы значений в колонках: если в таблице есть значения несериализуемых типов (например, COMОбъект или результат запроса), при передаче массивом структур возникнет ошибка. Для хранилища таких ограничений внутри сервера нет, но и там лучше хранить «чистые» данные.
При отладке удобно временно выводить ТЗ.Количество() и содержимое первой строки через Сообщить() на сервере — это быстрее, чем пошаговая трассировка клиент-серверных вызовов.
Как проверить результат
Совпадает с исходной таблицей
Строк меньше или ПолучитьИзВременногоХранилища вернул Неопределено
Ссылки, числа и строки перенесены без искажений
Пустые значения там, где были данные, или ошибка сериализации
Форма помечена как изменённая, данные сохраняются
Таблица заполнена, но при записи данные теряются
FAQ
Что важно запомнить
Таблицу значений в управляемых формах передают через временное хранилище: поместили на сервере — передали адрес — получили в целевой форме. Для маленьких таблиц допустим массив структур. Всегда привязывайте хранилище к УникальныйИдентификатор формы, которая живёт дольше.
Можно ли передать таблицу значений в фоновое задание?
Напрямую — нет, параметры фонового задания тоже сериализуются. Поместите таблицу во временное хранилище и передайте адрес в параметрах метода Выполнить(), либо сериализуйте таблицу через ЗначениеВСтрокуВнутр() и передайте строкой.
Почему ПолучитьИзВременногоХранилища возвращает Неопределено?
Чаще всего хранилище было привязано к форме, которая уже закрылась, — данные удаляются вместе с ней. Проверьте, чей УникальныйИдентификатор передавался вторым параметром в ПоместитьВоВременноеХранилище, и используйте идентификатор формы с более долгим жизненным циклом.
Как передать таблицу из одной формы в другую без открытия второй формы?
Через общий модуль с серверной процедурой, которая помещает таблицу в хранилище и возвращает адрес, либо через механизм оповещений Оповестить() с адресом хранилища в параметре — вторая форма получит его в ОбработкаОповещения.
Есть ли ограничение на размер таблицы во временном хранилище?
Жёсткого лимита платформа не документирует, но большие таблицы расходуют память сервера и замедляют сеансы всех пользователей. Для очень больших объёмов рассмотрите передачу отбора и повторное получение данных запросом в целевой форме вместо переноса самой таблицы.
Можно ли передать таблицу с картинками или двоичными данными?
Двоичные данные и картинки лучше не держать внутри таблицы значений при передаче. Передавайте ссылки на файлы или адреса отдельных элементов в хранилище, а сами данные подгружайте по требованию — это снижает объём сериализуемой информации.
Чем отличается ПоместитьВоВременноеХранилище от ЗначениеВСтрокуВнутр?
Первый метод размещает объект на сервере и возвращает адрес для чтения в течение сеанса. Второй сериализует значение в строку, которую можно сохранить в базу или передать куда угодно, но строка громоздкая и не предназначена для оперативного обмена между формами.