VS2005的C#使用WORD COM组件
VS2005的C#使用WORD COM组件
2008/06/05 16:48 [技术文章 ]运行环境:Windows Server 2003,Visual Studio.NET 2005,Office 2007
原理介绍:
我们都知道,Office是基于COM组件技术开发的,属于非托管程序,然而C#使用的都是托管程序,那么如何使用非托管的COM组件就是我们操作 WORD的第一个问题。所幸的是,.NET FRAMEWORK提供了一种不同种类类库的转换工具tlbimp,exe,通过这个转换工具,我们可以把COM组件转化为.NET FRAMEWORK可以直接调用的DLL文件。
实现说明:
接下来就是转化工作了,Office组件都可以在C:Program FilesMicrosoft Office目录下找到,当然安装的Office版本不同,子目录是不一样的。笔者使用的是Office 2007,可以在C:Program FilesMicrosoft OfficeOffice12目录下找到MSWORD.OLB,这个是WORD组件的类库文件,还可以找到MSACC.OLB操作 ACCESS,MSPPT.OLB操作PPT,XL5CHS32.OLB操作EXCEL。载入不同的组件就可以完成对不同Office组件的操作。使用 tlbimp,exe工具转化MSWORD.OLB文件后可以得到三个DLL文件,Office,dll,Visual BasicIDE.dll,Word.dll。最后在编译文件的时候,记得将这三个DLL文件载入,命令如下:
csc /r:system.dll /r:system.windows.forms.dll /r:system.drawing.dll /r:office.dll /r:vbide.dll /r:word.dll word.cs
笔者使用Visual Studio.NET 2005编译环境,通过IDE提供的功能可以大大简化我们对组件转化的工作,并且在编译时也不需要输入那么繁杂的语句,非常方便了。下面介绍一下IDE载入Office组件的方式。
在菜单栏选择“项目”-“添加引用”,弹出的窗口中我们可以选择“COM”选项卡,找到Microsoft Office 12.0 Object Library(Office 2003/2007需要使用12.0版的,如果你使用的是Office 2000或者更低的版本,只要载入10.0版的就可以了),确定后引入.也可以在“浏览”选项卡下找到我们上面提到的MSWORD.OLB文件,引入即 可。引入后我们可以发现在解决方案中,引用目录下多了三个文件 Microsoft.Office.Core,Microsoft.Office.Interop.Word,VSIDE。这说明引用文件成功,之后在编 译程序的时候,在Debug目录下会生成两个DLL文 件,Interop.Microsoft.Office.Core.dll,Interop.Microsoft.Office.Interop.Word.dll。 完成组件的引入,下面就可以开始程序设计了。
先看一下Word对像模型
Application :用来表现WORD应用程序,包含其它所有对象。他的成员经常应用于整个WORD,你可以用它的属性和方法控制WORD环境。
Document :Document对象是WORD编程的核心。当你打开一个已有的文档或创建一个新的文档时,就创建了一个新的Document对象, 新创建的Document将会被添加到Word Documents Collection。
Selection :Selection对象是描述当前选中的区域。若选择区域为空,则认为是当前光标处。
Rang :是Document的连续部分,根据起始字符和结束字符定义位置。
Bookmark:类似于Rang,但Bookmark可以有名字并在保存Document时Bookmark也被保存。
在编程中使用到的代码如下,注释比较详细,这里就不再具体的说明。
//Word程序对象
private Microsoft.Office.Interop.Word.Application WordApp = new Microsoft.Office.Interop.Word.Application();
//Word文档对象
private Microsoft.Office.Interop.Word._Document aDoc;
private void openfile_Click(object sender, EventArgs e)
{//打开Word文件
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
//定义打开文件的16个参数
object fileName = openFileDialog.FileName; //文件名称
object ConfirmConversions = false; //允许转换
object ReadOnly = false; //只读方式打开
object AddToRecentFiles = false; //添加到最近打开的文档
object PasswordDocument = System.Type.Missing;
object PasswordTemplate = System.Type.Missing;
object Revert = System.Type.Missing;
object WritePasswordDocument = System.Type.Missing;
object WritePasswordTemplate = System.Type.Missing;
object Format = System.Type.Missing; //格式
object Encoding = System.Type.Missing; //编码
object Visible = System.Type.Missing;
object OpenAndRepair = System.Type.Missing;
object DocumentDirection = System.Type.Missing;
object NoEncodingDialog = System.Type.Missing;
object XMLTransform = System.Type.Missing;
WordApp.Visible = true;
try
{
//打开文档
aDoc = WordApp.Documents.Open(ref fileName, ref ConfirmConversions, ref ReadOnly, ref AddToRecentFiles,
ref PasswordDocument, ref PasswordTemplate, ref Revert, ref WritePasswordDocument, ref WritePasswordTemplate,
ref Format, ref Encoding, ref Visible, ref OpenAndRepair, ref DocumentDirection, ref NoEncodingDialog, ref XMLTransform);
//激活文档,使文档为当前处理
aDoc.Activate();
}
catch
{
MessageBox.Show("出现错误!");
}
}
}
private void closefile_Click(object sender, EventArgs e)
{//关闭Word文件
object SaveChanges = false; //保存更改
object OriginalFormat = System.Type.Missing;
object RouteDocument = System.Type.Missing;
//关闭文档
aDoc.Close(ref SaveChanges, ref OriginalFormat, ref RouteDocument);
//退出程序
WordApp.Quit(ref SaveChanges, ref OriginalFormat, ref RouteDocument); }
通过文档类对象aDoc还可以完成文件的保存,另存为等等操作,详细的可以参阅MSDN。
.Net调用Office Com组件的原理及问题
今日用到WordToHtml的方法,需要添加对office组件的引用(Microsoft.Office.Interop.Word)
程序集Microsoft.Office.Interop.Word
D:\Program Files\Microsoft Visual Studio 9.0\Visual Studio Tools for Office\PIA\Office12\Microsoft.Office.Interop.Word.dll
调用代码如下
using Microsoft.Office.Interop.Word;
ApplicationClass word = new ApplicationClass();
Type wordType = word.GetType();
Documents docs = word.Documents;
//打开文件
Type docsType = docs.GetType();
Document doc = (Document)docsType.InvokeMember("Open",
System.Reflection.BindingFlags.InvokeMethod, null, docs, new Object[] { wordFilePath, true, true });
//转换格式,另存为
Type docType = doc.GetType();
docType.InvokeMember("SaveAs", System.Reflection.BindingFlags.InvokeMethod,
null, doc, new object[] { htmlFileUrl, WdSaveFormat.wdFormatFilteredHTML });
docType.InvokeMember("Close", System.Reflection.BindingFlags.InvokeMethod,
null, doc, null);
//退出 Word
wordType.InvokeMember("Quit", System.Reflection.BindingFlags.InvokeMethod,
null, word, null);
原理显而易见:通过程序启动Word.exe程序,将本地文件打开,做另存为html操作,关闭word文档,退出word程序
程序执行完成后存在两个文件,原有word文件和html文件
本地调试没有任何问题,Windows2003+Vs2008+IIS6.0+Office2007
发布网站,在本机IIS上配置好网站后(读取写入的权限都打钩),登陆上传word文件转换出错,错误异常消息如下:
检索 COM 类工厂中 CLSID 为{00024500-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005。
从网上搜帖子答案大致相同:登陆网站的用户没有操作word.exe的权限
好,运行"中输入dcomcnfg.exe启动"组件服务",也可以从管理工具里面进,
"组件服务"- >"计算机"- >"我的电脑"- >"DCOM配置"->找到word->属性->"标识"标签,选择"交互式用户"
->安全"标签"->在"启动和激活权限"上点击"自定义",然后点击对应的"编辑"按钮,在弹出的"安全性"对话框中填加 一个"NETWORK SERVICE"用户(注意要选择本计算机名),并给它赋予"本地启动"和"本地激活"权限.
->"安全"标签,在"访问权限"上点击"自定义",然后点击"编辑",在弹出的"安全性"对话框中也填加一个"NETWORK SERVICE"用户,然后赋予"本地访问"权限. 这样,我们便配置好了相应的Excel的DCOM权限.
重启本地机器上的IIS,未重启机器,打开网站测试,OK了,顺便提一下,操作的word文件和html文件夹要有读写的权限才行,右键--安全--Everyone或网络服务用户-->读写权限打钩
接下来,发布到服务器上,外网登陆测试,抛黄页,提示运行时错误 由于不是本地机器的登录用户所以不提示具体的错误信息。
得,从服务器的IIS里面浏览测试,抛出与我机器上同样的错误,吼吼太好了,这下我可以练练手配置一下Dcom权限了,打开组件服务傻眼了
服务器上Windows2008+IIS7.0,在Dcom配置里面没有找到word,看看安装了Office没有,结果是安装了,Office2007,再搜搜帖子windows2008 的,
找了几个帖子无果,看到了xp的组件服务配置,跟winserver2008的差不多,就这个吧
"组件服务"- >"计算机"- >"我的电脑"- >属性-->Com组件->启动和激活权限设置同上->访问权限编辑同上->都添加了Network service用户给用户赋予相应的读写权限
重启IIS了,盼望着盼望着,测试仍然是相同的错误 ,重启服务器,the same result! 我靠
难道用户添加错了吗?难道是AspNet用户吗,可是帖子上说window2000操作系统是这个用户,IIS5.0是添加这个用户,可是服务器上是windows2008+iis7.0 ,哎,试试吧
继续修改重启,仍然无果
网上仍然有招:尽管我还没有试,先贴上再说
在web.config中使用身份模拟,在<system.web>节中加入 <identity impersonate="true" userName="你的用户名" password="密码"/></system.web>
我一直在想,为什么在服务器上DCom配置里面,没有找到Office word 以及Office家族,是不是安装的Vs2008是框架版的没有自动注册Office的一系列组件呢
研究了一些com组件的注册和office的注册,理解了为什么之前说 *.dll(动态类库)和*.exe 都是可执行文件了,网上也有解决的办法是Excel的,贴出来:
注册方法执行 开始----运行----输入excel2003的安装路径,例如 "C:\Program Files\Microsoft Office\OFFICE11\excel.exe" /regserver 注意/符号前面有一个空格,其中"C:\Program Files\Microsoft Office\OFFICE11\excel.exe" 是excel2003的安装程序的路径,参数regserver表示注册的意思!
运行后,会启动Office 2003的安装程序,进行修复,重新注册。
excel2007为默认的启动程序的方法类同,可以执行 开始----运行----"D:\Program Files\Microsoft Office\Office12\excel.exe" /regserver
综上所述,再遇到Excel导出、导入问题时,先考虑权限问题,再考虑office的版本环境!如此基本能够解决这些问题了。
Good!Tomorrow I will have a try!
<--顺便贴出某个帖子的 楼主经验:我也遇到过应用以上方法还是报错的情况,我的环境是windows2003 + office2003+office2007,在测试服务器上都可以导出无任何问题!但是更新了正式环境就是报错,权限都设置了还是报错,因为我的测试服 务器是默认office启动的,所以我怀疑是office版本环境问题!于是我卸载了office2007,马上测试ok了,但是重启服务器后就产生了 have not been Pre-compiled错误,导出页面都无法打开了,于是我又重新安装了office2007,页面可以打开了,但是导出excel时又开始报错!我又 把所有的权限重新设置一遍,问题依旧!后来发现两个服务器默认打开excel的程序不一样,测试环境是默认office2003打开,正式环境是 office2007打开,于是我在正式环境重新注册office2003,使其同样也是默认office2003打开程序,靠!问题终于解决了---->