При интеграции 1С с офисными пакетами часто возникает задача автоматического чтения данных из файлов Microsoft Word. Если текстовые данные из ячеек таблиц извлекаются стандартным обращением через свойство Range().Text, то с графическими объектами разработчики сталкиваются со сложностями. В объектной модели Microsoft Word у объектов InlineShape и Shape отсутствует встроенный прямой метод сохранения графических данных в файл на диске.
Проанализируем специфику размещения графики в документе и разберем два надежных способа программного получения изображений средствами 1С.
Прежде чем приступать к программной обработке, выясним причину различий в доступе к картинкам:
InlineShapes диапазона ячейки. Если же картинка плавающая (с обтеканием текстом, за текстом или перед текстом), она попадает в коллекцию Shapes или ShapeRange.Word.Application на стороне сервера 1С требует наличия установленного пакета Microsoft Office, корректной настройки DCOM и не поддерживается на серверах под управлением Linux.Файлы формата .docx представляют собой стандартные архивы OpenXML. Все внедренные медиафайлы хранятся в несжатом или сжатом виде внутри структуры архива в каталоге word/media/. Это позволяет извлекать изображения штатными средствами платформы 1С без вызова сторонних программ и без установки Microsoft Word.
Разберем по шагам алгоритм извлечения:
.docx во временный каталог с помощью объекта ЧтениеZipФайла.word/_rels/document.xml.rels и структуру документа word/document.xml, сопоставляя ячейку таблицы с идентификатором rId и файлом в каталоге word/media/.ДвоичныеДанные или Картинка.Посмотрим на пример кода распаковки и получения файлов изображений из документа:
ПутьКФайлуDocx = "C:\Temp\Document.docx";
КаталогРаспаковки = КаталогВременныхФайлов() + "DocxUnpack_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
// Создаем каталог для распаковки
СоздатьКаталог(КаталогРаспаковки);
// Распаковываем DOCX как архив
Архив = Новый ЧтениеZipФайла(ПутьКФайлуDocx);
Архив.ИзвлечьВсе(КаталогРаспаковки, РежимВосстановленияПутейФайловZIP.Восстанавливать);
Архив.Закрыть();
// Все графические файлы документа находятся в папке word/media/
КаталогМедиа = КаталогРаспаковки + "\word\media\";
МассивФайлов = НайтиФайлы(КаталогМедиа, "*.*");
Для Каждого ФайлКартинки Из МассивФайлов Цикл
// Загружаем картинку в двоичные данные или объект Картинка 1С
ДвоичныеДанныеКартинки = Новый ДвоичныеДанные(ФайлКартинки.ПолноеИмя);
ОбъектКартинка = Новый Картинка(ДвоичныеДанныеКартинки);
// Выполняем дальнейшую обработку полученного объекта
КонецЦикла;
// Очищаем временный каталог после завершения работы
УдалитьФайлы(КаталогРаспаковки);
Если документ имеет формат .doc (Word 97-2003) или требуется однозначно сопоставить конкретную ячейку таблицы и находящуюся в ней картинку без разбора XML-дерева, используем экспорт фрагмента через веб-формат.
Рассмотрим подробнее логику работы:
COMОбъект("Word.Application").wdFormatFilteredHTML (код формата 10). При таком сохранении Word автоматически выгружает графические элементы ячейки в отдельную папку рядом с HTML-файлом.Посмотрим на пример реализации данного метода:
WordApp = Новый COMОбъект("Word.Application");
WordApp.Visible = Ложь;
Попытка
Документ = WordApp.Documents.Open("C:\Temp\Document.doc");
// Получаем нужную ячейку таблицы: Таблица 2, Строка 3, Колонка 2
Ячейка = Документ.Tables.Item(2).Cell(3, 2);
// Проверяем наличие встроенных фигур в ячейке
Если Ячейка.Range.InlineShapes.Count > 0 Тогда
Ячейка.Range.Copy();
// Создаем временный документ для выгрузки
ВременныйДок = WordApp.Documents.Add();
ВременныйДок.Range().Paste();
ПутьКHTML = КаталогВременныхФайлов() + "temp_cell.html";
ПапкаИзображений = КаталогВременныхФайлов() + "temp_cell_files";
// wdFormatFilteredHTML = 10
ВременныйДок.SaveAs2(ПутьКHTML, 10);
ВременныйДок.Close(0); // 0 = wdDoNotSaveChanges
// Считываем извлеченное изображение из созданной подпапки
НайденныеКартинки = НайтиФайлы(ПапкаИзображений, "*.*");
Если НайденныеКартинки.Количество() > 0 Тогда
ДвоичныеДанныеКартинки = Новый ДвоичныеДанные(НайденныеКартинки[0].ПолноеИмя);
КонецЕсли;
// Удаляем временные файлы выгрузки
УдалитьФайлы(ПутьКHTML);
УдалитьФайлы(ПапкаИзображений);
КонецЕсли;
Документ.Close(0);
Исключение
WordApp.Quit(0);
ВызватьИсключение;
КонецПопытки;
WordApp.Quit(0);
Подведем итоги выбора метода в зависимости от архитектуры вашей базы:
.doc.