Как экспортировать изображения из 1С в Excel без замедления работы?

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

При переносе доработок и отчетов со старых конфигураций 1С на обычных формах (например, УТ 10.3) на современные управляемые формы (например, УТ 11) разработчики часто сталкиваются с унаследованным кодом. Одним из таких «узких мест» является экспорт каталогов товаров или прайс-листов с картинками в Microsoft Excel через COM-соединение COMОбъект("Excel.Application").

Традиционный алгоритм выгрузки картинок через COM-объект выглядит следующим образом:

  1. Получение бинарных данных картинок номенклатуры на сервере.
  2. Передача массива структур с бинарными данными на клиент.
  3. Запись каждого изображения во временный файл на жесткий диск клиента.
  4. Вставка изображения в ячейку Excel с помощью метода Shapes.AddPicture().
  5. Удаление временного файла с диска.

Этот процесс сопряжен с огромными задержками. Основное время тратится на дисковые операции ввода-вывода (I/O) при сохранении сотен картинок на физический накопитель и их последующем чтении Excel-приложением. Давайте разберем, как можно кардинально ускорить этот процесс и избавиться от лишней работы с файловой системой.

Решение 1. Переход на использование Табличного документа (Рекомендуемый способ)

Самый логичный и производительный путь в управляемом приложении 1С — полностью отказаться от использования тяжеловесного COM-объекта Excel в пользу штатного объекта 1С ТабличныйДокумент. Платформа 1С умеет самостоятельно сохранять табличные документы в формат .xlsx со всеми картинками и форматированием, причем делает это на уровне платформы крайне быстро.

Рассмотрим по шагам, как реализовать этот подход:

Шаг 1. Создание структуры табличного документа и вывод картинок

Вместо передачи массива на клиент мы формируем табличный документ непосредственно на сервере. Для вывода изображений используется коллекция Рисунки области табличного документа.


// Пример формирования табличного документа на сервере
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("МакетЭкспорта");

// Начинаем автогруппировку, если нужно сворачивать группы (плюсики/минусики)
ТабДок.НачатьАвтогруппировкуСтрок();

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

ТабДок.ЗакончитьАвтогруппировкуСтрок();

Шаг 2. Сохранение в Excel

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

ТабДок.Записать(ПутьКФайлуЭксель, ТипФайлаТабличногоДокумента.XLSX);

Важный подводный камень при сохранении Табличного Документа в XLSX:

Разработчики часто сталкиваются с тем, что при экспорте табличного документа с картинками в формат XLSX итоговый файл начинает весить сотни мегабайт (даже если исходных картинок было немного). Это происходит потому, что 1С может сохранять картинки в несжатом формате BMP.

Чтобы избежать этой проблемы, обязательно устанавливайте свойство рисунка РазмерКартинки в значение РазмерКартинки.Растянуть или РазмерКартинки.Пропорционально. В современных релизах платформы это заставляет 1С сохранять исходное сжатие картинок (JPEG/PNG), что сохраняет адекватный размер файла Excel.

Решение 2. Прямая работа с XLSX-файлом как с ZIP-архивом (OpenXML)

Если вам требуется максимальная скорость формирования файлов (в десятки и сотни раз быстрее COM) и полная независимость от установленного Microsoft Office (например, когда сервер 1С работает под управлением ОС Linux), можно использовать прямую запись в XML-структуру XLSX.

Файл формата .xlsx — это обычный ZIP-архив. Мы можем наполнить его программно:

  1. Берем заранее подготовленный пустой шаблон .xlsx (файл-заготовку).
  2. Распаковываем его во временную директорию с помощью встроенного в 1С объекта ЧтениеZipФайла.
  3. Записываем бинарные данные изображений из базы напрямую в подпапку распакованного архива xl/media/ под уникальными именами (например, image1.jpg, image2.png).
  4. Программно модифицируем XML-файлы разметки листа (например, xl/drawings/drawing1.xml и файл связей xl/drawings/_rels/drawing1.xml.rels), прописывая туда пути к добавленным картинкам и координаты ячеек, в которых они должны отображаться.
  5. Запаковываем папку обратно в ZIP-архив с помощью объекта ЗаписьZipФайла и меняем расширение готового файла на .xlsx.

Этот метод требует детального изучения структуры OpenXML, но обеспечивает абсолютный рекорд скорости генерации отчетов.

Решение 3. Использование буфера обмена (для платформы 8.3.24 и выше)

Начиная с версии платформы 1С 8.3.24, разработчикам доступен новый инструмент — СредстваБуфераОбмена. С его помощью можно помещать картинки в системный буфер напрямую из двоичных данных без сохранения промежуточного файла на жесткий диск.

Схема работы выглядит следующим образом:


// Помещаем картинку в буфер обмена на клиенте
ДанныеБуфера = Новый Соответствие;
ДанныеБуфера.Вставить(СтандартныйФорматДанныхБуфераОбмена.Картинка, КартинкаИзБазы);
СредстваБуфераОбмена.УстановитьСодержимое(ДанныеБуфера);

// Вставляем изображение в Excel через COM
Лист.Cells(Строка, Колонка).Select();
Лист.Paste();

Важное ограничение: Программное использование буфера обмена может блокировать работу пользователя за компьютером во время выполнения экспорта, так как буфер является общим системным ресурсом. Кроме того, в некоторых версиях MS Office из-за внутренних различий в форматах картинок прямая вставка через буфер может вызывать искажение цветов или размеров изображения.

Решение 4. Оптимизация текущего алгоритма через RAM-диск

Если у вас нет времени переписывать весь legacy-код, завязанный на COM-объекты, можно ускорить дисковые операции «косметическим» путем.

Для этого можно оптимизировать запись временных файлов:

Резюме

Для долгосрочной перспективы и стабильной работы (особенно при переходе на Linux-серверы и Web-клиент) наиболее правильным решением является перенос выгрузки на Табличный документ 1С. Это избавит конфигурацию от зависимости от установленного пакета MS Office, решит проблему скорости за счет выполнения операций на сервере и позволит использовать стандартные механизмы группировок строк.

← На главную