Как вывести изображение из хранилища значений в печатную форму 1С?

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

При разработке печатных форм часто возникает задача вывода графической информации, которая хранится непосредственно в базе данных. Это могут быть логотипы компаний, подписи ответственных лиц, фотографии товаров или, как в нашем случае, карты геометки, полученные через внешние API. Основная сложность для начинающих разработчиков заключается в том, что изображение в базе хранится в специальном формате ХранилищеЗначения, который нельзя просто "вывести" в ячейку как текст.

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

Постановка задачи и анализ ситуации

Представим ситуацию: у нас есть документ, в котором реализовано получение карты через сервис Яндекс.Карты. Картинка сохраняется в реквизит Картинка с типом ХранилищеЗначения. Нам необходимо модифицировать существующий макет печати, чтобы в области подвала (Footer) отображалась эта карта. Рассмотрим типичный код сохранения изображения, который часто используется в управляемых формах:


&AtServer
Procedure BeforeWriteAtServer(Cancel, CurrentObject, WriteParameters)
    If IsTempStorageURL(PictureMap) Then
        // Помещаем картинку из временного хранилища в реквизит объекта
        CurrentObject.Picture = New ValueStorage(GetFromTempStorage(PictureMap));
    EndIf;
EndProcedure

Проблема заключается в том, что при попытке просто заполнить параметры макета через Параметры.Заполнить(Выборка), в печатной форме вместо картинки выводится текст "Picture ValueStorage". Это происходит потому, что система не знает, как визуализировать объект хранилища в текстовой ячейке.

Шаг 1. Подготовка макета табличного документа

Первым делом нам нужно подготовить сам макет. Вывод картинки в 1С осуществляется не в саму ячейку, а в специальный объект, который "плавает" над сеткой таблицы. Этот объект называется Рисунок.

  1. Откроем макет печатной формы в конфигураторе.
  2. Выберем область, куда должна выводиться картинка (например, область Footer).
  3. В главном меню выберем: Таблица — Рисунки — Вставить картинку.
  4. После выбора любой временной картинки (или просто создания пустой рамки), на макете появится объект.
  5. Важно: Нажмите правой кнопкой мыши на вставленный рисунок, выберите "Свойства". В поле Имя укажите понятный идентификатор, например, КартаМаршрута. Это имя мы будем использовать в коде.
  6. Настройте свойство Размер картинки. Мы рекомендуем установить значение Пропорционально, чтобы карта не искажалась при изменении размеров области.

Шаг 2. Программный вывод изображения

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

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


Procedure Печать(Spreadsheet, Ref) Export
    Template = Documents.Shipment.GetTemplate("Печать");
    // ... получение данных запросом ...
    
    Selection = Query.Execute().Select();
    
    While Selection.Next() Do
        // Получаем область подвала из макета
        AreaFooter = Template.GetArea("Footer");
        
        // Извлекаем картинку из ХранилищаЗначения реквизита ссылки
        // Обратите внимание: метод Get() возвращает объект Картинка
        ValueFromStorage = Selection.Picture.Get();
        
        If ValueFromStorage <> Неопределено Тогда
            // Ищем наш рисунок в коллекции Рисунки текущей области
            // Имя "КартаМаршрута" должно совпадать с именем в макете
            AreaFooter.Drawings.КартаМаршрута.Picture = ValueFromStorage;
        Else
            // Если картинки нет, можно скрыть рамку, чтобы не было пустого места
            AreaFooter.Drawings.КартаМаршрута.Visible = False;
        EndIf;
        
        // Заполняем остальные параметры области (текстовые поля)
        AreaFooter.Parameters.Fill(Selection);
        
        // Выводим готовую область в итоговый документ
        Spreadsheet.Put(AreaFooter);
    EndDo;
EndProcedure

Разбор ключевых методов

Рассмотрим подробнее, что происходит в коде. Основная работа выполняется через коллекцию Drawings (Рисунки). Каждый табличный документ (или его область) содержит эту коллекцию.

Метод Get() объекта ValueStorage: Этот метод извлекает содержимое из хранилища. Так как мы записывали туда объект Picture (Картинка), то и Get() вернет нам именно Picture. Если в хранилище пусто, метод вернет Undefined (Неопределено), поэтому проверка на пустое значение обязательна для избежания ошибок.

Прямое обращение через точку: В примере выше мы использовали Selection.Picture. Однако помните, что в языке запросов 1С напрямую прочитать данные из ХранилищеЗначения нельзя. Запрос вернет сам объект хранилища. Если вы работаете не через запрос, а напрямую с объектом или ссылкой, код будет выглядеть так: Ref.Picture.Get().

Шаг 3. Оптимизация и работа с памятью

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

  1. Избегайте чтения в цикле: Если вы печатаете 100 документов, обращение Selection.Picture.Get() в каждом цикле может существенно замедлить процесс, так как бинарные данные картинки считываются из базы каждый раз. Если картинка статична (например, логотип компании), лучше получить ее один раз перед циклом.
  2. Управление размером: Используйте свойство SizeMode (РазмерКартинки). Для карт идеально подходит PictureSizeMode.Proportional. Если же вы выводите штрих-код или QR-код, лучше использовать PictureSizeMode.RealSize, чтобы избежать проблем со сканированием.
  3. Очистка ресурсов: При получении картинки из интернета, как в исходном сообщении темы, автор использовал запись во временный файл на диске C:\Users\Admin\.... Рассмотрим, как сделать это правильнее с использованием временных файлов системы:

// Правильный способ работы с временными файлами
TempFileName = GetTempFileName("png");
Result.GetBodyAsBinaryData().Write(TempFileName);
Picture = New Picture(TempFileName);
// ... дальнейшая работа ...
// После завершения желательно удалить файл
DeleteFiles(TempFileName);

Дополнительные возможности: Вывод без использования Хранилища

Иногда возникает вопрос: можно ли вывести картинку в макет, не сохраняя ее в базу, а имея только навигационную ссылку во временном хранилище? Да, это возможно. Для этого в процедуре печати (если она выполняется на сервере) можно использовать функцию GetFromTempStorage().


// Пример вывода из временного хранилища (например, при предпросмотре)
If IsTempStorageURL(AddressInStorage) Then
    BinaryData = GetFromTempStorage(AddressInStorage);
    AreaFooter.Drawings.КартаМаршрута.Picture = New Picture(BinaryData);
EndIf;

Подведем итог. Для успешного вывода картинки из хранилища значений в макет 1С нужно выполнить три условия: создать объект Рисунок в макете, присвоить ему уникальное Имя и программно передать в свойство Picture этого рисунка данные, извлеченные методом Get() из реквизита. Этот метод является стандартным и наиболее надежным для платформы 1С:Предприятие 8.3.

← На главную