Как вывести фотографию сотрудника в отчет или печатную форму 1С

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом
← На главную

При разработке внешних печатных форм или кастомных отчетов в конфигурации 1С:Зарплата и управление персоналом 3.1 часто возникает задача визуализации данных, а именно — вывода фотографии сотрудника. На первый взгляд задача кажется простой, но разработчики часто сталкиваются с ошибками типа Несоответствие типов или ситуациями, когда область для картинки остается пустой. Рассмотрим подробно, как правильно извлечь изображение из базы данных и корректно отобразить его в табличном документе.

Разбор архитектуры хранения фотографий

Прежде чем приступать к написанию кода, проанализируем, где и в каком виде хранятся фотографии в 1С. В типовом решении ЗУП 3.1 для этого используется регистр сведений ФотографииФизическихЛиц. Этот регистр имеет одно ключевое измерение — ФизическоеЛицо и ресурс Фотография с типом ХранилищеЗначений.

Важно понимать: данные в ресурсе Фотография хранятся не в виде готового объекта Картинка, а в упакованном виде внутри объекта ХранилищеЗначений. Это необходимо для оптимизации базы данных, но требует от программиста дополнительных действий по «распаковке» данных.

Способ 1: Получение фотографии через менеджер записи

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

Разберем по шагам алгоритм получения данных:

  1. Создаем менеджер записи регистра сведений.
  2. Устанавливаем отбор по нужному физическому лицу.
  3. Читаем запись из базы данных.
  4. Извлекаем данные из хранилища с помощью метода Получить().

Посмотрим на пример кода, который учитывает возможные ошибки типизации:


// Предположим, что ФизическоеЛицоСсылка — это ссылка на справочник ФизическиеЛица
Запись = РегистрыСведений.ФотографииФизическихЛиц.СоздатьМенеджерЗаписи();
Запись.ФизическоеЛицо = ФизическоеЛицоСсылка;
Запись.Прочитать();

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

Вывод картинки в табличный документ

Теперь, когда у нас есть объект ОбъектКартинка, нам нужно поместить его в макет. Рассмотрим ситуацию, когда мы программно добавляем рисунок в область макета.

Проанализируем процесс настройки свойств рисунка:


// Получаем область из макета
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");

// Добавляем новый рисунок типа "Картинка"
Рисунок = ОбластьЗаголовок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);

// Устанавливаем координаты и размеры (в миллиметрах)
Рисунок.Верх = 5; 
Рисунок.Высота = 40; 
Рисунок.Ширина = 30; 
Рисунок.Лево = 150; 

// Настраиваем поведение картинки внутри рамки
Рисунок.РазмерКартинки = РазмерКартинки.Пропорционально; 

// Присваиваем саму картинку
Если ОбъектКартинка <> Неопределено Тогда
    Рисунок.Картинка = ОбъектКартинка;
КонецЕсли;

// Выводим область в результирующий табличный документ
ТабДок.Вывести(ОбластьЗаголовок);

Использование РазмерКартинки.Пропорционально крайне важно. Если установить АвтоРазмер, фотография может исказить границы ячеек макета, а РеальныйРазмер может отобразить лишь фрагмент изображения, если исходный файл имеет высокое разрешение.

Способ 2: Оптимизированный вывод через запрос (для списков)

Если вам нужно вывести фотографии для списка из 100 сотрудников, использование СоздатьМенеджерЗаписи() в цикле будет крайне неэффективным, так как это порождает 100 отдельных обращений к серверу БД. В этом случае выясним причину медленной работы и заменим её на пакетный запрос.

Рассмотрим пример запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Фотографии.Фотография КАК Фотография,
    |   Сотрудники.Ссылка КАК Сотрудник
    |ИЗ
    |   Справочник.Сотрудники КАК Сотрудники
    |       ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ФотографииФизическихЛиц КАК Фотографии
    |       ПО Сотрудники.ФизическоеЛицо = Фотографии.ФизическоеЛицо
    |ГДЕ
    |   Сотрудники.Ссылка В(&МассивСотрудников)";

Запрос.УстановитьПараметр("МассивСотрудников", СписокСсылок);
Выборка = Запрос.Выполнить().Выбрать();

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

Типичные ошибки и способы их решения

При работе с изображениями часто возникают нюансы, которые могут поставить в тупик:

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

Использование функций БСП

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

Совет: При работе с большим количеством фотографий не забывайте об очистке памяти. После вывода каждого рисунка в табличный документ можно явно обнулять переменную, хранящую объект картинки (ОбъектКартинка = Неопределено;), чтобы сборщик мусора быстрее освобождал оперативную память сервера.

← На главную