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

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

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

Как извлечь данные из хранилища значений в 1С: метод Получить(), работа с картинками, файлами и настройками, проверка типа, типичные ошибки.

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

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

Что такое хранилище значений и где оно встречается

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

Типичные места, где вы столкнётесь с хранилищем значений:

  • реквизиты справочников и документов (картинки номенклатуры, сканы договоров);
  • регистры сведений с настройками (типовые механизмы хранения настроек отчётов);
  • константы типа «ХранилищеЗначения» для глобальных параметров;
  • табличные части с присоединёнными файлами в нетиповых конфигурациях.

Базовый способ: метод Получить()

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

Запрос = Новый Запрос(

"ВЫБРАТЬ

| Номенклатура.ФайлКартинки КАК ФайлКартинки

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Ссылка = &Ссылка");

Запрос.УстановитьПараметр("Ссылка", ТекущийТовар);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

ДанныеКартинки = Выборка.ФайлКартинки.Получить();

Если ДанныеКартинки = Неопределено Тогда

Сообщить("Картинка не сохранена в базе");

КонецЕсли;

КонецЕсли;

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

Извлечение картинок и файлов

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

Сохранение файла на диск

Данные = Объект.ХранилищеФайла.Получить();

Если ТипЗнч(Данные) = Тип("ДвоичныеДанные") Тогда

Данные.Записать("C:\Temp\Выгрузка.pdf");

ИначеЕсли ТипЗнч(Данные) = Тип("Картинка") Тогда

Данные.Записать("C:\Temp\Картинка.png");

КонецЕсли;

Отображение картинки на управляемой форме

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

&НаСервере

Процедура ЗагрузитьКартинку()

Данные = Объект.Ссылка.ФайлКартинки.Получить();

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

АдресКартинки = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);

КонецЕсли;

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

Порядок извлечения картинки на форму
  1. 1
    Прочитайте реквизит с хранилищем запросом или через объект
  2. 2
    Вызовите Получить() и проверьте результат на Неопределено
  3. 3
    Поместите данные во временное хранилище с УникальныйИдентификатор формы
  4. 4
    Присвойте полученный адрес строковому реквизиту формы
  5. 5
    Убедитесь, что на форме элемент с видом Поле картинки связан с этим реквизитом

Извлечение структур, таблиц и настроек

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

Настройки = Константы.НастройкиОбмена.Получить().Получить();

Если ТипЗнч(Настройки) = Тип("Структура") Тогда

Если Настройки.Свойство("УзелОбмена") Тогда

Узел = Настройки.УзелОбмена;

КонецЕсли;

КонецЕсли;

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

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

Проверка результата и обработка пустых значений

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

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

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

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

Возвращён объект ожидаемого типа

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

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

ТипЗнч(Результат)
Норма

Совпадает с ожидаемым (ДвоичныеДанные, Картинка, Структура)

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

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

Размер двоичных данных
Норма

Размер больше нуля

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

Нулевой размер — файл был повреждён или записан некорректно

Универсальный шаблон безопасного извлечения:

Функция ПолучитьДанныеИзХранилища(Хранилище)

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

Возврат Неопределено;

КонецЕсли;

Попытка

Результат = Хранилище.Получить();

Исключение

ЗаписьЖурналаРегистрации("ХранилищеЗначений",

УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());

Возврат Неопределено;

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

Возврат Результат;

КонецФункции

Массовое извлечение и выгрузка данных

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

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Данные = Выборка.ФайлКартинки.Получить();

Если ТипЗнч(Данные) = Тип("ДвоичныеДанные") Тогда

ИмяФайла = КаталогВыгрузки + "\" + СокрЛП(Выборка.Артикул) + ".jpg";

Данные.Записать(ИмяФайла);

КонецЕсли;

КонецЦикла;

Для очень больших объёмов выполняйте выгрузку порциями через пакетный запрос или фоновое задание, чтобы не блокировать сеанс пользователя и не превысить ограничения по времени выполнения.

Типичные ошибки при работе с хранилищем значений

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

Часто задаваемые вопросы

Можно ли найти записи по содержимому хранилища значений запросом?

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

Почему Получить() возвращает Неопределено, хотя данные записывались?

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

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

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

Как передать извлечённые данные на тонкий клиент?

На сервере вызовите Получить(), затем поместите результат во временное хранилище методом ПоместитьВоВременноеХранилище() и передайте клиенту адрес. На клиенте данные извлекаются методом ПолучитьИзВременногоХранилища(). Двоичные данные передаются так без ограничений.

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

ХранилищеЗначения — объект для упаковки данных и постоянного сохранения в базе. Временное хранилище — серверный механизм передачи данных между сервером и клиентом в рамках сеанса или формы; данные в нём живут ограниченное время и не пишутся в базу.

Можно ли извлечь данные из хранилища во внешнем соединении (COM, HTTP)?

Да, логика та же: через COM-connector вы читаете реквизит и вызываете Получить(). Ограничение — сериализованные типы 1С (таблица значений, картинка) имеет смысл обрабатывать только внутри 1С; наружу лучше отдавать двоичные данные или строки.

Итог

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

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