При загрузке прайс-листов или каталогов от поставщиков разработчики 1С часто сталкиваются с задачей извлечения изображений, встроенных прямо в ячейки Excel. На первый взгляд, прямых свойств для доступа к картинкам и их координатам нет. Разберем по шагам несколько эффективных способов решения этой задачи, выясним причину ограничений стандартных методов и проанализируем ситуацию с форматами файлов.
Самый простой и «нативный» подход — попытаться прочитать файл Excel встроенными средствами платформы. Рассмотрим подробнее этот метод.
Для этого мы можем загрузить файл в объект ТабличныйДокумент, а затем обойти его коллекцию рисунков. Логика работы следующая:
ТабличныйДокумент.Прочитать, указав путь к нашему файлу Excel.ТабличныйДокумент.Рисунки.Картинка и определяем координаты (строку и колонку), используя свойства расположения рисунка.Ограничения метода: На практике мы часто сталкиваемся с тем, что этот способ срабатывает не всегда. Во-первых, старые форматы .xls читаются платформой с ошибками (иногда пропадает не только графика, но и текст). Во-вторых, картинки в Excel часто вставляются «поверх ячеек» в виде плавающих элементов (floating shapes), которые могут игнорироваться механизмом чтения 1С.
Если штатный табличный документ не справляется, посмотрим на пример использования технологии COM. Этот вариант позволяет взаимодействовать с файлом через сам Excel.
В объектной модели Excel картинки хранятся как объекты типа Shape. У них нет прямого метода сохранения на диск, поэтому мы применим программную хитрость. Разберем по шагам алгоритм извлечения:
Shapes (или Pictures) на активном листе.CopyPicture(), который помещает ее в буфер обмена Windows.Chart).Export(), который сохраняет ее содержимое на диск (например, в формате JPG).ХранилищеЗначения.Ограничения метода: Работа через COM требует обязательного наличия установленного пакета MS Office на том компьютере или сервере, где выполняется код. Если ваш сервер 1С развернут на базе ОС Linux, этот метод окажется нерабочим.
Теперь проанализируем самое надежное, быстрое и современное решение. Современные файлы с расширением .xlsx представляют собой стандартизированный пакет OpenXML. По сути, это обычный ZIP-архив с XML-файлами и медиаданными внутри.
Рассмотрим подробнее, как мы можем программно извлечь из него нужные данные без использования COM:
.xlsx и программно меняем его расширение на .zip.ЧтениеZipФайла) распаковываем архив во временную директорию.xl/media. Именно там лежат все оригинальные графические файлы (jpeg, png) без потери качества.xl/drawings и находим файлы вида drawing1.xml. Это карта расположения объектов на листе.Выясним причину, почему именно этот XML-файл так важен. Прочитав drawing1.xml средствами 1С (используя ЧтениеXML или ПостроительDOM), мы обнаружим специальные теги-якоря. Обычно они называются xdr:twoCellAnchor или xdr:oneCellAnchor.
Внутри этих тегов хранятся координаты привязки xdr:from (левый верхний угол) и xdr:to (правый нижний угол). В них четко прописаны индексы:
xdr:col — индекс колонки;xdr:row — индекс строки.Сопоставив идентификатор картинки из этого XML-узла с физическим файлом в папке xl/media, мы абсолютно точно определим, в какой строке прайс-листа находится то или иное изображение. После этого останется лишь сопоставить данные с нашей табличной частью в 1С.
Если задача стоит на потоке, и самостоятельное написание парсера XML кажется избыточным, рассмотрим альтернативу. Многие разработчики используют готовые внешние компоненты, написанные на C++, C# или Python.
Такие компоненты подключаются к 1С и умеют напрямую читать структуру .xlsx прямо в памяти сервера. Они самостоятельно извлекают двоичные данные картинок вместе с их координатами (строка, колонка) и возвращают их в 1С уже в виде удобных структур или таблиц значений. Этот метод объединяет скорость чтения OpenXML и отсутствие необходимости устанавливать MS Excel, значительно экономя ресурсы сервера.
Используя любой из описанных выше методов (с упором на парсинг OpenXML для современных конфигураций), вы сможете надежно и корректно загружать прайс-листы с визуальным контентом в свою информационную базу.