天天看点

开源Word读写组件DocX 的深入研究和问题总结

     当理解word实质上是xml以后,就不难了解如何操作word了。理论上说,你不需要任何工具就能对它进行操作,当然复杂性极高。微软推出了open xml sdk, 专门帮助.net语言与office实现互操作,这也成了com组件外的新选择,但它的安装包有100m, 对很多部署来说,难度不小。

    这个组件docx本身实际上是对xml操作的封装库,如果你有兴趣看它的源代码,基本核心就是xml的字符串组装和拼接,添加一个图表的本质就是在对应xml标签下面再增加一个图表的子文档。

    看到字符串拼接,有经验的同学肯定站出来会问性能如何。它没有使用stringbuilder,但本身性能不差,我生成100页的图文并茂的word文档也是瞬间的事情,所以,没有关系。

     对程序开发来说,最常见的需求便是自动生成文档,完全从0生成图文并茂,排版合理的文档对程序员来说不现实,代码多得海了去了。所以很多人的做法是字符串替换,通过替换特定文字来操作,但这样显然是相当不专业的。

    比较合理的做法,是office里面的“域”。域的本质,对程序员来说就是表达式,这个变量可以是文档字数,文档页数(这是office里面自带的属性)。域相当牛逼,甚至可以连接到一个数据库,一个按钮,乃至一篇网页上去,真心无所不能。

     同样你也可以自己添加属性,也就是所谓“自定义属性”。

    如何查看文档中的所有自定义域呢?

    在word最上面的“插入”卷展栏下选择文档部件->域,如下图所示,并在域控制框中左侧选择docproperty,即可看到所有的属性:

开源Word读写组件DocX 的深入研究和问题总结

  怎么在文档中插入一个自定义域呢?一种做法是,随便在上图中选择一个域(比如author),点击确定,就会在插入的位置生成一个域。 然后点击右键,选择‘切换域代码’,即可改变里面的域定义:

开源Word读写组件DocX 的深入研究和问题总结
开源Word读写组件DocX 的深入研究和问题总结

  修改author,变成你想要的属性,就可以了,把这个东西拷到别的地方,再修改下域代码,就是一个新的域定义了。这些域定义,可以被我们用程序操作来替换。

  由于域实质上是表达式,所以涉及一个计算过程。可以选择打印时自动更新,或者ctrl+a全选,然后f9,就可全部更新所有域表达式。

    但是,在实际开发中,有个致命的问题: 当你通过模板,为自定义属性赋值,生成新文档后,打开新文档这些域并没有自动更新,这是非常麻烦的,因为客户可不想打开文档后发现那些核心数据都是奇怪的东西,让他们去摁f9自动更新域更是不可能。但要命的是,有些域被更新了,有些域没有更新,从域定义上来看,没有任何区别,这到底是怎么回事? 如果有大神解决了这个问题,请不吝赐教!

   说到这里,有一个良好排版的模板,加上自动替换的功能,文档生成应该差不多了吧?不,还要插入图表和图片,这些用域暂时还不好解决。

   插入图片的问题,关键是插入位置,你需要找到要插入的位置所在的段落(paragraph).我的做法是,用linq查询,通过定位关键字的做法找到段落,然后插入之即可。虽然粗糙,但还能用。插入表格类似。

   但,怎么插入图表?所谓图表,就是柱状图饼状图等等的东西?虽然官方示例里有生成图表的功能,但我用word2013怎么都打不开: “该文档有问题”。百思不得其解,花了半天才在别人的2010上打开,大喊坑爹(因此,docx对office2013的兼容性不够!)

   那好吧,我们用word2010或者07总可以了吧?但目前版本的源代码,只能往文档的最后添加图表,因为只有一个这样的函数:

开源Word读写组件DocX 的深入研究和问题总结

这不是坑爹呢么?另外有时候插入图表或图片会出错,显示xml错误,建立连接的id重复! 更是坑爹。

开源Word读写组件DocX 的深入研究和问题总结

在这个地方会抛异常。

经过分析,是上面那个生成relationshipid的函数出错了, 后来,索性改了这个函数的方法,直接从guid生成,这样就不会错了,代码如下。

 至于只能在文档最后添加图表的问题,我做了以下的代码修改:

和源代码对比,很容易就能看出两者的区别。

我能添加更多的图表吗?当然可以。源代码只内置了三种图表:pie, line和bar,不能满足要求,既然充分理解了它的原理,不妨我们扩展它吧:

    用了这个组件,感受良多,这哥们和我一样的在校学生,,但已经做了这样的开源项目,下载量超过18000+。 虽然理论不一定多牛逼,但确实满足广大人民群众需要了,400kb的dll文件,直接解决了.net平台word生成这一刚性需求。  但作者确实下了功夫,大量的xml转换和分析,纯粹的体力活啊!

   1. 对office2013的支持不够

   2. api远没达到完善,例如无法良好的操作图表类型,只能使用默认值。

   3. 代码欠重构,可获得更好的程序风格和性能的提升。

   4. 域更新不正常

  如果这几个问题能解决,那确实是最好不过的了。除此之外,其实还有很多小问题,一方面期待作者解决,另外一方面如果项目需求紧急的话,索性我们自己先改了得了。代码还是很容易理解的。

  我尝试把它用在项目中,经过测试,发现基本稳定,大家可以尝试采纳。

  有任何问题,欢迎随时交流,如果您觉得对您有帮助,请点推荐,谢谢!