昨天,一个朋友说上司给安排了一个任务。任务是这么描述的:公司有一个文档(doc),该文档里面有很多部分,每部分都有唯一章节号。对于不同的开发人员可能只需要这个文档的某一章节或者某几个章节。如果人员不多的话,可以手工拷贝,形成一个新文档进行发布交付给相关人员。但如果人员众多,这种工作十分耗时,且易出差错。希望通过编程的方式,为每位员工分配好章节之后,自动生成符合需求的新文档。
因为一直都在做java的开发,所以第一反应就是找类似POI的库来解决问题。且解决类似问题都需要解析文档,而后根据分配情况重新组合形成新文档,输出这些步骤。但去POI主页上一看对word的支持还停留在word97的简单读写水平上,估计也能满足需求,不过没敢尝试。倒是后来突发奇想,觉得VBA肯定能解决这类问题,毕竟微软的东西向来都保密,鬼知道word2003是什么存储格式,JAVA来尝试解析它的文档,困难重重。但VBA就不一样了,通过宏的方式驾驭office的众多形式文档,自是游刃有余。所以尝试看了个大概,随手写了一点儿功能实现。
通过Document,Selection, Range以及Find对象以及相关方法基本上可以解决问题。解决的思路大概如下:
使用Find配合Range来确定一共有多少个章节以及每一章节的Range。而后通过一些窗体界面获取相关的组合方式,比如需要第几章第几章。有了组合方式接下来就是把相应的Range中的文本进行拷贝,保存至新文档。
随手写的功能是统计一共有多少个章节,这个使用Find就可以解决。代码片如下:
Selection.WholeStory
With Selection.Find
.ClearFormatting
.Text = "(第)?(章)"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchByte = True
.CorrectHangulEndings = False
.MatchWildcards = True
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
If Not Selection.Find.Found() Then
MsgBox "nothing found"
Exit Sub
End If
While Selection.Find.Found()
counter = counter + 1
Selection.Find.Execute
Wend
里面觉得好玩的地方是将.MatchWildcards设为True,而后通过.Text = "(第)?(章)"来设置要匹配的字符串,"(第)?(章)"中的问号表示一个字符,通过它可以匹配到"第一章"、"第二章"...
其它的选项都可以在word vba手册里面找到相应的含义。通过循环就可以进行所有的匹配,最终通过一个累加器counter计数共有多少个匹配,即有多少个章节。等周末没事儿了,把剩下的逻辑实现。
通过google关键字vba发现,有jjhou的《word排版艺术》以及其它很接近用户应用层面的实用技术,通过VBA,可以做很多重复型的劳动。想一劳永逸,得认真学学了。。。