В данной статье хочу показать 4 способа как экспортировать (сохранить) все изображения из Word документа в файлы в указанную папку на диске с помощью макроса VBA. Обращаю внимание, что речь идет про сохранение не авто-фигур и т.п., а импортированных изображений, которые входят в ворде в коллекцию InlineShapes объекты которой и будем сохранять.
Способ 1. Сохранение изображений из Word в формате EMF
Это самый короткий и быстрый способ экспортировать все изображения из Word-а. Формат изображений EMF (Microsoft Enhanced Metafile) - это медиа-формат, который Microsoft придумал на замену формату WMF. Однако, этот формат не всем приложениям понятен, в этом и минус этого способа.
ExportImages "C:\Мои документы\file.doc", "C:\Export" Sub ExportImages(DocFile As String, ExportPath As String) ' Открываем документ Set Wrd = CreateObject("Word.Application") Set Doc = Wrd.Documents.Open(DocFile) ' Цикл по картинкам в документе For i = 1 To Doc.InlineShapes.Count FileName = ExportPath & "\img" & CStr(i) & ".emf" SaveInlineShape FileName, Doc.InlineShapes(i) Next i ' Закрываем документ Doc.Close Wrd.Quit False End Sub Sub SaveInlineShape(FileName As Variant, iShape As InlineShape) Dim vData() As Byte ' Открываем файл для записи Open FileName For Binary Access Write As #1 ' Записываем данные vData = iShape.Range.EnhMetaFileBits Put #1, 1, vData ' Закрываем файл Close #1 End Sub
Способ 2. Распаковка Word файла как архива
Суть идеи в том, что если файл в формате docx, то он будет представлять собой архив, который содержит множество файлов, в т.ч. и папку с изображениями, которые есть в нем. На случай, если файл не в формате docx, макрос открывает его и пересохраняет в формат docx и потом распаковывает его во временную папку.
ExportImages "C:\Мои документы\file.doc", "C:\Export" Sub ExportImages(DocFile As String, ExportPath As String) ' Создаем временную папку TmpPath = ExportPath & "\tmp" Set FSO = CreateObject("Scripting.FileSystemObject") If Not FSO.FolderExists(TmpPath) Then FSO.CreateFolder (TmpPath) ' Открываем документ и пересохраняем во временную папку в формате docx (на случай если он был какого-то другого формата) DocXFile = TmpPath & "\1.docx" Set Wrd = CreateObject("Word.Application") Set Doc = Wrd.Documents.Open(DocFile) Doc.SaveAs FileName:=DocXFile, FileFormat:=wdFormatXMLDocument Doc.Close: Wrd.Quit False ' Переименовываем файл в zip ZipFile = TmpPath & "\1.zip" Name DocXFile As ZipFile ' Распаковываем файлы Set objShell = CreateObject("Shell.Application") Set FilesInZip = objShell.NameSpace(ZipFile).items objShell.NameSpace(TmpPath).CopyHere (FilesInZip) ' Получаем список картинок, которые теперь находятся в \word\media Set sFolder = FSO.GetFolder(TmpPath & "\word\media") For Each FileItem In sFolder.Files FileCopy FileItem.Path, ExportPath & "\" & FileItem.Name Next FileItem ' Удаляем временную папку и всё ее содержимое Shell "cmd /c rd /S/Q """ & TmpPath & """" End Sub
Способ 3. Сохранение файла в HTML
Принцип похож на 2-й способ. При сохранении в html формат создается папка, содержащая картинки и другие вложенные файлы и всё, что нужно, это взять из нее изображения. Минус в том, что изображения выгружаются по несколько раз в разных форматах.
ExportImages "C:\Мои документы\file.doc", "C:\Export" Sub ExportImages(DocFile As String, ExportPath As String) ' Создаем временную папку TmpPath = ExportPath & "\tmp" Set FSO = CreateObject("Scripting.FileSystemObject") If Not FSO.FolderExists(TmpPath) Then FSO.CreateFolder (TmpPath) ' Открываем файл и пересохраняем во временную папку в формате HTML Set Wrd = CreateObject("Word.Application") Set Doc = Wrd.Documents.Open(DocFile) Doc.SaveAs TmpPath & "\tmp.html", FileFormat:=wdFormatHTML Doc.Close: Wrd.Quit False ' Получаем список файлов в папке с вложениями tmp.files Set sFolder = FSO.GetFolder(TmpPath & "\tmp.files") For Each FileItem In sFolder.Files If FSO.GetExtensionName(FileItem.Name) = "jpg" Or _ FSO.GetExtensionName(FileItem.Name) = "gif" Or _ FSO.GetExtensionName(FileItem.Name) = "png" Then ' Копируем только картинки FileCopy FileItem.Path, ExportPath & "\" & FileItem.Name End If Next FileItem ' Удаляем временную папку и всё ее содержимое Shell "cmd /c rd /S/Q """ & TmpPath & """" End Sub
Способ 4. Экспорт изображений в формате BMP с использованием буфера обмена
Суть этого метода в том, чтобы скопировать картинку в буфер обмена и затем, используя API функции сохранить из буфера картинку в файл. Одно из преимуществ этого метода в том, что можно сохранить только одну конкретную картинку из Word документа, а не все подряд.
Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long Private Declare Function CloseClipboard Lib "user32" () As Long Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long Const CF_BITMAP = 2 Const IMAGE_BITMAP = 0 Const LR_COPYRETURNORG = &H4 Private Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(0 To 7) As Byte End Type Private Type uPicDesc Size As Long Type As Long hPic As Long hPal As Long End Type ExportImages "C:\Мои документы\file.doc", "C:\Export" Sub ExportImages(DocFile As String, ExportPath As String) ' Открываем документ Set Wrd = CreateObject("Word.Application") Set Doc = Wrd.Documents.Open(DocFile) ' Цикл по картинкам в документе For i = 1 To Doc.InlineShapes.Count Doc.InlineShapes(i).Range.CopyAsPicture Clip2File ExportPath & "\" & CStr(i) & ".bmp" Next i ' Закрываем документ Doc.Close Wrd.Quit False End Sub ' Процедуры для работы с буфером обмена Public Function Clip2File(OutputPath As String) Dim strOutputPath As String, oPic As IPictureDisp Set oPic = GetClipPicture() If Not oPic Is Nothing Then SavePicture oPic, OutputPath Clip2File = OutputPath Else Clip2File = "" MsgBox "Unable to retrieve bitmap from clipboard" End If End Function Private Function GetClipPicture() As IPicture Dim h As Long, hPicAvail As Long, hPtr As Long, hPal As Long, hCopy As Long hPicAvail = IsClipboardFormatAvailable(CF_BITMAP) If hPicAvail <> 0 Then h = OpenClipboard(0&) If h > 0 Then hPtr = GetClipboardData(CF_BITMAP) hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG) h = CloseClipboard If hPtr <> 0 Then Set GetClipPicture = CreatePicture(hCopy, 0, CF_BITMAP) End If End If End Function Private Function CreatePicture(ByVal hPic As Long, ByVal hPal As Long, ByVal lPicType) As IPicture Dim r As Long, uPicInfo As uPicDesc, IID_IDispatch As GUID, _ IPic As IPicture Const PICTYPE_BITMAP = 1 With IID_IDispatch .Data1 = &H7BF80980 .Data2 = &HBF32 .Data3 = &H101A .Data4(0) = &H8B .Data4(1) = &HBB .Data4(2) = &H0 .Data4(3) = &HAA .Data4(4) = &H0 .Data4(5) = &H30 .Data4(6) = &HC .Data4(7) = &HAB End With With uPicInfo .Size = Len(uPicInfo) .Type = PICTYPE_BITMAP .hPic = hPic .hPal = 0 End With r = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, IPic) Set CreatePicture = IPic End Function
У каждого из способов экспорта картинок есть свои плюсы и минусы. Самые быстрые в плане производительности скорее всего 1-й и 4-й способы. У 3-го способа есть плюс - сохраняет в файлы не только вставленные картинки, но так же и автофигуры, диаграммы и т.д. Какой из способов удобнее всего для вас - решайте сами.
Комментарии к статье:
Добавить комментарий: