Тип данных ХранилищеЗначений в 1С:Предприятие — один из самых загадочных для новичков и одновременно мощных инструментов для опытных разработчиков. В отличие от привычных массивов или структур, он сочетает в себе возможности хранения сложных данных, их быстрой обработки и даже сохранения между сеансами. Но почему его так редко используют в типичных задачах? И в каких случаях он становится незаменимым?

Если вы когда-нибудь сталкивались с необходимостью передать большой объём данных между формами, сохранить промежуточные результаты расчётов или оптимизировать работу с временными коллекциями — ХранилищеЗначений может сократить время выполнения операций в 5–10 раз по сравнению с альтернативными подходами. В этой статье мы разберём не только синтаксис, но и реальные кейсы, где этот тип данных проявляет свои сильные стороны — и где его лучше не применять.

Что такое ХранилищеЗначений в 1С и зачем оно нужно

Тип ХранилищеЗначений (англ. Value Storage) — это контейнер для хранения произвольных данных в памяти или на диске, который поддерживает:

  • 📦 Именованные значения — как в структуре, но с возможностью динамического добавления/удаления элементов.
  • 🔄 Сериализацию — сохранение в файл или базу данных с последующим восстановлением.
  • Быстрый доступ — внутренняя оптимизация для работы с большими объёмами данных.
  • 🔗 Ссылки на объекты — можно хранить не только примитивы, но и ссылки на справочники, документы и т.д.

Главное отличие от Массив или СтруктураХранилищеЗначений не является коллекцией в привычном смысле. Оно ближе к "контейнеру состояния", который может:

  • 💾 Сохраняться между сеансами работы (например, в файле .v8s).
  • 🔄 Передаваться между клиентом и сервером без потери структуры.
  • 🛠️ Использоваться для кэширования результатов сложных вычислений.
📊 Где вы чаще всего используете ХранилищеЗначений?
Для временного хранения данных
Для обмена между формами
Для сериализации настроек
Никогда не использовал

Пример создания и заполнения:

Хранилище = Новый ХранилищеЗначений();

Хранилище.Вставить("Даты", Новый Массив);

Хранилище.Вставить("Настройки", Новый Структура("Цвет,Размер", Синий, 10));

Хранилище.Вставить("Документ", СсылкаНаДокумент);

⚠️ Внимание: В отличие от Структура, ХранилищеЗначений не поддерживает оператор . для доступа к элементам. Вместо Хранилище.Даты нужно использовать Хранилище.Получить("Даты").

Отличия ХранилищеЗначений от Массива, Структуры и Соответствия

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

Характеристика ХранилищеЗначений Массив Структура Соответствие
Именованные элементы ✅ Да ❌ Нет ✅ Да ✅ Да (ключ-значение)
Сериализация в файл ✅ Да (.v8s) ❌ Нет ❌ Нет ❌ Нет
Передача клиент-сервер ✅ Без потерь ✅ Да ✅ Да ✅ Да
Хранение ссылок на объекты ✅ Да ✅ Да ✅ Да ✅ Да
Динамическое изменение ✅ Да ✅ Да ❌ Ограничено ✅ Да

Ключевые преимущества ХранилищеЗначений:

  • 🔹 Сохранение состояния — можно записать в файл иLater восстановить, например, для отмены действий (undo/redo).
  • 🔹 Оптимизация памяти — внутренняя реализация эффективнее, чем у Структура, при большом количестве данных.
  • 🔹 Гибкость — поддерживает любые типы данных, включая NULL и неопределённые значения.

Когда не стоит его использовать:

  • 🚫 Для простых коллекций с фиксированной структурой (лучше Структура).
  • 🚫 Если нужны операции вроде Найти() или Добавить() (лучше Массив).
  • 🚫 Для временных данных, которые не нужно сохранять (лишние накладные расходы).
💡

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

Как сохранить ХранилищеЗначений в файл и загрузить обратно

Одна из ключевых особенностей — возможность сериализации. Это позволяет:

  • 💾 Сохранять настройки пользователя между запусками 1С.
  • 📤 Передавать данные между разными базами.
  • 🔄 Восстанавливать состояние после сбоя.

Пример сохранения в файл:

Хранилище = Новый ХранилищеЗначений();

Хранилище.Вставить("Параметры", Новый Структура("Язык,Тема", "Русский", "Темная"));

Хранилище.Записать("C:\Temp\Настройки.v8s");

Загрузка из файла:

Хранилище = Новый ХранилищеЗначений();

Хранилище.Прочитать("C:\Temp\Настройки.v8s");

Параметры = Хранилище.Получить("Параметры");

⚠️ Внимание: При чтении из файла ХранилищеЗначений не проверяет целостность данных автоматически. Если файл повреждён, 1С может завершить работу с ошибкой. Всегда используйте Попытка...Исключение:

Попытка

Хранилище.Прочитать("Путь\К\Файлу.v8s");

Исключение

Сообщить("Ошибка чтения: " + ОписаниеОшибки());

КонецПопытки;

Файлы .v8s имеют бинарный формат и не читаются текстовыми редакторами. Для отладки можно использовать метод ЗаписатьJSON() (доступен в последних версиях платформы):

Хранилище.ЗаписатьJSON("C:\Temp\Настройки.json");
Как выглядит файл .v8s внутри?

Файл ХранилищеЗначений (.v8s) содержит бинарные данные в проприетарном формате 1С. Его структура включает:

1. Заголовок с версией формата.

2. Сериализованные метаданные (типы значений, имена ключей).

3. Сжатые данные (если включено сжатие).

4. Контрольные суммы для проверки целостности.

Разобрать его вручную невозможно — только через методы 1С или специализированные утилиты (например, 1C:EDT).

Практические примеры использования

Разберём реальные сценарии, где ХранилищеЗначений оказывается полезнее альтернатив.

1. Передача данных между формами

Проблема: нужно передать сложную структуру данных (например, настройки отчёта с фильтрами, группировками и параметрами) из одной формы в другую. Использование ПараметрыФормы ограничено размерами, а Структура не сохраняет ссылки на объекты.

Решение:

// В исходной форме:

Хранилище = Новый ХранилищеЗначений();

Хранилище.Вставить("Фильтры", ФильтрыОтчёта);

Хранилище.Вставить("Группировки", Группировки);

ОткрытьФорму("Отчёт.ФормаОтчёта", , Хранилище);

// В форме-приёмнике:

Процедура ПриСозданииНаСервере(ХранилищеДанных)

Фильтры = ХранилищеДанных.Получить("Фильтры");

Группировки = ХранилищеДанных.Получить("Группировки");

КонецПроцедуры

2. Кэширование результатов длительных операций

Если расчёт отчёта занимает 10 минут, можно сохранить результат в ХранилищеЗначений и при повторном открытии загружать его из файла за секунды.

Создать уникальное имя файла (например, с хэшем параметров)

Проверить актуальность кэша (дата создания файла)

Записать данные в ХранилищеЗначений и сохранить в файл

При повторном открытии сначала искать кэш

Обновлять кэш при изменении исходных данных-->

3. Реализация механизма отмены действий (Undo/Redo)

Хранилище позволяет сохранять "снимки" состояния документа перед каждым изменением:

Процедура СохранитьСостояние()

Снимок = Новый ХранилищеЗначений();

Снимок.Вставить("Данные", ТекущийДокумент.ПолучитьДанные());

ИсторияДействий.Добавить(Снимок);

КонецПроцедуры

Процедура Отменить()

ПоследнийСнимок = ИсторияДействий.Последний();

ТекущийДокумент.ЗагрузитьДанные(ПоследнийСнимок.Получить("Данные"));

КонецПроцедуры

💡

Для экономии памяти в истории действий можно хранить не полные копии документа, а только изменённые поля (дельта-сохранение).

Ограничения и подводные камни

Несмотря на гибкость, у ХранилищеЗначений есть нюансы, о которых часто забывают:

  1. Размер файла: При сериализации больших объектов (например, таблиц значений с 100K строк) файл .v8s может занимать сотни мегабайт. Всегда проверяйте размер перед сохранением:
    Если Хранилище.Размер() > 10000000 Тогда // ~10 МБ
    

    Сообщить("Предупреждение: большой объём данных!");

    КонецЕсли;

  2. Ссылки на объекты: При загрузке из файла ссылки на объекты (справочники, документы) становятся недействительными, если объекты были удалены или изменены. Используйте УникальныйИдентификатор() для восстановления связей.
  3. Производительность: Доступ к элементам по имени (Получить("Ключ")) медленнее, чем индексный доступ в массиве. Для критических участков кода тестируйте альтернативы.
⚠️ Внимание: В кластерных базах (например, 1С:Предприятие 8.3 с PostgreSQL) сериализация ХранилищеЗначений в БД может приводить к блокировкам. Для таких случаев рассмотрите хранение данных в отдельных таблицах.

Ещё одна ловушка — рекурсивные ссылки. Если хранилище содержит объект, который ссылается обратно на само хранилище, при сериализации возникнет ошибка:

Хранилище.Вставить("СамСебя", Хранилище); // Приведёт к зацикливанию!

Оптимизация работы с ХранилищеЗначений

Чтобы максимально эффективно использовать этот тип данных, следуйте этим рекомендациям:

1. Используйте сжатие

Для больших хранилищ включайте сжатие при записи:

Хранилище.Записать("путь.v8s", Истина); // Второй параметр = сжатие

Это уменьшает размер файла на 30–70%, но увеличивает время записи/чтения на 10–20%.

2. Разделяйте данные по ключам

Вместо одного большого хранилища:

Хранилище.Вставить("ВсеДанные", ОгромныйМассив);

Лучше разбить на логические блоки:

Хранилище.Вставить("Заголовок", ДанныеЗаголовка);

Хранилище.Вставить("ТабличнаяЧасть1", ТЧ1);

Хранилище.Вставить("ТабличнаяЧасть2", ТЧ2);

Это ускорит доступ к отдельным частям данных.

3. Очищайте ненужные данные

Хранилище не освобождает память автоматически. После использования:

Хранилище.Очистить();
💡

Для хранения временных данных в пределах одного сеанса часто эффективнее использовать Структуру или Массив. ХранилищеЗначений оправдано, когда нужна сериализация или передача между формами.

Альтернативы ХранилищуЗначений в современных версиях 1С

В последних релизах платформы 1С:Предприятие 8.3.20+ появились новые инструменты, которые могут заменить ХранилищеЗначений в некоторых сценариях:

Альтернатива Когда использовать Преимущества Недостатки
JSON Обмен данными с внешними системами Читаемый формат, поддержка веб-сервисов Медленнее, нет ссылок на объекты
ДвоичныеДанные Сохранение бинарных файлов (PDF, изображения) Компактное хранение Нет структуры, только "сырые" данные
СериализаторXDTO Сложные схемы обмена с типизацией Поддержка XSD-схем, валидация Сложнее в настройке

Пример использования JSON вместо ХранилищеЗначений:

ДанныеJSON = Новый ЗаписьJSON;

ДанныеJSON.УстановитьСтроку();

ДанныеJSON.ЗаписатьНачалоОбъекта();

ДанныеJSON.ЗаписатьЗначение("Имя", "Иван");

ДанныеJSON.ЗаписатьЗначение("Возраст", 30);

СтрокаJSON = ДанныеJSON.Закрыть();

// Сохранение в файл

Текст.Записать("data.json", СтрокаJSON);

// Чтение обратно

ЧтениеJSON = Новый ЧтениеJSON;

ЧтениеJSON.УстановитьСтроку(Текст.Прочитать("data.json"));

Имя = ЧтениеJSON.ПрочитатьJSON().Имя;

Однако JSON не поддерживает:

  • 🔹 Ссылки на объекты 1С (только примитивы и массивы).
  • 🔹 Двоичные данные (нужно кодировать в Base64).
  • 🔹 Автоматическое сжатие.

FAQ: Частые вопросы по ХранилищуЗначений

Можно ли в ХранилищеЗначений хранить таблицу значений?

Да, но с оговорками:

  • 🔹 Таблица сохранится целиком, включая все колонки и данные.
  • 🔹 При загрузке из файла все ссылки на объекты в таблице станут недействительными (потребуется восстанавливать их вручную по УникальныйИдентификатор()).
  • 🔹 Для больших таблиц (100K+ строк) лучше использовать ЗаписьДанных или разбивать на части.

Пример:

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Наименование");

ТЗ.Добавить().Наименование = "Товар 1";

Хранилище = Новый ХранилищеЗначений();

Хранилище.Вставить("Таблица", ТЗ);

Хранилище.Записать("таблица.v8s");

Как передать ХранилищеЗначений между клиентом и сервером?

Хранилище автоматически поддерживает передачу в обе стороны. Главное — не забывать про ограничения:

  • 🔹 На клиенте нельзя работать с серверными объектами (например, ДокументОбъект).
  • 🔹 При передаче с сервера на клиент все серверные объекты преобразуются в ссылки (нужно проверять права доступа).

Пример:

// На сервере:

Хранилище = Новый ХранилищеЗначений();

Хранилище.Вставить("Документ", СсылкаНаДокумент);

Возврат Хранилище;

// На клиенте:

Процедура ПолучаемДанные(Хранилище)

Документ = Хранилище.Получить("Документ"); // Это будет Ссылка, а не объект!

КонецПроцедуры

Почему ХранилищеЗначений медленнее Структуры при доступе к элементам?

Это связано с внутренней реализацией:

  • 🔹 Структура использует хэш-таблицу для быстрого доступа по ключу (O(1)).
  • 🔹 ХранилищеЗначений хранит данные в более универсальном формате, оптимизированном для сериализации, а не для частого доступа.
  • 🔹 При каждом Получить("Ключ") происходит проверка типов и валидация.

Если вам нужен частый доступ к данным по ключу — используйте Структура или Соответствие.

Можно ли хранить в ХранилищеЗначений объекты с методами (например, менеджеры)?

Технически — да, но:

  • 🔹 Методы объекта не сохранятся — при десериализации вы получите только данные (свойства).
  • 🔹 Для менеджеров (например, ДокументОбъект.Менеджер) это бессмысленно — они привязаны к сеансу.
  • 🔹 Если нужен "снимок" объекта — лучше вручную сохранить его свойства в структуру.

Пример неправильного использования:

Объект = Документы.ЗаказКлиента.СоздатьДокумент();

Хранилище.Вставить("Объект", Объект); // Сохранится только "пустая оболочка"

Как проверить, существует ли ключ в ХранилищеЗначений?

Используйте метод Свойство():

Если Хранилище.Свойство("МойКлюч") Тогда

Значение = Хранилище.Получить("МойКлюч");

Иначе

Сообщить("Ключ не найден!");

КонецЕсли;

Альтернатива — обернуть Получить() в Попытка...Исключение:

Попытка

Значение = Хранилище.Получить("НесуществующийКлюч");

Исключение

Сообщить("Ошибка: " + ОписаниеОшибки());

КонецПопытки;