最近在做一个BS项目的时候要求生成一个word文档供用户下载,因为原先的项目中也曾涉及过类似的东西,是通过winform调用office的命名空间,直接调用office的程序,打开文档,修改,保存关闭文档。但是在原来开发对应实用程序时就存在问题:
1.用户必须安装Office否则无法使用,这个是不友好的
2.用户安装不同的Office版本也会出现兼容性问题
3.即使调用Quit函数有时也无法关闭Office进程,内存无法回收。如果杀掉进程的话可能导致用户正在使用的其他的word文档丢失,这也是不友好的。
4.小概率会出现文档访问权限异常。
现如今将整套系统搬上服务器的话,虽然说原先的前两个问题都不存在了,但却出现了更加严重的问题:
1. 原先的第三个问题变得更为可怕,如果客户端的话多一个word的进程也就罢了,重启的时候会自动关闭,但是服务器的话用的人多一点内存马上就会爆掉
2. 并发问题是最严重的一个问题,测试条件下服务器只允许一个处理过程在运行,一旦出现并发,后来的请求就会出现错误。
3. 使用IIS的话,IIS本身的权限并没有这么高,启动Office的话必须经过一套复杂的权限设置
鉴于以上问题,我便放弃了调用实用程序,尝试通过读写doc文档的方式。再查阅大量相关文章后发现OPI的一套开源的东西是专门用于操作xls和doc的并且OPI在.net下有对应的封装NOPI,可继续查阅大量相关材料后我得到的仅是一句:“word部分的关键开发人员离开”。
并且在最新版本的dll里我没有见到doc操作的任何东西。相反xls操作的东西倒是很多,而且用起来方便无比。如果有需要的朋友倒是可以参考一下。
当我在官方文档看到:“任何曾花费时间编写额外代码来让Office桌面应用在服务器上可靠运行的人都会告诉你,那绝对不是理想的解决方案。因为在Word和Excel之类的Office桌面应用程序设计初衷从来不是使其在服务器上运行,每当需要人工干预的复杂对话时,就需要一个自定义实用程序来终止并重新启动他们”
于是乎我放弃了doc的生成转战docx,虽然docx是Office2007才用上的新鲜玩意,但是如果用户正常开启更新的话2003也是支持docx的,而且docx在WPS上的支持也是不错的。而且docx可以使用微软官方的Open XML 直接进行操作。
下面进入正题,Open XML与Docx的操作。
首先关于准备工作,网上有些文章说要下载SDK和工具包,关于工具包是必须下载的里面包含着DLL,至于SDK就随意了,初学者的话会有所帮助。
http://www.microsoft.com/en-us/download/details.aspx?id=5124
在引用中添加WindowsBase,DocumentFormat.OpenXML命名空间,安装工具后再引用界面右上角搜索就能找到。
将上面的两个命名空间using到代码中,当然对应着你操作不同的文档可能需要引入OpenXML下的不同的命名空间,以下以操作word为例所以我需要将DocumentFormat.OpenXml.Wordprocessing这个命名空间也引入进来,下面才会有word的标准文档对象。
关于word文档的具体操作,如果用过HtmlAgilityPack的朋友一定会非常快的上手,因为它的结构跟OpenXML文档的结构非常的相似,将整个文档看作一个节点,节点下包含着很多的小节点,最小的节点是text节点。通过添加或者删改节点可以达到操作文档的目的。
下面我来演示一下如何打开一个文档并添加一句话
using System; using System.Collections.Generic; using System.Linq; using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using System.Text; using System.Text.RegularExpressions; using System.Diagnostics; using HtmlAgilityPack; using System.IO; namespace Sample { static void AddText() { //path是你需要打开的文档全路径 using (WordprocessingDocument doc = WordprocessingDocument.Open(path, true)) { AppendText(doc,“Your Text Here!”); } } public static void AppendText(WordprocessingDocument _doc, string _txt) { //每一个 Paragraph 节点都会成为word文档中单独的一行 Paragraph p = new Paragraph(); // Find the first run in the paragraph. Run r = new Run(); // Set the text for the run. Text t = new Text(); t.Text = _txt; r.Append(t); p.Append(r); _doc.MainDocumentPart.Document.Body.Append(p); _doc.MainDocumentPart.Document.Save(); } }
类似于这样每执行一次AppendText方法都会在新的一行添加一句话!