СКД. Отчеты с картинками














Решение популярных кейсов с картинками в отчетах на СКД.

Опять баян

Тема с добавлением картинок в отчеты на СКД появляется периодически на просторах сообщества и вне его. Самыми популярными задачами являются добавление логотипа компании в шапку отчета и отображение картинок товаров.

Почти всегда эти требования появляются для прайс-листов, но бывают и исключения.

Сегодня рассмотрим решения обоих кейсов, а также новые возможности платформы для вывода картинок.

Кейс №1: Логотип в шапке отчета

Начнем с простой задачи — вывод логотипа в шапку отчета на СКД.

Хочу логотип

И так, у нас есть простой внешний отчет "Прайс-лист", в котором для номенклатуры выводятся цены в разрезе их типов. Отчет создан для типовой конфигурации "Управление торговлей" версии 11. На следующем скриншоте представлен вывод для стандартных настроек отчета.

 

 Пример вывода стандартного отчета

Наша задача заключается в добавлении в шапку табличного документа отчета логотипа компании. Для этого нам необходимо программно сформировать отчет и вставить изображение логотипа. Теперь подробнее.

Подготовка

Для начала нам необходимо подготовить изображение для логотипа. Во внешний отчет добавим макет табличного документа "Логотип", в который вставим объект "Картинка" с необходимым изображением.

 

 Настройка макета для логотипа

Не забудьте создать область табличного документа для ячеек, где находится изображение логотипа. В текущем примере область названа "Логотип". Также нужно создать область "СвернутьЛоготип", которая будет использоваться для сворачивания/разворачивания логотипа в сформированном отчете.

Теперь нам необходимо вмешаться в процесс компоновки отчета программным образом. Для этого в модуле объекта отчета в процедуре-обработчике "ПриКомпоновкеРезультата" напишем алгоритм формирования отчета. На первом этапе сформируем отчет таким, какой он был без логотипа. Алгоритм процедуры будет следующим:

 

 Вывод логотипа при компоновке результата

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

 

 Изменения для вывода логотипа

На этом процесс модификации отчета закончен. Посмотрим результат работы в режиме предприятия.

В режиме предприятия

Запустим созданный отчет в режиме предприятия. Мы увидим следующую картину:

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

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

Кейс №2: Вывод изображений номенклатуры

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

Предисловие

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

 

 Пример сформированного отчета с изображением

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

В чем проблема?

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

Например, добавим в поле макета рисунок, как показано на следующем изображении:

 

 Добавляем изображение в макет СКД

В теории, СКД должна вывести в данной ячейке добавленный рисунок, но этого не происходит:

 

 Нет изображения в отчете!

Как мы видим, создание собственного макета не является решением данной задачи. Использование собственного макета имеет весьма ограниченные возможности в сравнении с отчетами НЕ на СКД.

На просторах глобальной сети находил несколько вариантов решения по выводу изображений в подобных отчетах. В основном все они основывались на обработке табличного документа после вывода отчета, когда программным образом искалась колонка в табличном документе и обходилась в цикле для добавления в соответствующие ячейки рисунков. Однако после изменения настроек варианта отчета в пользовательском режиме подобные отчеты работали нестабильно. Представьте, что структура отчета вида "Список" была изменена на "Таблица". Тогда алгоритм сразу переставал работать, так как ориентироваться на колонку с изображениями уже было нельзя.

Рассмотрим универсальное решение данной задачи, работающее при любых настройках отчета и выполняемой достаточно оптимальным образом.

Универсальное решение

Так какое же решение использовать, чтобы сохранить все возможности СКД по настройке отчета и скорость его работы была на оптимальном уровне? Такое решение есть, давайте рассмотрим его подробно.

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

 

 Изменяем запрос набора данных для получения изображений

Запрос отчета на СКД выбирает в запросе номенклатуру и ссылку на файл основного изображения. Если мы выведем отчет на такой стадии, то он будет выглядеть следующим образом:

 

 Отчет еще не готов!

Из рисунка выше мы видим, что в отчете ссылка на присоединенный файл (элемент справочника "НоменклатураПрисоединенныеФайлы") отображается в виде представления (реквизит "Наименование"). Чтобы вмешаться в процесс формирования отчета и отобразить изображение в табличном документе, нам необходимо изменить алгоритм компоновки отчета.

Для начала в обработчике "ПриКомпоновкеРезультата" модуля объекта отчета отключим стандартную обработку и сформируем отчет полностью программным образом.

 

 Подготовим программное формирование отчета

Действия в программном коде подробно описаны в комментариях. Отмечу лишь важные моменты:

  1. В начале процедуры "ПриКомпоновкеРезультата" проводим инициализацию настроек.
  2. Далее по обычному алгоритму формируем отчет.
  3. Обязательно необходимо заполнить данные расшифровки, чтобы мы могли получать ссылки на данные, хранящиеся в ячейках табличного документа.

В результате выполнения отчета с внесенными изменениями, он выполнится точно таким же образом, как если бы мы никаких изменений не вносили. 

Теперь самый важный момент: после вывода отчета в табличный документ (метод "Выполнить" процессора вывода) нам необходимо обойти ВСЕ ячейки табличного документа, и если в ячейке содержится поле расшифровки значения с типом "СправочникСсылка.НоменклатураПрисоединенныеФайлы", необходимо добавить в эту ячейку объект "Рисунок" и заполнить его изображением, хранящемся в регистре сведений (схему хранения изображений для справочника "Номенклатура" смотри выше). На следующем скриншоте приведен программный код для выполнения описанных действий:

 

 Обходим ячейки отчета для добавления изображений

Код имеет подробные комментарии. В общих чертах алгоритм проверяет все ячейки табличного документа на значение расшифровки "СправочникСсылка.НоменклатураПрисоединенныеФайлы". Если ячейка имеет поле расшифровки с соответствующим типом данных, то выполняется функция "ПолучитьИзображение", в качестве параметра которому передается значение расшифровки:

 

 Получение двоичных данных изображения

Может возникнуть логичный вопрос: "Почему не получить двоичные данные для изображений в одном запросе?". Ответ прост. Если мы будем получать изображения из регистра двоичных данных файлов в одном запросе, то очень велика вероятность получить ошибку "Недостаточно памяти", если размер выбираемых изображений будет очень большим.

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

На этом реализация отчета закончена, посмотрим на его работу в режиме предприятия.

Что имеем

Сформируем отчет в виде простого списка номенклатуры. Результат будет следующим:

Теперь изменим настройки отчета. Вместо списка отчет будет иметь структуру таблицы, где строки — это ссылка на номенклатуру, а колонки — изображения.

Выше было упомянуто, что большинство решений по выводу картинок в отчетах на системе компоновки данных не работают стабильно для сложных вариантов настроек отчета пользователем.

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

 

 Финальный вариант после перемещения картинок в заголовки колонок таблицы

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

Платформенный путь

Хорошие новости! Платформа 1С начиная с версии 8.3.14 (причем режим совместимости тоже должен быть 8.3.14 и выше) позволяет штатными средствами выводить картинки в отчетах на СКД. Вот официальная информация. Использовать новый функционал проще простого! Нужно сделать следующие шаги:

  1. Убедиться, что у вас режим совместимости 8.3.14 и выше, иначе функционал не будет доступен.
  2. В запросе получить двоичные данные картинок в отдельном поле.
  3. Добавить это поле в выбранные поля.
  4. Добавить условное оформление для этого поля, указав отображение картинки, положение и размер. Последние две настройки по необходимости.
 

 Инструкция с картинками

Конечно, есть и некоторые ограничения. Например, картинку в шапку Вы так не выведите, но для решения большинства задач работает отлично.

Спасибо за внимание

Благодарю за интерес к статье! Это не первая, и, я надеюсь, не последняя статья про вывод изображений в отчетах на СКД на Инфостарте. Ждем появления информации об опыте наших коллег. В будущем подходы к решению подобных задач могут измениться. Будем следить за событиями.

А пока всем удачи, здоровья, успехов! Подписывайтесь на канал, оставляйте комментарии. 🙂

Другие ссылки

26 Comments

  1. rpgshnik

    Дельная статья и собрано в одном месте. Подача материала как всегда хорошая, лови ⭐

    Reply
  2. YPermitin

    (1) благодарю! 🙂

    Reply
  3. ZloyProger

    (0) Автор пеши есчо)) Как всегда отличная подача и материал интересный, лови заслуженный плюс.

    Reply
  4. YPermitin

    (3) хммм, и правда. Возможно забыл что-то, перепроверю сегодня 🙂

    Спасибо )

    Reply
  5. ZloyProger

    (4) Да я отредактировал уже :-(, там же в процедуре получения изображения проверка и возврат пустой картинки если не тот тип) Поспешишь — людей насмешишь)

    Reply
  6. YPermitin

    (5) очепятался по полной 🙂

    Reply
  7. glek

    Классная статья. Утаскиваю в закладки

    Reply
  8. makc2k

    Можно выводить картинки «при компоновке» анализируя значение элемента КД

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

    Показать

    Reply
  9. YPermitin

    (8) супер вариант!

    Если не будете против, то через пару дней этот вариант добавлю в конце публикации с упоминанием Вашего авторства.

    Reply
  10. ids79

    Спасибо за статью!

    Хорошие новости! Платформа 1С начиная с версии 8.3.14 (причем режим совместимости тоже должен быть 8.3.14 и выше) позволяет штатными средствами выводить картинки в отчетах на СКД

    Здорово, не знал. Ну наконец-то сделали )).

    Reply
  11. YPermitin

    (10) я сам сначала в шоке был 🙂

    Reply
  12. Den75Ch

    хорошая статья

    Reply
  13. AlX0id
    В запросе получить двоичные данные картинок в отдельном поле.

    Это, конечно, хорошо.. Но как тогда быть вот с этим?

    Если мы будем получать изображения из регистра двоичных данных файлов в одном запросе, то очень велика вероятность получить ошибку «Недостаточно памяти», если размер выбираемых изображений будет очень большим.
    Reply
  14. YPermitin

    (13) подходить разумно:)

    То есть:

    1. Не хранить картинки для отчетов по 2.5 МБ

    2. Ее формировать отчеты с выводом 1000 картинок. Все таки это больше какой-то точечный отчет.

    3. Смириться и докупить железа 🙂

    Reply
  15. AlX0id

    (14)

    Ну то есть 1сники чот сделали, но как это будет работать — хз )

    По поводу смириться и докупить железа — еще не факт, возможно, просто расширить файл подкачки — ведь, если я правильно понимаю — если не хватает памяти реальной — она свопается на диск. Уж такого чтобы вообще «Не хватает памяти» — это либо 32битная система должна быть или же сильно маленький своп-файл..

    Reply
  16. YPermitin

    (15) на маленьких отчетах у меня нареканий нет. На больших не смотрел.

    По нехватке памяти там сложнее. А на клиент-сервере еще вопросы с размером сеансовых данных будут и др. Вообщем надо тестить 🙂

    Reply
  17. makc2k

    (9) Конечно нет, тем более сам его унес из УЦ №1 )))

    Reply
  18. Yashazz

    Кстати в новых релизах хвалятся, что ещё более будут продвигать вопрос картинок в СКД. В условном оформлении там и прочая, даже на Зазеркалье кажись было.

    Reply
  19. YPermitin

    (18) про Зазеркалье не знал. Как-то упустил из виду.

    Reply
  20. pan_alex

    Отличная статья!

    Reply
  21. RocKeR_13

    (13) Еще на прошлых платформах, когда не добавили эту фишку, делал отчет по методу, описанном в сообщении (8). Так вот, отчет выводился, в котором было картинок на 6 Гб))) При этом временные файлы раздувались примерно до 18-20 Гб, но отчет формировался. На криво настроенной виртуалке время формирования приближалось к 5 часам))) Но тем не менее. Не думаю, что использование нового функционала платформы будет хуже)

    Reply
  22. YPermitin

    (21) однако.

    Прайс на 6 ГБ? 🙂

    Reply
  23. RocKeR_13

    (22) ну да, сеть магазинов одежды и обуви) Там картинки просто «жирные». На файловом варианте 1С пробовал этот же отчет на базе другого клиента — 800 строк с картинками выводились примерно минут 7-10

    Reply
  24. nsirotkin@mail.ru

    (23) Табличный документ получается сильно легче, а на экране или печати разницы не видно

    Функция ВывестиИзображениеВОбластиТД(ДанныеКартинки, ТД, Область)
    Изображение = ТД.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
    Изображение.РазмерКартинки = РазмерКартинки.Пропорционально;
    Индекс = ТД.Рисунки.Индекс(Изображение);
    //ТД.Рисунки[Индекс].Картинка = Новый Картинка(ДанныеКартинки, Истина);
    ////////////////////////////////////////////////////////////­////////////////////
    Картинка = Новый Картинка(ДанныеКартинки, Истина);
    Размер = ДанныеКартинки.Размер();
    МаксимальныйРазмер = 40000;
    Если Размер > МаксимальныйРазмер Тогда
    ОбрабатываемаяКартинка = Новый ОбрабатываемаяКартинка(Картинка);
    Попытка
    Если Картинка.ПлотностьПоВертикали() >= 150 Тогда
    ОбрабатываемаяКартинка.УстановитьПлотность(72, 72);
    КонецЕсли;
    Исключение
    
    КонецПопытки;
    //ОбрабатываемаяКартинка.Масштабировать(Макс(10,Окр(100*МаксимальныйРазмер/Размер)));
    Ширина = Картинка.Ширина();
    МаксимальнаяШирина = 320;
    Если Ширина > МаксимальнаяШирина Тогда
    ОбрабатываемаяКартинка.УстановитьРазмер(МаксимальнаяШирина,Окр(Картинка.Высота()/Ширина*МаксимальнаяШирина));
    КонецЕсли;
    Картинка = ОбрабатываемаяКартинка.ПолучитьКартинку();
    КонецЕсли;
    ТД.Рисунки[Индекс].Картинка = Картинка;
    ////////////////////////////////////////////////////////////­////////////////////
    
    ТД.Рисунки[Индекс].Расположить(Область);
    Возврат ТД.Рисунки[Индекс];
    КонецФункции
    

    Показать

    Reply
  25. ByNiko1984

    (0) статьи отличная. Плюс поставить не могу, говорит 5 минут назад ставил. А я только авторизовался.

    Пишите еще!

    Reply
  26. ByNiko1984

    (25) а нет, смог поставить. Магия….

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *