有些時候,我們需要對大量的 word 文檔進行相同的操作,我們肯定不會願意花上一整天進行這些重複的勞動。所有純文本文件(如.c, .txt, .tex, .py, .xml等)都能使用任意一種高級程式語言進行批量處理,但不幸的是,doc 類(.doc, .docx, .dot等)的文件並不是簡單的純文本文件(.doc文件為 Office 專用格式,.docx為 OpenXML 格式),因此,我們無法直接使用高級程式語言處理 doc 類文件(但仍然可以處理,如 python 使用python-docx模塊)。
但是,MS Office Word 內置的宏(VBA)為我們進行批處理提供了一種簡易的渠道(事實上,MS Office 套件都有相應的宏功能)。
VBA,Visual Basic for Application,是用來擴展應用程式功能的宏語言,MS Office VBA 具備了面向對象程式語言應有的特徵。在本文中,我們將簡要介紹其在批處理中的應用。
Word 宏簡介首先引入面向對象編程中的兩個概念:類和對象。
類是現實世界或思維世界中的實體在計算機中的反映(表現為一段代碼)。對象是具有類類型的變量(表現為一個具體的東西)。類是抽象的,對象是具體的。
舉例來說,我們打開一個名為Doc1.docx的文檔,那麼,這個打開的文檔就是一個Document對象(具體的),而在 Word 中,就有一個抽象的描述這個文檔的類(抽象的):
class Document
properties '描述一個Document的所有屬性
methods '描述一個Document具有的方法
events '描述一個Document具有的事件這個名為Document的類中,有眾多屬性,類的屬性被賦予一定的值(實例化),就成為了一個對象。如,Doc1.docx文檔的所有段落,就是這個文檔的Paragraphs屬性;文檔中的所有表格,就是它的Tables屬性;文檔的名字,就是它的Name屬性,等等。這些屬性也可以是對象。
了解了這些概念,我們就可以開始用 VBA 來操作 Word 文檔了。
一般情況下,宏的編輯是隱藏的,用戶可以在:文件>選項>自定義功能區 的右側將「開發工具」勾上,就可以在菜單欄中看到它了。
用宏操作文檔在這一部分及下一部分,我們假定讀者有一定的編程基礎,沒有編程基礎的讀者也不必退出,下面的內容沒有引入更多的概念。
我們在 Word 的任何操作,都可以使用宏來完成,並且,宏可以實現一些常規操作無法實現的內容。
在批處理中,比較常見的是設置文檔的格式。我們嘗試使用宏來修改段落的樣式。
我們先錄製一個宏,看看我們的一個操作到底設置了些什麼吧。
在開發工具菜單中,單擊 Visual Basic,我們可以看到編輯器中有如下代碼:
Sub 宏1()
'
' 宏1 宏
'
'
Selection.Style = ActiveDocument.Styles("標題")
End Sub這說明我們剛剛設置樣式的操作可以編寫上述宏來完成。它的含義是將我們選擇的文本的樣式設置為當前文檔的樣式列表中的「標題」。
編寫如下代碼:
Sub 設置標題()
Selection.Style = wdStyleTitle
End Sub並運行之,看看效果是不是和剛才的操作一致呢!wdStyleTitle這個枚舉變量值就是「標題」這個樣式。具體可以參考WdBuildinStyle 枚舉[1]。
上述代碼的含義應該十分明顯:把Selection對象的Style屬性設置為wdStyleTitle。
但是,上面這一步驟仍然有局限性,因為我們必須手動選擇要改動的文字,才能使用這個宏。但在批處理的時候我們肯定不能去選擇文字,我們動手的地方應該越少越好。
在Document對象中有一個Paragraphs屬性,改屬性是文檔中所有段落的集合,我們剛才的操作相當於是把第一段的樣式設置為wdStyleTitle,因此,編寫以下宏:
Sub 設置標題2()
ActiveDocument.Paragraphs(1).Style = wdStyleTitle
End Sub運行一下,可以看到,我們並沒有選擇任何文本,但是它同樣達到了剛才的效果!
解釋一下上述宏:ActiveDocument的全稱是Application.ActiveDocument,它表示當前的Document對象,然後,獲取Document對象的Paragraphs屬性,我們給了它一個參數1,這樣它返回一個Paragraph對象,然後將它的樣式設置為wdStyleTitle。
我們並不滿足於 Word 內置的樣式。以下代碼將設置一個新的樣式:
Sub 創建樣式()
ActiveDocument.Styles.Add "樣式1", wdStyleTypeParagraph
With ActiveDocument.Styles("樣式1")
With .Font
.Bold = True
.Size = 30
.ColorIndex = wdAuto
.NameFarEast = "黑體"
.NameAscii = "Times New Roman"
End With
With .ParagraphFormat
.Alignment = wdAlignParagraphCenter
End With
End With
End Sub運行之,在樣式列表中可以看到多出一個「樣式 1」,這就是我們剛才設置的樣式。第 2 行,我們創建了一個新的樣式,名為「樣式 1」,它的樣式類型為wdStyleTypeParagraph(段落),第 3-14 行,修改樣式的字體和段落格式。我們想把第一段的樣式設置為這個新的樣式,該怎麼寫呢?讀者可以先想想,用到的知識都是上面講過的。讀者也可以錄製宏試試看。
Sub 設置樣式()
ActiveDocument.Paragraphs(1).Style = ActiveDocument.Styles("樣式1")
End Sub它的思路是:把當前文檔的第一段的樣式設置為當前文檔樣式列表中的「樣式 1」。
我們想要把文檔中所有內容的樣式全都設置為「樣式 1」該怎麼辦呢。
一種方法是全選,再將選擇的內容的樣式設置為「樣式 1」:
Sub 設置所有段落樣式()
Selection.WholeStory
Selection.Style = ActiveDocument.Styles("樣式1")
End SubWholeStory方法將Selection擴選至整個文章。至於第 3 行,讀者已經十分熟悉了。
第二種方法是,循環遍歷文章的所有段落,將這些段落的樣式全都設為「樣式 1」。
Sub 設置所有段落樣式2()
Dim para As Paragraph '定義para為段落對象
'For Each ... In ... Next 語句將遍歷Paragraphs中所有Paragraph對象
For Each para In ActiveDocument.Paragraphs
para.Style = ActiveDocument.Styles("樣式1")
Next
End Sub這兩種方法都能實現相同的效果。
但是,這兩種方法都有一個問題:如果我們的文章中有圖表,那麼表格中的文字和圖片的樣式也將變成「樣式 1」。我們顯然不希望出現這種情況。
我們只要在para.Style = ActiveDocument.Styles("樣式1")前加上一個判斷語句
If Not para.Range.Information(wdWithInTable) Then
para.Style = ActiveDocument.Styles("樣式1")
End If這樣,表格內文字的樣式就不是「樣式 1」了。
批處理一個批處理程序應該要能調用其它宏。直接在這個批處理程序中調用這個宏即可:
Sub 批處理()
...某些功能...
宏1 '調用 宏1
End Sub
Sub 宏1()
...宏1的功能...
End Sub一個批處理程序大致的功能應該有:
首先創建一個文件選取器:
Sub 批處理()
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
End Sub運行之,我們能看到它創建了一個文件選取器對話框,我們能選擇一個或多個文件,但選擇之後似乎什麼也沒發生。這是因為我們沒有編寫相應的功能。
接下來我們把所選的文件的路徑全都展示出來:
Sub 批處理()
Dim fd As FileDialog
Dim selected As Variant
Dim selitem As String
selitem = ""
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
If .Show = -1 Then
For Each selected In .SelectedItems
selitem = selitem & selected & vbCr
Next
End If
MsgBox "選擇了以下文件:" & vbCr & selitem
End With
End Sub再次運行這個宏,選擇幾個文件,我們發現它將所有文件的路徑全都輸出到屏幕上了。
我們的目的並不是輸出文件名。我們嘗試將選擇的 doc 類文件的第一段的樣式設置為「樣式 1」。
Sub 批處理()
Dim fd As FileDialog
Dim dcm As Document
Dim selected As Variant
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
If .Show = -1 Then
For Each selected In .SelectedItems
Set dcm = Documents.Open(selected) '打開文檔
dcm.Activate '將文檔設置為當前文檔
設置樣式 '注意不要加括號
dcm.Close (wdSaveChanges) '關閉並保存更改
Next
End If
End With
End Sub
Sub 設置樣式()
ActiveDocument.Paragraphs(1).Style = ActiveDocument.Styles("樣式1")
End Sub運行,發現出現一個錯誤:提示不存在「樣式 1」。這是因為在其它文檔中並不一定有「樣式 1」這個樣式。因此我們需要先創建樣式:
...
For Each selected In .SelectedItems
Set dcm = Documents.Open(selected)
dcm.Activate
創建樣式
設置樣式
dcm.Close (wdSaveChanges)
Next
...
Sub 創建樣式()
ActiveDocument.Styles.Add "樣式1", wdStyleTypeParagraph
With ActiveDocument.Styles("樣式1")
With .Font
.Bold = True
.Size = 30
.ColorIndex = wdAuto
.NameFarEast = "黑體"
.NameAscii = "Times New Roman"
End With
With .ParagraphFormat
.Alignment = wdAlignParagraphCenter
End With
End With
End Sub批處理有可能會出現誤操作,因此我們不能在原文檔上更改,這時可以將原文檔另存為,再在這個文檔上更改。並且,我們希望在所有文件修改完之後,有相應的提示信息。最終的成果如下:
Sub 批處理()
Dim fd As FileDialog
Dim dcm As Document
Dim selected As Variant
Dim changedpath As String
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.Filters.Add "Word文檔", "*.doc; *.docx; *.docm", 1
If .Show = -1 Then
MkDir("+changed") '創建修改後的文件的存放位置
changedpath = "+changed"
For Each selected In .SelectedItems
Set dcm = Documents.Open(selected) '打開文檔
dcm.SaveAs2 (changedpath & "\" & dcm.Name) '把文件另存到+changed文件夾中
dcm.Activate '將文檔設置為當前文檔
創建樣式 '注意不要加括號
設置樣式
dcm.Close (wdSaveChanges) '關閉並保存更改
Next
MsgBox "已修改" & .SelectedItems.Count & "個文件,修改的文件保存在" _
& changedpath & "文件夾中"
Else
MsgBox "沒有選擇文件"
End If
End With
End Sub
Sub 設置樣式()
ActiveDocument.Paragraphs(1).Style = ActiveDocument.Styles("樣式1")
End Sub
Sub 創建樣式()
ActiveDocument.Styles.Add "樣式1", wdStyleTypeParagraph
With ActiveDocument.Styles("樣式1")
With .Font
.Bold = True
.Size = 30
.ColorIndex = wdAuto
.NameFarEast = "黑體"
.NameAscii = "Times New Roman"
End With
With .ParagraphFormat
.Alignment = wdAlignParagraphCenter
End With
End With
End Sub本文簡要地講解了用 Word 宏的一點內容,更加詳細的說明可以參考MS Office Word VBA[2],這是微軟官方的說明文檔,其中詳細介紹了 Word VBA 的所有內容,有興趣的讀者可以進行學習。
參考資料[1]WdBuildinStyle枚舉: https://docs.microsoft.com/office/vba/api/word.wdbuiltinstyle
[2]MS Office Word VBA: https://docs.microsoft.com/office/vba/api/overview/word