Возникла необходимость написать парсер для чтения прайс-листов поставщиков, с чтением картинок. Среди публикаций нашел вот эту Сохранение картинки из MS Excel в файл без использования внешних компонент — в ней описано, как скопировать изображение во временный лист Excel, на котором создается диаграмма, в которую заливается картинка с последующим экспортом диаграммы в файл. Работает отлично, за исключением того, что диаграмма сохраняется с двумя разрешениями — для печати и как на экране, а очень хотелось получить изображение с исходным разрешением именно таким, в котором картинка была помещена в книгу (для файла, в котором не было сжатия изображений).
Способа работы через коллекцию Shapes я не нашел, зато есть способ сохранить файл как Web-архив, открыть его архиватором и получить нужные изображения в виде набора файлов с именами "Image1", "Image2" и так далее. Правда не совсем ясно, какое изображение в какой ячейке находится и в каком конкретно порядке они выгружены.
Нужные данные для случая, когда книга состоит из одного листа содержатся в файлах "drawing1.xml" и "drawing1.xml.rels" внутри web-архива. Картинки лежат в папке "xl/media/" архива.
Приведенная ниже функция сохраняет все данные в каталог временных файлов 1с, но можно указать любое другое нужное место.
Функция ВыгрузитьКартинки(Путь) Экспорт // Путь к исходному файлу Excel
АрхивныеДанные = Новый ТаблицаЗначений;
АрхивныеДанные.Колонки.Добавить("ИД"); // rId - внутренний идентификатор
АрхивныеДанные.Колонки.Добавить("НомерСтроки",Новый ОписаниеТипов("Число"));
АрхивныеДанные.Колонки.Добавить("НомерКолонки",Новый ОписаниеТипов("Число"));
АрхивныеДанные.Колонки.Добавить("ИмяФайла");
АрхивныеДанные.Колонки.Добавить("КороткоеИмяФайла"); // Image1 ...
ИмяФайлаПутей = "";
ИмяФайлаКоординат = "";
Читалка = Новый ЧтениеZipФайла(Путь);
ВотВамКаталог = ПолучитьИмяВременногоФайла();
Для Каждого Эл Из Читалка.Элементы Цикл
Если Эл.Путь = "xl/media/" Тогда // это папка с картинками - элемент - картинка
Читалка.Извлечь(Эл,ВотВамКаталог,РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
НС = АрхивныеДанные.Добавить();
НС.КороткоеИмяФайла = Эл.Имя;
НС.ИмяФайла = ВотВамКаталог + "" + Эл.Имя;
ИначеЕсли Эл.ПолноеИмя = "xl/drawings/drawing1.xml" Тогда
Читалка.Извлечь(Эл,ВотВамКаталог,РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
ИмяФайлаКоординат = ВотВамКаталог + "" + Эл.Имя;
ИначеЕсли Эл.ПолноеИмя = "xl/drawings/_rels/drawing1.xml.rels" Тогда
Читалка.Извлечь(Эл,ВотВамКаталог,РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
ИмяФайлаПутей = ВотВамКаталог + "" + Эл.Имя;
КонецЕсли;
КонецЦикла;
//ИмяФайлаПутей
ЧтениеФайлаXML = Новый ЧтениеXML;
ЧтениеФайлаXML.ОткрытьФайл(ИмяФайлаПутей);
Пока ЧтениеФайлаXML.Прочитать() Цикл
Если ЧтениеФайлаXML.Имя = "Relationship" Тогда
ИД = "";
КороткоеИмя = "";
Пока ЧтениеФайлаXML.СледующийАтрибут() Цикл
Если ЧтениеФайлаXML.Имя = "Id" Тогда
Ид = ЧтениеФайлаXML.Значение;
ИначеЕсли ЧтениеФайлаXML.Имя = "Target" Тогда
КороткоеИмя = ЧтениеФайлаXML.Значение; // ../media/image3.jpeg
ПозНачала = Найти(КороткоеИмя,"/image");
Если ПозНачала > 0 Тогда
КороткоеИмя = Сред(КороткоеИмя,ПозНачала + 1,СтрДлина(КороткоеИмя) - ПозНачала);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(КороткоеИмя) И ЗначениеЗаполнено(ИД) Тогда
СтрокаДанных = АрхивныеДанные.Найти(КороткоеИмя,"КороткоеИмяФайла");
Если СтрокаДанных <> Неопределено Тогда
СтрокаДанных.ИД = ИД;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
//ИмяФайлаКоординат
ЗаголовокНачалоУзла = "xdr:twoCellAnchor";
ЗаголовокНачалоУзла1 = "xdr:oneCellAnchor";
ЗаголовокНачалоКоординат = "xdr:from";
ЗаголовокНачалаКоординатКолонка = "xdr:col";
ЗаголовокНачалаКоординатСтрока = "xdr:row";
ЗаголовокНачалаИдентификатора = "a:blip";
ИмяАтрибутаИдентификатора = "r:embed";
//Заголовок
ЧтениеФайлаXML = Новый ЧтениеXML;
ЧтениеФайлаXML.ОткрытьФайл(ИмяФайлаКоординат);
ПутьЧтения = "";
Пока ЧтениеФайлаXML.Прочитать() Цикл
Если ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И (ЧтениеФайлаXML.Имя = ЗаголовокНачалоУзла Или ЧтениеФайлаXML.Имя = ЗаголовокНачалоУзла1) Тогда
ПутьЧтения = "Узел";
Данные = Новый Структура("Столбец,Строчка,Ид");
ИначеЕсли ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.КонецЭлемента И (ЧтениеФайлаXML.Имя = ЗаголовокНачалоУзла Или ЧтениеФайлаXML.Имя = ЗаголовокНачалоУзла1) Тогда
СтрокиДанных = АрхивныеДанные.НайтиСтроки(Новый Структура("Ид",Данные.Ид));
СтрокаДляЗаполнения = Неопределено;
Для Каждого Стр Из СтрокиДанных Цикл
Если Не ЗначениеЗаполнено(Стр.НомерСтроки) Тогда
СтрокаДляЗаполнения = Стр;
Прервать;
КонецЕсли;
КонецЦикла;
Если СтрокаДляЗаполнения = Неопределено Тогда
СтрокаДляЗаполнения = АрхивныеДанные.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаДляЗаполнения,СтрокиДанных[0],,"НомерСтроки,НомерКолонки");
КонецЕсли;
СтрокаДляЗаполнения.НомерСтроки = Данные.Строчка;
СтрокаДляЗаполнения.НомерКолонки = Данные.Столбец;
ПутьЧтения = "";
КонецЕсли;
Если ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеФайлаXML.Имя = ЗаголовокНачалоКоординат И Найти(ПутьЧтения,"Узел") > 0 Тогда
ПутьЧтения = ПутьЧтения + "Координаты";
ИначеЕсли ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеФайлаXML.Имя = ЗаголовокНачалоКоординат Тогда
ПутьЧтения = СтрЗаменить(ПутьЧтения,"Координаты","");
КонецЕсли;
Если ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеФайлаXML.Имя = ЗаголовокНачалаКоординатСтрока И Найти(ПутьЧтения,"Координаты") > 0 Тогда
ЧтениеФайлаXML.Прочитать();
Данные.Вставить("Строчка",Число(ЧтениеФайлаXML.Значение));
КонецЕсли;
Если ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеФайлаXML.Имя = ЗаголовокНачалаКоординатКолонка И Найти(ПутьЧтения,"Координаты") > 0 Тогда
ЧтениеФайлаXML.Прочитать();
Данные.Вставить("Столбец",Число(ЧтениеФайлаXML.Значение));
КонецЕсли;
Если ЧтениеФайлаXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеФайлаXML.Имя = ЗаголовокНачалаИдентификатора И Найти(ПутьЧтения,"Узел") > 0 Тогда
Данные.Вставить("Ид",ЧтениеФайлаXML.ПолучитьАтрибут(ИмяАтрибутаИдентификатора));
КонецЕсли;
КонецЦикла;
Возврат АрхивныеДанные;
КонецФункции
Спасибо, очень полезная статья.