К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как поместить структуру в хранилище значений в 1С

Как поместить структуру в ХранилищеЗначения в 1С: конструктор, сериализация, извлечение данных, типичные ошибки и ограничения по типам значений.

Структура в 1С — универсальный способ передать набор именованных значений между процедурами, формами и сеансами. Но сама по себе структура не может храниться в реквизите объекта или реквизите формы между вызовами сервера: для этого её нужно сериализовать. Штатный механизм для такой задачи — объект «ХранилищеЗначения», который упаковывает структуру в двоичное представление и позволяет сохранить её в базе данных или передать через параметры.

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

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

Что такое ХранилищеЗначения и когда оно нужно

«ХранилищеЗначения» — это встроенный тип платформы 1С, предназначенный для упаковки произвольных данных в компактное двоичное представление. В конфигураторе реквизиты с этим типом доступны у справочников, документов, планов видов характеристик, регистров сведений, констант и других объектов. Физически данные сохраняются в базе в сжатом виде.

Типовые задачи, где хранилище оправдано: сохранение настроек пользователя (отбор, порядок колонок, параметры отчёта), кэширование результатов тяжёлых вычислений, передача пакета параметров в фоновое задание, хранение двоичных данных файлов, сохранение снимков данных для истории изменений. Структура здесь выступает удобным контейнером, потому что позволяет именовать каждый параметр.

Базовый пример: поместить структуру и прочитать её обратно

Минимальный рабочий код выглядит следующим образом. Сначала формируется структура, затем она упаковывается и записывается в реквизит объекта:

СтруктураНастроек = Новый Структура;

СтруктураНастроек.Вставить("Склад", СкладСсылка);

СтруктураНастроек.Вставить("ПериодОтбора", ТекущаяДатаСеанса());

СтруктураНастроек.Вставить("ВыводитьОстатки", Истина);

ОбъектНастроек = Справочники.НастройкиПользователей.СоздатьЭлемент();

ОбъектНастроек.Наименование = "Настройки отчёта";

ОбъектНастроек.ДанныеНастроек = Новый ХранилищеЗначения(СтруктураНастроек);

ОбъектНастроек.Записать();

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

Хранилище = ОбъектНастроек.ДанныеНастроек;

Если Хранилище <> Неопределено Тогда

ВосстановленнаяСтруктура = Хранилище.Получить();

Если ТипЗнч(ВосстановленнаяСтруктура) = Тип("Структура") Тогда

Склад = ВосстановленнаяСтруктура.Склад;

КонецЕсли;

КонецЕсли;

Порядок действий
  1. 1
    Создайте структуру и заполните её ключами через Вставить()
  2. 2
    Убедитесь, что все значения сериализуемы (примитивы, ссылки, таблицы, массивы)
  3. 3
    Упакуйте структуру: Новый ХранилищеЗначения(Структура)
  4. 4
    Запишите результат в реквизит типа ХранилищеЗначения и сохраните объект
  5. 5
    При чтении вызовите Получить() и проверьте результат на Неопределено и тип

Передача структуры в фоновое задание и между сеансами

Одна из самых частых причин упаковки структуры — фоновые задания. Метод ФоновыеЗадания.Выполнить() принимает массив параметров, и все они должны быть сериализуемыми. Структура сама по себе здесь допустима, но если внутри лежат сложные данные (например, таблица значений с результатами запроса), надёжнее упаковать её в хранилище и передать одним параметром.

Другой сценарий — временное хранилище формы. Когда нужно передать данные с сервера на клиент или между вызовами, используется связка ПоместитьВоВременноеХранилище(Новый ХранилищеЗначения(Структура), УникальныйИдентификаторФормы). Второй параметр привязывает данные к времени жизни формы, иначе они удалятся после завершения серверного вызова.

// На сервере

ПараметрыРасчёта = Новый Структура("Организация, Период", Организация, Период);

АдресРезультата = ПоместитьВоВременноеХранилище(

Новый ХранилищеЗначения(ПараметрыРасчёта),

ЭтаФорма.УникальныйИдентификатор);

Какие типы можно и нельзя помещать внутри структуры

Платформа сериализует далеко не всё. Перед записью проверьте состав структуры, особенно если она формируется динамически и её содержимое зависит от входных данных.

Тип значенияМожно ли в хранилищеКомментарий
Число, Строка, Дата, БулевоДаСериализуются без ограничений
Ссылки на объекты базыДаСохраняется ссылка, а не копия объекта
Массив, Структура, СоответствиеДаДопускается вложенность
ТаблицаЗначений, ДеревоЗначенийДаУдобно для кэша результатов запросов
Картинка, ДвоичныеДанныеДаСтандартный способ хранения файлов
Форма, элементы формыНетОбъекты интерфейса не сериализуются
COMОбъект, OLE-объектыНетВнешние соединения нельзя сохранить
Запрос с открытым результатомНетСначала выполните Выгрузить()
Типичные ошибки
01
Чтение без проверки: Получить() вернул Неопределено, а код сразу обращается к ключу структуры — ошибка выполнения
02
Сохранение ссылки вместо копии: после изменения исходного объекта в базе «старые» данные из хранилища перестают совпадать с ожиданиями
03
Помещение COM-объекта или формы внутрь структуры — ошибка сериализации при записи
04
Изменение структуры после упаковки: изменения не попадут в хранилище, упаковывать нужно повторно
05
Хранение огромных таблиц без сжатия — раздувание базы и медленная запись

Сериализация через XML и JSON как альтернатива

ХранилищеЗначения — не единственный способ сохранить структуру. Если данные нужно передавать во внешние системы или хранить в читаемом виде, подойдут строковые форматы. Платформа предлагает два штатных механизма: сериализацию через XDTO (СериализаторXDTO или функции ЗначениеВСтрокуXML) и запись в JSON через ЗаписьJSON.

JSON удобен для обмена с веб-сервисами, но имеет ограничения: даты, ссылки и некоторые типы 1С требуют ручного преобразования. XDTO-строка сохраняет типы платформы полностью, но получается громоздкой и читается только внутри 1С. ХранилищеЗначения выигрывает у обоих вариантов по компактности и простоте, когда обмен с внешними системами не нужен.

Сравнение вариантов

ХранилищеЗначения

Лучший выбор для внутреннего хранения в базе: компактно, быстро, сохраняет типы. Не читается вне 1С.

Строка JSON

Подходит для обмена с внешними системами и API. Требует ручной обработки дат и ссылок.

ЗначениеВСтрокуXML (XDTO)

Сохраняет все типы платформы в текстовом виде. Громоздко, применимо для отладки и переноса между базами 1С.

План обмена

Если задача — регулярная синхронизация данных между базами, а не разовое сохранение параметров.

Проверка результата и отладка

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

При отладке полезно помнить: если вы изменили структуру после того, как упаковали её в хранилище, внутри хранилища останется старый снимок. Упаковка — это копирование данных на момент вызова конструктора, а не живая ссылка на структуру.

Контрольные точки

Как проверить результат

Результат Получить()
Норма

Возвращается значение типа Структура с ожидаемыми ключами

Тревожный признак

Неопределено — реквизит пуст или данные не записывались

Состав ключей после чтения
Норма

Все ключи на месте, типы значений совпадают с исходными

Тревожный признак

Часть ключей отсутствует — структура была изменена до повторной упаковки

Размер записи в базе
Норма

Запись происходит быстро, размер адекватен данным

Тревожный признак

Резкий рост размера — внутрь попали лишние большие объекты без сжатия

Ограничения и риски при работе с хранилищем

Данные внутри ХранилищеЗначения невидимы для запросов: нельзя отобрать записи по значению ключа внутри упакованной структуры. Если по параметрам нужно строить отборы и отчёты, храните их в обычных реквизитах, а хранилище используйте только для служебного «пакета» данных.

Второй риск — версионирование структуры. Если формат набора ключей изменился после обновления конфигурации, старые записи в базе будут читаться в прежнем виде. Код чтения должен учитывать отсутствие новых ключей: используйте проверку Структура.Свойство("НовыйКлюч", Значение) вместо прямого обращения.

Удобный приём — добавлять в структуру служебный ключ с версией формата, например ВерсияДанных = 2. При чтении код сразу понимает, как обрабатывать набор ключей, и обновление конфигурации не ломает старые записи.
ПЗ
Практическое замечание

Частые вопросы

Можно ли поместить в хранилище структуру с вложенной структурой или массивом?

Да, вложенность поддерживается без ограничений по глубине на практике. Внутри могут быть массивы, соответствия, другие структуры и таблицы значений — главное, чтобы все конечные значения были сериализуемыми типами.

Что вернёт метод Получить(), если реквизит пустой?

Метод вернёт Неопределено. Поэтому перед обращением к ключам структуры всегда проверяйте результат: сначала на Неопределено, затем через ТипЗнч() — что это действительно Структура.

Изменится ли содержимое хранилища, если изменить структуру после упаковки?

Нет. Конструктор Новый ХранилищеЗначения() создаёт снимок данных на момент вызова. Чтобы зафиксировать изменения, нужно упаковать структуру заново и перезаписать реквизит объекта.

Можно ли отобрать записи запросом по значению внутри хранилища?

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

Чем отличается ХранилищеЗначения от временного хранилища формы?

ХранилищеЗначения — это формат упаковки данных, а временное хранилище — механизм передачи данных между сервером и клиентом по адресу. На практике они комбинируются: структуру упаковывают в ХранилищеЗначения и помещают во временное хранилище через ПоместитьВоВременноеХранилище().

Есть ли ограничение по размеру данных в хранилище?

Жёсткого лимита со стороны платформы нет, но на практике большие объёмы замедляют чтение и запись объекта и раздувают базу. Для крупных данных используйте сжатие (второй параметр конструктора) или храните файлы в томах/на диске, а в базе — только ссылки.

Итог

Что важно запомнить

Структура помещается в хранилище одной строкой: Новый ХранилищеЗначения(Структура), читается методом Получить() с обязательной проверкой на Неопределено. Внутрь допускаются только сериализуемые типы, упаковка создаёт снимок данных, а содержимое хранилища недоступно для запросов. Для больших данных включайте сжатие, для чувствительных — шифрование.