最近的項目中有一個功能點為:根據分析數據庫並生成報告。不過不是大數據、數據挖掘之類,報告的內容、組織方式都是事先固定下來的。實現的方式為,在普通word文檔中插入書簽制成模板,然后程序使用OpenXML解析文檔,找到書簽,並根據書簽的意義進行相應的計算,最后用計算結果替換書簽,替換的內容涉及到文本、圖表、表格等。
這一套已經可以穩定工作,但美中不足的是關於目錄的問題,太長的文檔開始有必要存在目錄,但在模板中簽入真實數據后,最后文檔的篇幅每次都是不一樣的,這就需要目錄能都自動更新,但不知道OpenXML怎么實現(大俠遇到過的話懇請告知),最后找到了其它辦法。
第一種是使用宏。在模板中設置好標題並插入目錄,然后在VBA編輯器中,雙擊This Document,添加如下代碼:
Sub AutoOpen()
Dim aStory As Range
Dim aField As Field
For Each aStory In ActiveDocument.StoryRanges
For Each aField In aStory.Fields
aField.Update
Next aField
Next aStory
End Sub
目錄屬於域的一種,上面的代碼大致意思是要求word在每次打開該文檔時都遍歷並更新每一個域,這樣就把目錄自動更新了。但這個方法在word禁用了宏時便會失效。
第二種是手工修改word背后的XML文件,這個方法是看老外的一個視頻學的,鏈接:http://ericwhite.com/blog/screen-cast-exploring-tables-of-contents-in-open-xml-wordprocessingml-documents/。不得不佩服,查找別的帖子的時候看到過視頻作者的發言,這個Eric White之前也受困於這個問題,得到啟示后把問題順利解決,此外還做了這份非常細致的視頻。
要編輯所謂的“word背后的XML文件”,我的方法是把word后綴從"docx"改為“zip”,然后解壓,記事本打開。Eric White的方法應該是用了OpenXML相關的插件,用vs可以直接打開word對應的xml文件並編輯,這個非常方便,可是我不會用唉。
可以打開xml文件后,先修改settings.xml,在末尾加上一句 <w:updateFields w:val="true"/>,注意xml文件的層次。
還要修改document.xml文件,找到目錄所在的部分,不好找可以搜索w:fldChar,fldChar就是跟域相關的標簽,模板中的每條目錄都被包圍在w:hyperlink標簽之中,找到這些並刪除,最終目錄部分只留下這樣的:
留意紅框中的內容,最終相當於去掉了具體的目錄信息,只保留了目錄的框架。xml必須有閉標簽,刪除的時候留意別刪錯了,比如我當時的情況就是不小心把這個p標簽刪了。
改好后,保存,重新壓縮,將后綴改回“docx”便OK了。
第一次打開會有詢問是否更新域,選是。
以上便是這兩種方法。各有優劣,對比一下
方法一(宏) | 方法二(修改XML) | |
失效 | word禁用宏便會失效 | 不會失效 |
更新 | 每次打開自動更新 | 只在第一次更新 |
樣式 | 可以設置目錄的字體字號 | 不能修改目錄樣式 |
可以看到兩種方法都不完美,應該還有更好的辦法吧,請多指教。