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