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