При переносе доработок и отчетов со старых конфигураций 1С на обычных формах (например, УТ 10.3) на современные управляемые формы (например, УТ 11) разработчики часто сталкиваются с унаследованным кодом. Одним из таких «узких мест» является экспорт каталогов товаров или прайс-листов с картинками в Microsoft Excel через COM-соединение COMОбъект("Excel.Application").
Традиционный алгоритм выгрузки картинок через COM-объект выглядит следующим образом:
Shapes.AddPicture().Этот процесс сопряжен с огромными задержками. Основное время тратится на дисковые операции ввода-вывода (I/O) при сохранении сотен картинок на физический накопитель и их последующем чтении Excel-приложением. Давайте разберем, как можно кардинально ускорить этот процесс и избавиться от лишней работы с файловой системой.
Самый логичный и производительный путь в управляемом приложении 1С — полностью отказаться от использования тяжеловесного COM-объекта Excel в пользу штатного объекта 1С ТабличныйДокумент. Платформа 1С умеет самостоятельно сохранять табличные документы в формат .xlsx со всеми картинками и форматированием, причем делает это на уровне платформы крайне быстро.
Рассмотрим по шагам, как реализовать этот подход:
Шаг 1. Создание структуры табличного документа и вывод картинок
Вместо передачи массива на клиент мы формируем табличный документ непосредственно на сервере. Для вывода изображений используется коллекция Рисунки области табличного документа.
// Пример формирования табличного документа на сервере
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("МакетЭкспорта");
// Начинаем автогруппировку, если нужно сворачивать группы (плюсики/минусики)
ТабДок.НачатьАвтогруппировкуСтрок();
Пока ВыборкаНоменклатуры.Следующий() Цикл
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.Номенклатура = ВыборкаНоменклатуры.Наименование;
// Получаем двоичные данные картинки
ДвоичныеДанныеКартинки = ПрисоединенныеФайлы.ПолучитьДвоичныеДанныеФайла(ВыборкаНоменклатуры.ФайлКартинки);
Если ДвоичныеДанныеКартинки <> Неопределено Тогда
// Создаем объект Картинка из двоичных данных напрямую, без сохранения на диск
КартинкаНоменклатуры = Новый Картинка(ДвоичныеДанныеКартинки);
// Добавляем рисунок в область табличного документа
НовыйРисунок = ОбластьСтрока.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
НовыйРисунок.Картинка = КартинкаНоменклатуры;
// Позиционируем картинку в нужные ячейки (например, в колонку 2)
НовыйРисунок.Расположить(ОбластьСтрока.Область("R1C2"));
// КРИТИЧЕСКИ ВАЖНО: настраиваем размер во избежание раздувания файла
НовыйРисунок.РазмерКартинки = РазмерКартинки.Растянуть;
КонецЕсли;
ТабДок.Вывести(ОбластьСтрока, ВыборкаНоменклатуры.Уровень);
КонецЦикла;
ТабДок.ЗакончитьАвтогруппировкуСтрок();
Шаг 2. Сохранение в Excel
После заполнения табличного документа его можно записать в файл на сервере или передать на клиент и сохранить там:
ТабДок.Записать(ПутьКФайлуЭксель, ТипФайлаТабличногоДокумента.XLSX);
Важный подводный камень при сохранении Табличного Документа в XLSX:
Разработчики часто сталкиваются с тем, что при экспорте табличного документа с картинками в формат XLSX итоговый файл начинает весить сотни мегабайт (даже если исходных картинок было немного). Это происходит потому, что 1С может сохранять картинки в несжатом формате BMP.
Чтобы избежать этой проблемы, обязательно устанавливайте свойство рисунка РазмерКартинки в значение РазмерКартинки.Растянуть или РазмерКартинки.Пропорционально. В современных релизах платформы это заставляет 1С сохранять исходное сжатие картинок (JPEG/PNG), что сохраняет адекватный размер файла Excel.
Если вам требуется максимальная скорость формирования файлов (в десятки и сотни раз быстрее COM) и полная независимость от установленного Microsoft Office (например, когда сервер 1С работает под управлением ОС Linux), можно использовать прямую запись в XML-структуру XLSX.
Файл формата .xlsx — это обычный ZIP-архив. Мы можем наполнить его программно:
.xlsx (файл-заготовку).ЧтениеZipФайла.xl/media/ под уникальными именами (например, image1.jpg, image2.png).xl/drawings/drawing1.xml и файл связей xl/drawings/_rels/drawing1.xml.rels), прописывая туда пути к добавленным картинкам и координаты ячеек, в которых они должны отображаться.ЗаписьZipФайла и меняем расширение готового файла на .xlsx.Этот метод требует детального изучения структуры OpenXML, но обеспечивает абсолютный рекорд скорости генерации отчетов.
Начиная с версии платформы 1С 8.3.24, разработчикам доступен новый инструмент — СредстваБуфераОбмена. С его помощью можно помещать картинки в системный буфер напрямую из двоичных данных без сохранения промежуточного файла на жесткий диск.
Схема работы выглядит следующим образом:
// Помещаем картинку в буфер обмена на клиенте
ДанныеБуфера = Новый Соответствие;
ДанныеБуфера.Вставить(СтандартныйФорматДанныхБуфераОбмена.Картинка, КартинкаИзБазы);
СредстваБуфераОбмена.УстановитьСодержимое(ДанныеБуфера);
// Вставляем изображение в Excel через COM
Лист.Cells(Строка, Колонка).Select();
Лист.Paste();
Важное ограничение: Программное использование буфера обмена может блокировать работу пользователя за компьютером во время выполнения экспорта, так как буфер является общим системным ресурсом. Кроме того, в некоторых версиях MS Office из-за внутренних различий в форматах картинок прямая вставка через буфер может вызывать искажение цветов или размеров изображения.
Если у вас нет времени переписывать весь legacy-код, завязанный на COM-объекты, можно ускорить дисковые операции «косметическим» путем.
Для этого можно оптимизировать запись временных файлов:
ПолучитьИмяВременногоФайла(). Платформа создает файлы в системной временной папке, которая часто кэшируется операционной системой, а также автоматически очищает их по завершении сеанса.W:\), вы уберете физическую задержку дискового ввода-вывода. Оперативная память работает в тысячи раз быстрее классических HDD и даже современных SSD-накопителей, что практически полностью нивелирует задержки при сохранении и удалении временных файлов.Для долгосрочной перспективы и стабильной работы (особенно при переходе на Linux-серверы и Web-клиент) наиболее правильным решением является перенос выгрузки на Табличный документ 1С. Это избавит конфигурацию от зависимости от установленного пакета MS Office, решит проблему скорости за счет выполнения операций на сервере и позволит использовать стандартные механизмы группировок строк.