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