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