VBA/VBScript提取Word(*.doc)文件中包含的圖片(照片)
要處理的人事簡歷表是典型的Word文檔,其中一人一份doc,里面包含有個人的照片,如果要把里面的照片復制出來就比較麻煩了,一般手動的做法是選擇文件另存為,保存類型選擇“網頁(*.htm; *.html)”,這樣就會另存為網頁形式,同時會有個以文件名開頭,以.files結尾的文件夾,點擊進去就可以看到Word里面嵌入的所有資源,包含所需要的圖片資源。
值得注意的是該文件夾里同一張圖片正常會有兩個副本,其中一張圖片文件體積較大,另一張圖片文件體積較小,顯而易見較小體積的文件是Word自動創建的縮略圖,在絕大多數情況下我們可能僅僅需要原始的插入圖片,那么選擇較大體積的圖片文件即可,好在我要處理的人事簡歷表只有員工的一張照片,那么另存為網頁后的文件夾也僅僅只有兩張圖片,一張原始圖片,一張縮略圖,這兩張圖片可以通過大小區分。
到這里大家可能對提取Word里面的圖片有了大概的思路,如果文件比較少,那么剛才手動另存的方法是可以接受的,但是我所要處理的人事簡歷表就有好幾百份,一份一份手動處理肯定耗時耗力,所以本文接下來將要簡單介紹如何編程處理這項任務。
首先對於大批Word文件來襲,第一件事情就是要枚舉每份文件,VBScript枚舉文件的方式有很多,我就不一一介紹了,感興趣的可以參考我這篇文章。這里有個注意點就是僅僅篩選擴展名為*.doc
或者*.docx
的文件,可以通過FileSystemObject
組件的GetExtensionName
獲取,還有一個需要注意的地方就是Word會生成以~$
開頭的隱藏文件,偏偏這個文件也是doc擴展名結尾的,但該文件不是可用的Word文件,所以也要排除~$
打頭的文件類型。
下一步要明確將該Word文檔另存為網頁時保存的位置,因為我們主要是提取Word里插入的圖片,另存文件這一部分不需要向用戶展示,所以我們可以借助臨時目錄和臨時文件來存儲。
獲取臨時目錄和文件名的方法如下:
Set fso = WSH.CreateObject("Scripting.FileSystemObject") strTempDir = fso.GetSpecialFolder(2) ' 臨時目錄路徑 strTempFileName = fso.GetTempName() ' 臨時文件名 ' 另存為HTML網頁的文件路徑 strTempHTMLFileName = fso.BuildPath(strTempDir, strTempFileName & ".html" ) ' 對應的網頁資源文件夾路徑 strTempHTMLDirName = fso.BuildPath(strTempDir, strTempFileName & ".files" ) Set fso = Nothing |
然后使用SaveAs對目標Word文件進行另存操作,其中另存類型為wdFormatHTML,這是個常量,具體如下所示,表示不同的保存類型選項。
Const wdFormatDocument = 0 Const wdFormatDocument97 = 0 Const wdFormatDocumentDefault = 16 Const wdFormatDOSText = 4 Const wdFormatDOSTextLineBreaks = 5 Const wdFormatEncodedText = 7 Const wdFormatFilteredHTML = 10 Const wdFormatFlatXML = 19 Const wdFormatFlatXMLMacroEnabled = 20 Const wdFormatFlatXMLTemplate = 21 Const wdFormatFlatXMLTemplateMacroEnabled = 22 Const wdFormatHTML = 8 Const wdFormatPDF = 17 Const wdFormatRTF = 6 Const wdFormatTemplate = 1 Const wdFormatTemplate97 = 1 Const wdFormatText = 2 Const wdFormatTextLineBreaks = 3 Const wdFormatUnicodeText = 7 Const wdFormatWebArchive = 9 Const wdFormatXML = 11 Const wdFormatXMLDocument = 12 Const wdFormatXMLDocumentMacroEnabled = 13 Const wdFormatXMLTemplate = 14 Const wdFormatXMLTemplateMacroEnabled = 15 Const wdFormatXPS = 18 Const wdFormatOfficeDocumentTemplate = 23 Const wdFormatMediaWiki = 24 |
對於上述類型,本文不做詳細敘述,詳情可以參考MSDN相關文檔,關於另存的VBScript代碼如下所示。
Set objWordApp = WSH.CreateObject("Word.Application") objWordApp.Visible = True ' 打開目標Word文件 Set objDoc = objWordApp.Documents.Open(strFileName) ' 另存為HTML文件 objDoc.SaveAs strTempHTMLFileName, wdFormatHTML objDoc.Close Set objDoc = Nothing objWordApp.Quit Set objWordApp = Nothing |
另存成功后,我們就可以通過變量strTempHTMLDirName
定位到導出的資源文件夾,找到所需要的圖片即可。這里需要再次用到文件枚舉,實際上每次導出,Word會很貼心的生成一個XML的文件列表,叫做filelist.xml
,所有導出的文件該列表均有記錄,如下所示:
<xml xmlns:o="urn:schemas-microsoft-com:office:office"> <o:MainFile HRef="../rad1378A.tmp.html"/> <o:File HRef="image001.jpg"/> <o:File HRef="image002.jpg"/> <o:File HRef="header.html"/> <o:File HRef="filelist.xml"/> </xml> |
另外由於是XML格式的,所以可以通過解析這個文件完成對所有導出資源的處理,得到所需要的圖片文件路徑,獲得所對應圖片文件大小,取最大存儲體積的圖片為最終所需要的圖片,相關代碼如下所示:
Function GetRealImageFileName(fso, strBaseDir) Dim i, objXml, objNode, objChildNode Dim strFileListFile, strExtension, strFileName strFileListFile = fso.BuildPath(strBaseDir, "filelist.xml") Set objXml = WSH.CreateObject("Microsoft.XMLDOM") objXml.validateOnParse = True objXml.Load strFileListFile objXml.Async = False Set objNode = objXml.documentElement Dim f, strFileName2, strFinalImageFileName, fFinalImageFileSize fFinalImageFileSize = 0 strFinalImageFileName = "" For i = 0 To objNode.childNodes.Length - 1 Set objChildNode = objNode.childNodes.Item(i) If objChildNode.tagName = "o:File" Then strFileName = objChildNode.attributes.getNamedItem("HRef").text strExtension = UCase(fso.GetExtensionName(strFileName)) If strExtension = "JPG" Or strExtension = "JPEG" Or _ strExtension = "GIF" Or strExtension = "BMP" Or _ strExtension = "PNG" Then strFileName2 = fso.BuildPath(strBaseDir, strFileName) Set f = fso.GetFile(strFileName2) If fFinalImageFileSize < f.Size Then fFinalImageFileSize = f.Size strFinalImageFileName = strFileName2 End If Set f = Nothing End If End If Set objChildNode = Nothing Next Set objNode = Nothing Set objXml = Nothing GetRealImageFileName = strFinalImageFileName End Function |
最后將該圖片復制出來即可,這里直接判斷最大存儲體積的圖片為所需要的原始圖片是基於每張簡歷表僅插入一張照片為前提的。
另外別忘了進行掃尾工作,刪除另存的網頁文件和關聯資源文件夾,當然由於是臨時目錄,使用臨時文件清理工具也可以完成此項工作,如果我們代碼完美一些,可以編程實現自動刪除。
' 刪除網頁文件 fso.DeleteFile strTempHTMLFileName ' 刪除網頁文件對應資源文件夾里所有文件 fso.DeleteFile fso.BuildPath(strTempHTMLDirName, "*"), True ' 刪除網頁文件對應資源文件夾里所有目錄 fso.DeleteFolder fso.BuildPath(strTempHTMLDirName, "*"), True ' 刪除網頁文件對應資源文件夾 fso.DeleteFolder strTempHTMLDirName, True |