Как программно извлечь изображение из документа Word в 1С?

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

При интеграции 1С с офисными пакетами часто возникает задача автоматического чтения данных из файлов Microsoft Word. Если текстовые данные из ячеек таблиц извлекаются стандартным обращением через свойство Range().Text, то с графическими объектами разработчики сталкиваются со сложностями. В объектной модели Microsoft Word у объектов InlineShape и Shape отсутствует встроенный прямой метод сохранения графических данных в файл на диске.

Проанализируем специфику размещения графики в документе и разберем два надежных способа программного получения изображений средствами 1С.

Особенности хранения графики в Word

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

  1. Тип обтекания объекта: если изображение вставлено в режиме «В тексте», оно входит в коллекцию InlineShapes диапазона ячейки. Если же картинка плавающая (с обтеканием текстом, за текстом или перед текстом), она попадает в коллекцию Shapes или ShapeRange.
  2. Ограничения COM-соединения: работа с объектом Word.Application на стороне сервера 1С требует наличия установленного пакета Microsoft Office, корректной настройки DCOM и не поддерживается на серверах под управлением Linux.

Способ 1. Извлечение изображений из формата DOCX через ZIP-архив (Рекомендуемый способ)

Файлы формата .docx представляют собой стандартные архивы OpenXML. Все внедренные медиафайлы хранятся в несжатом или сжатом виде внутри структуры архива в каталоге word/media/. Это позволяет извлекать изображения штатными средствами платформы 1С без вызова сторонних программ и без установки Microsoft Word.

Разберем по шагам алгоритм извлечения:

  1. Распаковываем .docx во временный каталог с помощью объекта ЧтениеZipФайла.
  2. Считываем связи из файла word/_rels/document.xml.rels и структуру документа word/document.xml, сопоставляя ячейку таблицы с идентификатором rId и файлом в каталоге word/media/.
  3. Загружаем полученный файл в объект ДвоичныеДанные или Картинка.

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


ПутьКФайлуDocx = "C:\Temp\Document.docx";
КаталогРаспаковки = КаталогВременныхФайлов() + "DocxUnpack_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");

// Создаем каталог для распаковки
СоздатьКаталог(КаталогРаспаковки);

// Распаковываем DOCX как архив
Архив = Новый ЧтениеZipФайла(ПутьКФайлуDocx);
Архив.ИзвлечьВсе(КаталогРаспаковки, РежимВосстановленияПутейФайловZIP.Восстанавливать);
Архив.Закрыть();

// Все графические файлы документа находятся в папке word/media/
КаталогМедиа = КаталогРаспаковки + "\word\media\";
МассивФайлов = НайтиФайлы(КаталогМедиа, "*.*");

Для Каждого ФайлКартинки Из МассивФайлов Цикл
    // Загружаем картинку в двоичные данные или объект Картинка 1С
    ДвоичныеДанныеКартинки = Новый ДвоичныеДанные(ФайлКартинки.ПолноеИмя);
    ОбъектКартинка = Новый Картинка(ДвоичныеДанныеКартинки);
    
    // Выполняем дальнейшую обработку полученного объекта
КонецЦикла;

// Очищаем временный каталог после завершения работы
УдалитьФайлы(КаталогРаспаковки);

Способ 2. Экспорт ячейки через промежуточный HTML средствами Word (COM)

Если документ имеет формат .doc (Word 97-2003) или требуется однозначно сопоставить конкретную ячейку таблицы и находящуюся в ней картинку без разбора XML-дерева, используем экспорт фрагмента через веб-формат.

Рассмотрим подробнее логику работы:

  1. Подключаемся к приложению через COMОбъект("Word.Application").
  2. Копируем содержимое нужной ячейки таблицы в буфер Word.
  3. Создаем пустой временный документ и вставляем туда фрагмент.
  4. Сохраняем временный документ с форматом 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);

Сравнение и выбор оптимального решения

Подведем итоги выбора метода в зависимости от архитектуры вашей базы:

  1. Разбор DOCX как архива: оптимален для высоконагруженных серверных систем, баз на Linux и регламентных заданий. Метод работает максимально быстро и не создает зависимостей от стороннего ПО.
  2. Экспорт через HTML (COM): подходит для клиентских рабочих мест под управлением Windows при обработке устаревших файлов .doc.
← На главную