纯C语言集成Excel遇到的问题及解决
Kagula
2010-12-30
简介
对在VisualStudio2008+SP1环境下纯C语言调用Excel12(Excel2007)功能实现过程中碰到的问题做下简单总结。
正文
参考[1]和参考[3]的编程思路用纯C语言调用Excel2007( OLE对象)。
第一步:我们要利用OLE Viewer、MIDL工具得到Excel对象接口的C语言头文件及源文件。
[S1-1]Visual Studio2008中自带Windows SDK,我这里用到了6.0A版本的Win SDK,启动[你的Win SDK安装目录]/Microsoft SDKs/Windows/v6.0A/bin/OleView.Exe
打开Type Libraries中的Microsoft Excel 12.0 Object Library,在新出现的窗口中你可以看到IDL语言源文件内容把它复制拷贝出来(注意不要使用Toolbar中的Save按钮来保存文件,用该方式保存的文件是GBK编码很难编辑和使用)。我这里把这个文件命令为excel.idl
[S1-2]使用快捷菜单“Microsoft Visual Studio 2008/Visual Studio Tools/Visual Studio 2008 Command Prompt”,在新弹出的窗口中使用MIDL excel.idl命令,当然会弹出大量的错误。因为很多类型的定义依赖于mso.idl。
在你系统的Program Files目录下的Common Files/Microsoft Shared目录中搜索mso.dll利用OLE Viewer工具得到mso.idl。
[S1-3]把缺少的类型定义复制到excel.idl文件中。注意这里有些定义没找到不是不存在,而是被放到了文件尾部,这里建议你使用前向引用,特别是coclass的定义,你不能移动它原来的位置否则MIDL为报MIDL9008号错误。
[S1-4]修改excel.idl直到midl excel.idl不在出现error,这时使用midl /h excel12.h excel.idl命令,我们就得到了excel12.h excel12_i.c excel12.tlb文件。
第二步:现在我们要利用生成的代码实现对Excel OLE对象的操作
[S2-1]引入excel12.h文件后报出大量的错误,修改代码直到没有error。对象的定义如果没找到,可以用IDispatch类型代替。在idl源文件dispinterface的定义只会引出IDispatch接口,dispinterface对象中的其它method需要使用Invoke的方式调用。或者使用QueryInterface方式得到它的interface对象,这样就可以使用“宏方式”操作这个对象。
注意源文件头部可能需要加上下面两行代码,第一行表示COM采用C接口,第二行表示COM对象采用宏调用
#define CINTERFACE
#define COBJMACROS
QueryInterface方式调用在Pure C中有两种方式
第一种如下:
HRESULT hr = IUnknown_QueryInterface_Proxy(COM对象指针,&要查询的COM对象的IID,&查询得到的COM对象指针);
hr = IUnknown_Release_Proxy(要释放的COM对象指针);
在文件头加上下面这段代码
#pragma comment(lib, "rpcrt4.lib")
否则你会找不到这两个函数的实现。如果调用成功hr的值为S_OK
第二种方式:
COM对象->lpVtbl->QueryInterface(COM对象,&要查询的COM对象的IID,&查询得到的COM对象指针);
第二种方式只适合从interface中引出的COM对象,这类对象支持VTBL(虚函数列表)。
在这种方式下你也可以直接使用“宏方式”,示例代码如下
IRange_QueryInterface(COM对象,&要查询的COM对象的IID,&查询得到的COM对象指针);
其中上面的IRange是COM对象的类型名称。
[S2-2]对COM对象方法的调用
参考[2]手动对COM对象(IDispatch接口)操作
先使用GetIDsOfNames方法再使用Invoke。这里需要注意入口参数的设置。不需要入口参数直接可以使用下面这个变量传入
DISPPARAMS disp_params = {NULL,NULL,0,0};
如果需要传入一个字符串变量,参考下面的这段代码
VARIANT vBSTR;
vBSTR.vt = VT_BSTR;
vBSTR.bstrVal = SysAllocString(L"这是第一行第一列");
DISPPARAMS disp_params = {NULL,NULL,0,0};
DISPID dispidNamed = DISPID_PROPERTYPUT;
disp_params.cArgs = 1;
disp_params.rgvarg = &vBSTR;
disp_params.cNamedArgs = 1;
disp_params.rgdispidNamedArgs = &dispidNamed;
字符串类型的变量用好后记得使用下面的语句释放
SysFreeString(vBSTR.bstrVal);
如果需要传入两个字符串变量,参考下面的这段代码
VARIANT vRanges[2]
disp_params.cArgs = 2;
disp_params.rgvarg = vRanges;
参考
[1]用C语言调用COM组件(ADO)
http://www.rupeng.com/forum/thread-16350-1-1.html
[2] Excel writing and reading with pure c API
http://blog.youkuaiyun.com/fanchuan0077/archive/2009/09/14/4552117.aspx
[3] 用C实现Excel的OLE自动化
http://hi.baidu.com/mettlesome/blog/item/d655ea173cd98809c83d6ddf.html
本文介绍如何在Visual Studio 2008环境下使用纯C语言调用Excel 2007的功能,包括获取Excel对象接口文件、处理COM对象操作及解决常见错误。
10万+

被折叠的 条评论
为什么被折叠?



