Как вывести изображения товаров в отчете СКД и исправить ошибку конструктора Картинка

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на базе Системы компоновки данных (СКД) часто возникает необходимость визуализировать данные, например, вывести фотографии номенклатуры в прайс-листе. Поскольку штатные механизмы СКД в старых версиях платформы или в специфических задачах не всегда позволяют сделать это «в один клик», разработчики прибегают к программной постобработке результата. В этой статье мы разберем, как правильно вставить изображения в табличный документ, и выясним, почему возникает популярная ошибка «Несоответствие типов» при использовании конструктора Картинка.

Разбор алгоритма вывода изображения через постобработку

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

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


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // 1. Инициализируем процесс компоновки
    НастройкиКомпоновки = КомпоновщикНастроек.ПолучитьНастройки();
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных();
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиКомпоновки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных();
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент();
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    // 2. Обработка полученного табличного документа
    КоличествоСтрок = ДокументРезультат.ВысотаТаблицы;
    КоличествоКолонок = ДокументРезультат.ШиринаТаблицы;
    
    Для СтрокаДокумента = 1 По КоличествоСтрок Цикл
        Для КолонкаДокумента = 1 По КоличествоКолонок Цикл
            Область = ДокументРезультат.Область(СтрокаДокумента, КолонкаДокумента);
            Расшифровка = Область.Расшифровка;
            
            Если ТипЗнч(Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
                ПоляРасшифровки = ДанныеРасшифровки.Элементы.Получить(Расшифровка).ПолучитьПоля();
                НайденоеПоле = ПоляРасшифровки.Найти("Картинка");
                
                Если НЕ НайденоеПоле = Неопределено Тогда
                    ХранимыйФайл = НайденоеПоле.Значение;
                    // Здесь будет логика вставки картинки
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
КонецПроцедуры

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

Анализ ошибки «Несоответствие типов» в конструкторе Картинка

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

Рассмотрим, что может возвращать метод Получить() у объекта ХранилищеЗначения:

  1. ДвоичныеДанные: Если в хранилище был записан файл напрямую. В этом случае конструктор сработает корректно.
  2. Объект Картинка: Если при записи в базу данные предварительно были преобразованы в объект 1С. В этом случае попытка передать объект Картинка внутрь конструктора Новый Картинка() приведет к ошибке, так как конструктор не ожидает на вход саму себя.

Решение: Перед созданием объекта необходимо проверить тип извлеченных данных. Если в хранилище уже лежит Картинка, мы используем её напрямую. Если там ДвоичныеДанные — используем конструктор.


ДанныеИзХранилища = ХранимыйФайл.Хранилище.Получить();

Если ТипЗнч(ДанныеИзХранилища) = Тип("Картинка") Тогда
    Картинка = ДанныеИзХранилища;
ИначеЕсли ТипЗнч(ДанныеИзХранилища) = Тип("ДвоичныеДанные") Тогда
    Картинка = Новый Картинка(ДанныеИзХранилища);
Иначе
    Продолжить; // Неизвестный формат данных
КонецЕсли;

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

После того как мы успешно получили объект Картинка, нам нужно разместить его в табличном документе так, чтобы он соответствовал границам ячейки. Для этого используется коллекция Рисунки табличного документа.

Разберем по шагам процесс вставки:

  1. Создаем новый рисунок с типом ТипРисункаТабличногоДокумента.Картинка.
  2. Присваиваем нашему рисунку полученный объект Картинка.
  3. Устанавливаем режим масштабирования. Чтобы изображение не искажалось, рекомендуется использовать РазмерКартинки.Пропорционально.
  4. Используем метод Расположить(), чтобы «привязать» рисунок к конкретной области (ячейке) отчета.

Пример итогового кода внутри цикла:


Если ЗначениеЗаполнено(ХранимыйФайл) Тогда
    Данные = ХранимыйФайл.Хранилище.Получить();
    Попытка
        Если ТипЗнч(Данные) = Тип("ДвоичныеДанные") Тогда
            Картинка = Новый Картинка(Данные);
        ИначеЕсли ТипЗнч(Данные) = Тип("Картинка") Тогда
            Картинка = Данные;
        Иначе
            Возврат;
        КонецЕсли;
        
        КартинкаВДокументе = ДокументРезультат.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
        КартинкаВДокументе.Картинка = Картинка;
        КартинкаВДокументе.РазмерКартинки = РазмерКартинки.Пропорционально;
        
        // Привязываем картинку к ячейке
        КартинкаВДокументе.Расположить(Область);
        
        // Опционально: увеличиваем высоту строки, чтобы картинку было видно
        Область.ВысотаСтроки = 60; 
    Исключение
        // Обработка ошибок чтения данных
    КонецПопытки;
КонецЕсли;

Оптимизация производительности при выводе больших отчетов

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

Подводя итог, отметим, что программный вывод через расшифровку — это гибкий и надежный метод, особенно для «обычных форм» или сложных отчетов, где требуется динамическое изменение размеров и свойств выводимых объектов. Главное — внимательно следить за соответствием типов данных при работе с объектом ХранилищеЗначения.

← На главную