现状:项目使用Jacob组件对word加水印,xdocreport进行数据的加载和pdf的转换。
问题:目前由于word数量越来越大,而大部分word都有几页纸是相同的,所以每次修改都需要遍历大部分的word,这种设计显然不利于项目的维护。
解决思路:考虑将相同的几页纸抽取出来,在转PDF的时候,将这些内容插入到指定的位置即可,以后要修改这几页纸的内容,则只需要修改一次即可。
技术难点:如何将相同的几页纸插入到指定的位置?
采用技术:在网上搜索后得知,最灵活的莫过于Jacob,而且项目已经使用此技术进行添加水印,因此,决定采用此技术。
Jacob关于Jacob的使用,网上到处都有,比如下面几个网址:
http://danadler.com/jacob/ 当然少不了官方网址
http://wv1124.iteye.com/blog/582921 该网址中的介绍和示例,基本已经满足大部分需求
http://wv19831124.blog.163.com/blog/static/59950007200811585819650/ 此文章同上面的大致一样,但是在文章后面提到了我后面要讲的VBA
http://www.360doc.com/content/11/0130/19/3947093_90007570.shtml 大神之作,在这个文章里面,我终于突破了困扰的问题
以上就是比较典型的Jacob的介绍和操作示例等,里面比较重要的就是VBA了,这个东西我最初苦苦寻找,但是未果,后来在我说的“大神之作”的末尾终于找到答案了。读过上面的几篇文章,基本就会知道有VBA这个东西,而且Jacob都是通过VBA在操作word,所以解决了VBA,基本Jacob就得心应手了,而如果对VBA不太了解的话,是很难寻找到线索去突破VBA的,在大神之作的末尾,提到了“录制宏”,对,就是录制宏,根据网上的资料,打开Word的开发者工具,点击“Visual Basic”,然后按下F1,即可得到Jacob操作的东西。帮助里面所有的对象在jacob中都是Dispatch,Documents是,Document也是,Content也是……而对于每个对象都会有属性和方法,OK,调用属性,使用Dispatch.get,调用方法使用Dispatch.call,懂了吧,这就是那些示例代码里面写的。
比如下图就是我截取的Document对象:
比如想关闭文档,则调用Dispatch.call(doc2, "Close", new Variant(true));
其中的"Close"就是上图中的最后一行的方法名称,而最后没的参数,则可以点击该方法进去,即可知道。
至此,jacob即可被掌握,至于我上述遇到的问题,解决方法如下:
public void copyOrgInfo2TargetWord(String orgPath, String targetPath) { ActiveXComponent wrdCom = getInstance(); Dispatch documents = wrdCom.getProperty("Documents").toDispatch(); // documents表示word的所有文档窗口,(word是多文档应用程序) Dispatch doc = Dispatch.call(documents, "Open", orgPath).toDispatch(); Dispatch content = Dispatch.get(doc, "Content").toDispatch(); Dispatch.call(content, "Copy"); Dispatch doc2 = Dispatch.call(documents, "Open", targetPath).toDispatch(); Dispatch threepage = Dispatch.call(doc2, "GoTo", new Object[] { new Variant(1), new Variant(1), new Variant(3) }).toDispatch(); Dispatch.call(threepage, "Paste"); Dispatch.call(doc2, "Close", new Variant(true)); }
orgPath为相同的那几页纸,targetPath为目标word,"GoTo", new Object[] { new Variant(1), new Variant(1), new Variant(3) }为定位到第3页。