При разработке отчетов и обработок часто возникает задача вывести признак наличия прикрепленного файла или картинки в виде булева значения (Истина или Ложь). Однако попытка обратиться к реквизиту с типом ХранилищеЗначения внутри запроса 1С или преобразовать его через ВЫРАЗИТЬ() приводит к ошибке несовместимости типов.
Разберем причины такого поведения платформы и рассмотрим рабочие способы решения этой задачи.
Поле типа ХранилищеЗначения предназначено для хранения двоичных данных произвольного объема (BLOB). На уровне СУБД и языка запросов «1С:Предприятие» для таких полей действуют жесткие ограничения:
ХранилищеЗначения запрещено использовать в операциях сравнения (=, <>), функциях ВЫРАЗИТЬ(), условиях ВЫБОР КОГДА ..., секциях ГДЕ, СГРУППИРОВАТЬ ПО и УПОРЯДОЧИТЬ ПО.ЕСТЬ NULL не позволяет определить пустоту хранилища — она проверяет только физическое отсутствие всей записи при соединениях таблиц.К данным, находящимся в хранилище, невозможно обратиться непосредственно из запроса — их можно только извлечь программно с помощью специального метода. Поэтому напрямую получить флаг заполненности одним запросом не получится. Рассмотрим основные варианты решения проблемы.
Если типовая конфигурация находится на поддержке, оптимальным решением без снятия с поддержки является использование механизма расширений (доступно начиная с платформы 8.3.11).
Разберем по шагам, как настроить этот вариант:
Номенклатура).ЕстьКартинка с типом Булево.ПередЗаписью или ПриЗаписи объекта и заполняем флаг:
&Вместо("ПередЗаписью")
Процедура Расш_ПередЗаписью(Отказ)
// Проверяем заполненность хранилища перед сохранением
Если ЭтотОбъект.Картинка.Получить() <> Неопределено Тогда
ЭтотОбъект.ЕстьКартинка = Истина;
Иначе
ЭтотОбъект.ЕстьКартинка = Ложь;
КонецЕсли;
ПродолжитьВызов(Отказ);
КонецПроцедуры
ЕстьКартинка в тексте запроса.Важная особенность: если разработка запроса ведется во внешней обработке или отчете, Конструктор запросов в конфигураторе может не отображать реквизиты, добавленные в расширении. В этом случае имя поля (например, Товар.ЕстьКартинка) достаточно прописать в тексте запроса вручную — в режиме «1С:Предприятие» запрос выполнится корректно.
Если изменение конфигурации или добавление расширений невозможно, задачу можно решить программным обходом результата запроса. Чтобы не замедлять работу базы и не перегружать память передачей больших бинарных данных, из базы запрашиваются только ссылки на объекты, а само хранилище считывается точечно.
Посмотрим на пример программной обработки:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПартииОстатки.Товар КАК Товар,
| ПартииОстатки.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.ПартииНоменклатуры.Остатки(&Период, ) КАК ПартииОстатки";
РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультат = РезультатЗапроса.Выгрузить();
ТаблицаРезультат.Колонки.Добавить("ЕстьФото", Новый ОписаниеТипов("Булево"));
Для Каждого Стр Из ТаблицаРезультат Цикл
// Метод Получить() извлекает данные из ХранилищаЗначения
ДвоичныеДанные = Стр.Товар.Картинка.Получить();
Стр.ЕстьФото = (ДвоичныеДанные <> Неопределено);
КонецЦикла;
В большинстве современных конфигураций файлы и изображения хранятся не в реквизитах справочника, а в отдельных связанных объектах (например, справочниках НоменклатураПрисоединенныеФайлы).
В такой структуре проверка наличия картинки легко реализуется стандартным запросом через левое соединение:
ВЫБРАТЬ
Товары.Ссылка КАК Товар,
ВЫБОР
КОГДА Файлы.Ссылка ЕСТЬ NULL ТОГДА ЛОЖЬ
ИНАЧЕ ИСТИНА
КОНЕЦ КАК ЕстьФото
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.НоменклатураПрисоединенныеФайлы КАК Файлы
ПО Файлы.ВладелецФайла = Товары.Ссылка
И НЕ Файлы.ПометкаУдаления