При формировании печатных форм в 1С:Предприятии программисты часто сталкиваются с задачей вывода графических объектов: логотипов компаний, чертежей номенклатуры, штрихкодов или изображений товаров. Стандартный вывод картинок «как есть» нередко приводит к тому, что изображение перекрывает соседние ячейки, вылезает за границы отведенной области макета или отображается в некорректном масштабе. Особые сложности возникают при динамическом расчете высоты строк и использовании метода Присоединить.
В этой статье мы подробно разберем, как решить эти проблемы, правильно спроектировать макет и красиво вписать изображение в область табличного документа, используя современные механизмы платформы «1С:Предприятие 8».
Начиная с относительно свежих релизов платформы 1С v8.3, разработчикам доступен наиболее элегантный и простой способ размещения изображений без написания сложного программного кода позиционирования. Картинку можно встроить непосредственно внутрь ячейки (или объединенной области ячеек) макета как обычный параметр.
Разберем по шагам, как это настроить в конфигураторе и вызвать в коде:
ПараметрИзображения.Пропорционально. Это позволит платформе автоматически сжимать или растягивать изображение под размеры ячейки без искажения пропорций.Теперь посмотрим на программный код заполнения такого макета. Он ничем не отличается от работы с обычными текстовыми параметрами:
// Получаем область макета, где настроен параметр картинки
ОбластьМакета = Макет.ПолучитьОбласть("СтрокаСКартинкой");
// Получаем двоичные данные картинки из хранилища значения (например, из справочника)
ДвоичныеДанныеКартинки = СтрокаТЧ.ФайлКартинки.Получить();
Если ЗначениеЗаполнено(ДвоичныеДанныеКартинки) Тогда
// Создаем объект Картинка и передаем его напрямую в параметр ячейки
ОбластьМакета.Параметры.ПараметрИзображения = Новый Картинка(ДвоичныеДанныеКартинки);
КонецЕсли;
// Выводим готовую область в итоговый документ
ДокументРезультат.Вывести(ОбластьМакета);
Преимущества данного метода: изображение жестко привязано к границам ячейки. При изменении пользователем ширины колонок или высоты строк картинка будет масштабироваться автоматически, никогда не «уплывая» за пределы назначенной ей области.
Если по каким-то причинам первый способ вам не подходит (например, вам требуется динамически создавать множество картинок в разных местах одной области или накладывать их друг на друга), придется использовать программное добавление графических объектов типа РисунокТабличногоДокумента.
Главная ошибка разработчиков при программном добавлении рисунков — попытка вручную рассчитать геометрические свойства Высота, Ширина, Верх и Лево в миллиметрах или пунктах. Размеры ячеек могут меняться в зависимости от данных, и жестко заданные координаты приведут к некрасивому наложению.
Для решения этой проблемы мы применим встроенный метод Расположить(), который автоматически «натягивает» графический объект на указанную область ячеек. Проанализируем пример кода:
// 1. Сначала выводим область строк без рисунка
ДокументРезультат.Вывести(ОбластьСтрокаДанных);
// 2. Создаем новый объект рисунка в результирующем документе
НовыйРисунок = ДокументРезультат.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
// 3. Заполняем картинку данными
ДвоичныеДанные = СтрокаТЧ.Чертеж.Получить();
Если ЗначениеЗаполнено(ДвоичныеДанные) Тогда
НовыйРисунок.Картинка = Новый Картинка(ДвоичныеДанные);
КонецЕсли;
// 4. Задаем режим масштабирования
НовыйРисунок.РазмерКартинки = РазмерКартинки.Пропорционально;
// 5. Определяем область ячеек в ДокументеРезультате, где должен лежать рисунок.
// Вычислим номер последней выведенной строки, чтобы привязаться к ней.
ТекущийНомерСтроки = ДокументРезультат.ВысотаТаблицы;
// Нам нужна область в текущей строке со 2-й по 5-ю колонку
ОбластьНазначения = ДокументРезультат.Область(ТекущийНомерСтроки, 2, ТекущийНомерСтроки, 5);
// 6. Позиционируем рисунок строго по границам выбранной области
НовыйРисунок.Расположить(ОбластьНазначения);
Чтобы рисунок выглядел эстетично и не выделялся черной рамкой или серым фоном на фоне печатной формы, мы можем отключить его границы и сделать подложку прозрачной:
// Отключаем видимость границ рисунка
НовыйРисунок.Линия = Новый Линия(ТипЛинииРисункаТабличногоДокумента.БезЛинии);
// Делаем фон рисунка прозрачным (без узора)
НовыйРисунок.Узор = РисунокУзораТабличногоДокумента.БезУзора;
При формировании сложных отчетов часто применяется метод Присоединить(), когда к уже выведенной строке справа пристыковываются дополнительные колонки (например, колонка с чертежом). Здесь кроется важный нюанс: при присоединении новой области высота результирующей строки определяется высотой уже выведенной левой части. Если левая часть строки содержала мало текста и была узкой, то присоединенная справа картинка сожмется до минимальных размеров или некрасиво выйдет за рамки строки.
Выясним причину такого поведения: автовысота строк принудительно подстраивается под текстовое содержимое, игнорируя размеры добавленных поверх ячеек рисунков.
Для обхода этого ограничения мы должны программно управлять высотой строки результирующего документа после того, как к ней присоединены все части. Рассмотрим правильный алгоритм:
// Выводим левую текстовую часть строки
ДокументРезультат.Вывести(ОбластьДанныеТекста);
// Присоединяем область, предназначенную под чертеж
ДокументРезультат.Присоединить(ОбластьПодЧертеж);
// Узнаем индекс строки, которая только что сформировалась в результате вывода и присоединения
НомерТекущейСтроки = ДокументРезультат.ВысотаТаблицы;
// Получаем всю строку целиком и принудительно задаем ей достаточную высоту в пунктах (например, 75 пунктов)
// Это гарантирует, что картинка не сожмется по вертикали.
СтрокаРезультата = ДокументРезультат.Область(НомерТекущейСтроки, , НомерТекущейСтроки, );
СтрокаРезультата.ВысотаСтроки = 75;
// Только ПОСЛЕ явной установки высоты строки выполняем позиционирование рисунка,
// иначе метод Расположить() рассчитает координаты по старой "узкой" строке.
НовыйРисунок = ДокументРезультат.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
НовыйРисунок.Картинка = Новый Картинка(СтрокаТЧ.Чертеж.Получить());
НовыйРисунок.РазмерКартинки = РазмерКартинки.Пропорционально;
// Позиционируем рисунок в созданной области
ОбластьДляКартинки = ДокументРезультат.Область(НомерТекущейСтроки, 6, НомерТекущейСтроки, 8);
НовыйРисунок.Расположить(ОбластьДляКартинки);
Для того чтобы картинки в вашем отчете всегда смотрелись гармонично, важно правильно выбрать свойство РазмерКартинки. Рассмотрим подробнее доступные варианты перечисления:
РазмерКартинки.Пропорционально — самый популярный и безопасный выбор. Изображение масштабируется до максимально возможных размеров области ячейки, сохраняя свое исходное соотношение сторон. Чертежи и схемы не будут искажены или растянуты.РазмерКартинки.Растянуть — картинка полностью заполняет всю область ячеек (и по ширине, и по высоте). Если пропорции области не совпадают с пропорциями картинки, изображение сожмется или растянется, что может выглядеть некрасиво.РазмерКартинки.АвтоРазмер — если физический размер картинки меньше ячейки, она выводится «как есть» по центру. Если картинка больше — она пропорционально сжимается, чтобы поместиться в рамки.РазмерКартинки.РеальныйРазмер — выводит картинку пиксель в пиксель. Если область ячейки меньше реального размера файла, изображение будет просто обрезано по правому и нижнему краю.Используя предложенные методики, мы можем гибко управлять графикой в отчетах любой сложности, добиваясь идеального визуального соответствия макетам печатных форм. В качестве готового образца реализации вывода факсимиле можно использовать пример внешней печатной формы с печатью и подписями на БСП.