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

Так делаются прайс-листы с фото номенклатуры, списки сотрудников с фотографиями, каталоги оборудования. Ниже — пошаговая реализация, готовый код и то, что стоит сделать, чтобы отчёт не тормозил.

Подготовка схемы: поле с картинкой

Сначала определяемся, где хранится изображение и как его получить в коде:

Где хранится картинкаЧто выбирать в запросКак получить двоичные данные
Реквизит типа ХранилищеЗначения (например, регистр «ФотографииФизическихЛиц» в ЗУП)Само полеЗначение.Получить()
Присоединённый файл БСП (например, файл картинки номенклатуры)Ссылку на файлРаботаСФайлами.ДвоичныеДанныеФайла(Ссылка)
Двоичные данные в своём реквизитеСсылку на объектЧтение реквизита по ссылке

Схема делается конструктором как обычно: набор данных с нужными полями плюс поле-носитель картинки, например Фотография. В настройках для начала достаточно одной группировки детальных записей. Поле Фотография должно быть среди выбранных — иначе его не будет в данных расшифровки, и найти ячейку не получится.

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

Формирование отчета в ПриКомпоновкеРезультата

В модуле объекта отчёта отключаем стандартную обработку и выводим результат в ДокументРезультат сами. Данные расшифровки обязательно передаём в компоновщик макета и процессор — по ним будем искать ячейки.

1С
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	Настройки = КомпоновщикНастроек.ПолучитьНастройки();

	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);

	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);

	РазместитьКартинки(ДокументРезультат, ДанныеРасшифровки, "Фотография");

КонецПроцедуры

Размещение картинок по ячейкам

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

Алгоритм: идём по ячейкам результата, у каждой берём идентификатор расшифровки, по нему — значения полей. Если среди них есть поле с картинкой и значение заполнено, увеличиваем высоту строки, создаём рисунок и располагаем его в области ячейки.

1С
// Размещает картинки в ячейках, где выведено поле ИмяПоля.
Процедура РазместитьКартинки(ДокументРезультат, ДанныеРасшифровки, ИмяПоля, ВысотаСтроки = 80)

	Для НомерСтроки = 1 По ДокументРезультат.ВысотаТаблицы Цикл
		Для НомерКолонки = 1 По ДокументРезультат.ШиринаТаблицы Цикл

			Область = ДокументРезультат.Область(НомерСтроки, НомерКолонки);
			Если ТипЗнч(Область.Расшифровка) <> Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
				Продолжить;
			КонецЕсли;

			ЭлементРасшифровки = ДанныеРасшифровки.Элементы[Область.Расшифровка];
			Если ТипЗнч(ЭлементРасшифровки) <> Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
				Продолжить;
			КонецЕсли;

			ЗначениеПоля = ЭлементРасшифровки.ПолучитьПоля().Найти(ИмяПоля);
			Если ЗначениеПоля = Неопределено Тогда
				Продолжить;
			КонецЕсли;

			ДвоичныеДанные = ДвоичныеДанныеКартинки(ЗначениеПоля.Значение);
			Если ДвоичныеДанные = Неопределено Тогда
				Продолжить;
			КонецЕсли;

			// Текст ячейки (представление ссылки) под картинкой не нужен
			Область.Текст = "";
			Область.АвтоВысотаСтроки = Ложь;
			Область.ВысотаСтроки = ВысотаСтроки;

			Рисунок = ДокументРезультат.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
			Рисунок.Картинка = Новый Картинка(ДвоичныеДанные);
			Рисунок.РазмерКартинки = РазмерКартинки.Пропорционально;
			Рисунок.Расположить(Область);

		КонецЦикла;
	КонецЦикла;

КонецПроцедуры

// Возвращает двоичные данные изображения по значению поля или Неопределено.
Функция ДвоичныеДанныеКартинки(Значение)

	Если ТипЗнч(Значение) = Тип("ХранилищеЗначения") Тогда
		Данные = Значение.Получить();
		Возврат ?(ТипЗнч(Данные) = Тип("ДвоичныеДанные"), Данные, Неопределено);
	ИначеЕсли ТипЗнч(Значение) = Тип("ДвоичныеДанные") Тогда
		Возврат Значение;
	КонецЕсли;

	// Для присоединённых файлов БСП:
	// Возврат РаботаСФайлами.ДвоичныеДанныеФайла(Значение);
	Возврат Неопределено;

КонецФункции

В хранилище значения может лежать как ДвоичныеДанные, так и уже Картинка — посмотрите, что пишет ваша конфигурация, и при необходимости добавьте ветку с Тип("Картинка").

Как ускорить отчет с картинками

На списке в сотню строк код выше работает быстро. На прайсе в несколько тысяч позиций начинаются проблемы. Что помогает:

  • Перебирать одну колонку. Найдите колонку с полем картинки на первой строке данных и дальше проверяйте только её. Полный перебор «строки × колонки» на широком отчёте — тысячи лишних обращений к данным расшифровки.
  • Выбирать ссылку, а не данные. Изображения загружаются только для реально выведенных строк.
  • Кешировать. Если одна картинка повторяется (например, фото товара в нескольких группировках), держите соответствие «ссылка → картинка» и не читайте файл повторно.
  • Хранить превью. Фото с телефона весит мегабайты, а в ячейке нужен квадрат 80 пикселей. Табличный документ со всеми оригиналами долго передаётся на клиент, особенно в веб-клиенте. Отдельный уменьшенный файл для отчётов решает проблему.
  • Ограничить вывод. Для огромных прайсов картинки лучше выводить по флажку в настройках отчёта.

Типичные ошибки

  • Картинки не появляются. Поле с картинкой не выбрано в настройках варианта — его нет в данных расшифровки. Или данные расшифровки не переданы в компоновщик макета.
  • Найти возвращает Неопределено. В расшифровке поле называется не так, как вы ищете: для полей через точку имя будет вида Номенклатура.ФайлКартинки.
  • Картинка наезжает на соседние строки. Не отключена автовысота строки или рисунок расположен до изменения высоты.
  • Ошибка «Недопустимое значение» при создании картинки. В хранилище не изображение, а другой тип данных или пустое значение — проверяйте тип перед Новый Картинка.
  • Отчёт не открывается у пользователя. Нет прав на регистр или справочник с файлами. Проверьте роли — либо читайте картинки в привилегированном режиме, если это допустимо по политике безопасности.
Отчёт с картинками — это обычный отчёт на СКД плюс один проход по результату. Не храните изображения в запросе и не перебирайте весь документ, и он останется быстрым.

Если нужен прайс с фотографиями в виде печатной формы документа, а не отчёта, задача решается макетом и тем же объектом Рисунки — это часть работы над печатными формами 1С. Отчёты с нестандартным выводом делаю в рамках услуги отчёты на СКД, кадровые отчёты в ЗУП — в доработке 1С:ЗУП.

Итог

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