返回首页


{S0}简介
这段代码演示了如何访问Excel电子表格使用C,COM和ATL使用Visual Studio。NET 2003(V7.1)。背景
我一个老同学的C程序员,我的工作,周围用C旋转。虽然我不反对使用新的方法,如C#(和其他咨询演出的事实),我总是喜欢到C回来。
第一的原因,我需要摆在首位访问的Excel。
我公司是Windows 2000和XP开发一个产品,需要获得其字符串翻译。的权力,已经决定,我们将提供给我们的翻译文件将Excel文件,每个项目之一。一切都很好。
但是我懒,我不喜欢由专人维护散落翻译字符串电子表格。我宁愿写一个程序中提取的字符串(驻留在XML文件),塞进他们的Excel电子表格。好了,第一部分是很容易的。只需使用得心应手花花公子IXMLDOMDocument COM接口。这块蛋糕。
然后,我开始探索如何通过C访问Excel编程。
哦... ...我... ...上帝!缺乏关于这一问题的文件,不只是轻薄。这是可笑不存在的。有一个有关如何使用MFC做(不要尝试,除非你喜欢在几分钟的过程中产生一个亿的小模块,而欢快的MFC导入向导生成Excel的许多接口IDispatch的代码包装的很少很少的文章)。但我被遗弃的MFC不久前在ATL和WTL的祭坛崇拜,再也没有回头。
经过几个小时的搜索,我设法找到各种接口各种版本的Excel中谈到的一个环节。因为我安装了Office 2003,我去那一个。 (它存储的方式,在实际EXCEL.EXE二进制)。
"太棒了!"我对自己说。只需添加一个#import行stdafx.h和我所做的一切。的#import"C:\ \ PROGRAM FILES \ \微软Office \ \ OFFICE11 \ \ EXCEL.EXEquot;
是啊,没错。男孩,我感到失望。你得到丢失,重复,一式三份,googleplicate错误消息,警告,诅咒和一般吠叫从编译器和/或连接器的行为。卷起衣袖,准备搏斗的时间,包括文件和#import指令。
我首先注意到的是,很多失踪阶级"MSO"前缀。 Hmmmm ...不知道这是否意味着微软Office?果然,它出现的Office产品都需要相同的Mso.dll执行他们的工作很多。所以添加英寸#进口quot; C:\ \ PROGRAM FILES \ \共同文件\ \微软共享\ \ OFFICE11 \ \ MSO.DLLquot;的#import"C:\ \ PROGRAM FILES \ \微软Office \ \ OFFICE11 \ \ EXCEL.EXEquot;
好了,帮助了很多。但它仍然吠叫有关"定义",没有足够的参数。似乎很多的属性,方法名等,在Microsoft Office碰撞标准C / C#定义声明。幸运的是,超过在微软的Visual Studio hierophants预期,并提供了一​​个机制,解决#import指令,即"重命名"选项。这似乎也该办公室是深深在床上用Visual Basic,因为你需要,#进口。
毕竟说和做的,我终于到C程序中,包括Excel的COM接口神奇的炼金公式。 #进口"C:\ \ Program Files文件\ \ Common Files文件\ \微软共享\ \ OFFICE11 \ \ MSO.DLLquot; \ 重命名("; RGBquot","MSORGBquot;)使用命名空间的办公室;的#import"C:\ \ PROGRAM FILES \ \共同文件\ \微软共享\ \ VBA \ \ VBA6 \ \ VBE6EXT.OLBquot;使用命名空间VBIDE; #进口"C:\ \ PROGRAM FILES \ \微软Office \ \ OFFICE11 \ \ EXCEL.EXEquot; \ 重命名("; DialogBoxquot","ExcelDialogBoxquot;)\ 重命名("; RGBquot","ExcelRGBquot;)\ 重命名("; CopyFilequot","ExcelCopyFilequot;)\ 重命名("; ReplaceTextquot","ExcelReplaceTextquot;)
瞧!
我试图越来越花哨,包括了"使用命名空间的Excel"以及,但编译器开始咆哮的噪音,同时刨着地面,我决定辞职,而我是提前。我可以输入几个"Excel中::"前缀,以保持社会的事情。使用代码
应用程序是一个简单的基于WTL的对话框的小程序。该对话框包含在报告模式单一的列表视图控件。它的编制与Unicode,所以我不担心杂乱的MBCS字符串。所有的代码与Excel的接口是在OnLoad()方法被调用,当用户按下"载入..."按钮。
此方法不执行的第一件事是NUKE在列表控制的项目。 m_list.DeleteAllItems();而(m_list.DeleteColumn(0));
然后它会提示用户选择使用WTL的类CFileDialog的Excel文件。的方式,WTL的,如果你不完全,熟悉它,是一个真正的准系统包装周围的Win32 API(除少数例外)。案例分析。 CFileDialog的需要一个指向一个空终止字符串,定义过滤器,以帮助用户文件选择过程。这是一个痛苦的定义上的飞有点所以我写了一个简单的类,它与竖线的单个字符串是空终止的占位符(|)。它有一个操作符LPCTSTR()方法返回与他们的空终止更换竖线到一个字符串缓冲区的指针。
我给你AFileFilter类。类AFileFilter{市民: AFileFilter(LPCTSTR pszFilter):  0; m_strFilter(pszFilter) m_pszFilter(空) { m_pszFilter = m_strFilter.GetBuffer(0); LPTSTR PSZ = m_pszFilter; (* PSZ) &# 160; { LPTSTR pszNext =::CharNext(PSZ); 如果(* PSZ == _T ('|')) &# 160;* PSZ = _T('\ 0'); &# 160;PSZ = pszNext; } &# 160;回报; } 虚拟〜AFileFilter() { m_strFilter.ReleaseBuffer();  ; 回报; }市民: 运营商LPCTSTR()const的 { 返回(m_pszFilter); }保护: CString的m_strFilter; LPTSTR m_pszFilter;};
现在肉的方法。首先,我们需要一个Excel应用程序的指针。 ,如果你在调试器中运行这,你会发现有夫妇的第二个暂停时,通过此代码跟踪Excel是由COM加载。我认为这是一个好兆头,我第一次调试的程序:我其实是调用Excel中! (我总是一步我第一次运行一个程序在调试器中通过新的代码行,不要你呢?)的Excel:_ApplicationPtr pApplication;(失败(pApplication.CreateInstance(_T("; Excel.Applicationquo​​t";)))){ Errorf(_T("无法初始化的Excel::_Application quot;)); &# 160;回报;
Errorf()方法,使我能够快速格式化与用户飞可选参数的信息。
接下来,我们要在Excel中打开。xls文件。这是通过工作簿属性和它的Open()方法。 varOption _variant_t((长)DISP_E_PARAMNOTFOUND VT_ERROR);Excel中:_WorkbookPtr pBook;pBook = pApplication - GT;工作簿- GT公开赛(dlgFile.m_szFileName   ; varOption,varOption,varOption,varOption &# 160; varOption,varOption,varOption,varOption   ; varOption,varOption,varOption,varOption);
如果你离开了,即使这些varOption参数之一,它不会工作。哎呀,我想我知道他们都做了什么。
接下来,我的工作簿中的第一张工作表的指针。当然,第一张工作表的索引是1而不是0。 (记住:办公室在床上的Visual Basic在11mps MPEG BitTorrent的。)Excel中:_WorksheetPtr pSheet = pBook - GT;表- GT;项目[1];
唷!最后,我们就可以开始通过电子表格数据的筛选。我可以计算出漂亮的附近,这是所有通过Range对象。现在的Range对象,如果在脚本语言,如C#或Visual Basic中使用的是一个大胆的,俏皮的接口和强大的方法美妙的事情。在C中,它的争论与宙斯像,而他的指法他主持。
使用它的基本方法,我发现,只是供大于求范围。然后我用一个黑客通过扫描空细胞作为结束的列或行结束标记。我敢肯定,有更优雅的方式,使用这个对象在C,我仔细地离开学生的练习。
我做的第一件事是获取第一行,我假设是标题行,界定所有的列名。 Excel中:RangePtr pRange = pSheet - GT; GetRange(_bstr_t(_T("; A1quot";)),_bstr_t(_T("; Z1quot";)));
代码扫描通过Range对象的项目运营商,此行。我去的第一单元格的内容填充到一个_variant_t,然后进入一个_bstr_t的两个步骤的过程,因为我懒,不想检查的_variant_t类型。 _variant_t vItem = pRange - GT;项目[1] [iColumn];_bstr_t bstrText(vItem);
bstrText轮番上涨空当,它的时间停止添加列。
然后我疯狂与精神错乱,并创建了一个Range对象的一个​​实例humdinger。 pRange = pSheet - GT; GetRange(_bstr_t(_T("; A2quot";)) _bstr_t(_T("; Z16384quot";)));
我用一个简单的嵌套循环在列表视图控件创建的行和列设置数据。
最后,我关闭与VARIANT_FALSE书,以防止任何意外的变化。xls文件蠕变。 pBook - GT;关闭(VARIANT_FALSE);
最后,我退出Excel应用程序。这是一个重要的步骤,因为如果你忽视这样做时,Excel将悬空在内存中,更糟糕的是,它会保持你打​​开上面的文件的锁。 Yeck! pApplication - GT;退出();
这是很多!玩得开心!兴趣点
哦,是的。如果你要修改的电子表格中的数据呢?好了,原来是很简单。只需使用Item属性为左操作数。 bstrText _bstr_t(_T("有些文字quot;!));_variant_t vItem(bstrText); pRange - GT;项目[5] [1] = vItem;
保持C类火灾的燃烧。他们需要我们。他们总是需要我们。历史
第一次修订。

回答

评论会员:会员7875568 时间:2011/12/07
我想使用Excel的COM接口来访问Excel在C的。我用cygwin的(而不是微软的Visual Studio)。我试图导入的Mso.dll和其他的代码,并获得了一堆错误。有没有人尝试在Cygwin
?huibenpaodechong
评论会员:所以greate 时间:2011/12/07
murrine
评论会员:游客 时间:2011/12/07
这与任何版本的Excel工作?前97,2000
查尔斯宋
评论会员:游客 时间:2011/12/07
感谢您的代码。我的彩票软件,这使得数字自动基于过去几个星期前选择号码。imgsrc=http://www.orcode.com/upimg/2011_12_07_02_50_31_1.gif如此。我需要加载Excel。我将添加我的算法生成数字。imgsrc=http://www.orcode.com/upimg/2011_12_07_02_50_31_2.gif但..有一个错误......如果有一个表中间的空白,该软件无法加载右侧数据的空白。我觉得...位置的问题是..有没有行限制;我插入一个例程来找到行的限制,这是固定的。有一个愉快的一天
。MsmVc
评论会员:游客 时间:2011/12/07
您好迈克尔罗伯特 所有尼斯article.It的第一有助于me.I有问题读取日期和时间format.Currently时间格式显示在双values​​.Plz,帮我
NarVish
评论会员:游客 时间:2011/12/07
。迈克尔,谢谢你的文章(IDispatch接口*的IDispatch)功能SheetCalculate火灾时,计算在Excel发生BEGIN_SINK_MAP(ExcelBookEventHandler)SINK_ENTRY_INFO(1,__uuidof(EXCEL:WorkbookEvents),0x0000061b,ExcelBookEventHandler:SheetCalculateSheetCalculateInfo)END_SINK_MAP()无效_stdcallSheetCalculate(IDispatch接口*的IDispatch){}我需要跟踪的细胞,这是Excel中的公式影响的价值。我怎样才能读取单元格的值由公式影响。希望我们可以从IDispatch指针的值。请引导我获得的单元格值。在此先感谢
shamus99
评论会员:游客 时间:2011/12/07
我有2日验证下拉列表用于统计目的的下降,到目前为止,做工精细。我的问题是如何才能让我从清单中选择显示多条线路,从不同的鞘。它是一个团队的名字和信息,但应用程序19线长和10个跨表。Havent能够找出如何,我可以通过一个下拉它显示下拉列表
拉杰什ř Subramanian
评论会员:游客 时间:2011/12/07
感谢您的精彩贡献。有我的5票。imgsrc=http://www.orcode.com/upimg/2011_12_07_02_50_31_3.gif这是一个糟糕的事情,但它的生命imgsrc=http://www.orcode.com/upimg/2011_12_07_02_50_29_0.gif卡罗Pallini
Maximilien
评论会员:游客 时间:2011/12/07
嗨,首先,真的非常漂亮的梦幻般的code.its的感谢,并有很大帮助。此代码开放的第一个工作表的Excel文件。我要打开多个工作表ecel文件。请告诉我,我怎么能打开多张工作表如果可能的话,我可以打开选定的工作表,这些选定的列请帮助敌人。预先感谢。为了完成伟大的事情,我们不仅要采取行动,但还梦想;不仅计划,但也相信。BR}
Bhagvat Gohel
评论会员:游客 时间:2011/12/07
。只是一点蛛丝马迹,我需要让我去imgsrc=http://www.orcode.com/upimg/2011_12_07_02_50_31_4.gif的此签名骄傲地对动物测试
Minok
评论会员:游客 时间:2011/12/07
给像错误返回枚举类型的所有功能。..\excel.tli(86160):错误C2556:'枚举XlPaperSize__thiscallExcel中:PAGESETUP:GetPaperSize(无效)":重载函数返回类型不同,只从"枚举Excel中:XlPaperSize__thiscallExcel中:PAGESETUP::GetPaperSize(无效)..\excel.tli(86160):错误C2371:'GetPaperSize":重新定义,不同的基本类型
zhangdb
评论会员:游客 时间:2011/12/07
跟踪通过的CreateInstance实施,其对CoCreateInstance的调用失败codeprehr=CoCreateInstance(rclsid,pOuter,dwClsContext,spanclass="code-keyword"__uuidof/span(IUnknown),spanclass="code-keyword"reinterpret_cast/spanspanclass="code-keyword"</spanspanclass="code-keyword"void/span**spanclass="code-keyword">/span(&pIUnknown));/pre/codemesage(结果):小时0x800401f0尚未调用CoInitialize的。HRESULT的任何人有任何想法?这是我们在这里使用的是库中的代码...
unclemilford
评论会员:游客 时间:2011/12/07
!运行CoInitialize的(空)
TClarke
评论会员:如题 时间:2011/12/07
Oleg_Krilov
评论会员:游客 时间:2011/12/07
我不能得到的代码编译由于链接器错误:使用Excel:范围。我调用这个类的任何属性或方法在链接自动死亡。别人经历,是很简单的项目设置,还是事物的变化,现在的MS决定将迫使我们进口的又一对象。这已经驾驶我坚果天,因此,如果任何人有一个解决办法,我求求你将它张贴
ProductDE
评论会员:游客 时间:2011/12/07
嗨,首先,大文章。imgsrc=http://www.orcode.com/upimg/2011_12_07_02_50_31_3.gif我得到的错误警告C4192:导入类型库"时,自动排除"IFont"C:\\PROGRAMFILES\\微软Office\\OFFICE11\\EXCEL.EXE"警告C4192:导入类型库"时,自动排除"IPicture"C:\\PROGRAMFILES\\微软Office\\OFFICE11\\EXCEL.EXE"它是安全使用include()属性或类似?任何想法表示赞赏。干杯汤姆经营理念:艺术,从未被超越的生活理念。宗教道德运气的工作信贷
。high_low_jack
评论会员:游客 时间:2011/12/07
如果你想打开的文件只读使​​用此代码:(长)DISP_E_PARAMNOTFOUNDVT_ERROR的_variant_tvarOption()var_RO_variant_t((短整型)的Excel:xlReadOnly,VT_I2);pBook= pApplication-GT;工作簿-GT公开赛("D:\\1.xls",varOption,var_RO,varOption,varOption, varOption,varOption,varOption,varOption, varOption,varOption,varOption,varOption);
阿尔文潘
评论会员:游客 时间:2011/12/07
您好,你能请帮助我"如何使Excel文件只读"使用C/C我开发一个自定义的应用软件,它可以产生温度数据,并可以为Excel文件使用一个GUI。下载我想这个Excel是一个只读文件,使用户不能编辑内容。感谢您的帮助。的问候,蜜蜂
图略
评论会员:游客 时间:2011/12/07
我如何使用C禁用的宏打开一个Excel文件???使用CI要启动Excel内的Excel文件,但确保Excel本身运行"禁用宏"。??Excel文件包含VBA宏。
pendejo666
评论会员:游客 时间:2011/12/07
我注意到,您可以使用Excel中:_ApplicationPtr:GetActiveObject()而不是Excel:_ApplicationPtr:的CreateInstance()来访问当前打开的Excel实例,而不是在后台打开另一个实例Excel中:_ApplicationPtr应用;HRESULT,HR=app.GetActiveObject(_T("Excel.Application的"));{BR}实际上,你可以访问所有应用程序-工作簿打开的工作簿。(全部到位最新变化,甚至在他们被保存)奇怪的是,一旦我这样做:Excel中:_WorkbookPtr书;本书=应用程序-工作簿-项目[1];//1,或一本书的名字...该工作簿从ExcelGUI消失,如果我的程序只能获得独占访问的工作簿。有谁知道的方式来访问工作簿,而无需从GUI消失?阿尔文|flippydeflippydebop:
您好,

我需要复制一行,并插入一个新行。
我发现下面这些方法在excel.tli文件,但我不知道如何使用的参数。任何人都知道一些文档?

- EXCEL::范围:插入(常量的_variant_t移位,常量的_variant_t CopyOrigin)
- EXCEL::范围:复制(常量的_variant_t目的地)

谢谢!
评论会员:图略 时间:2011/12/07
喜迈克尔,
代码,它的伟大!!我的应用程序访问Excel工作表,但数据是字符串和数字。我想知道我怎么能检查的数据类型(整数,浮点,字符.....)和数据存储在他的正确的格式吗?
我也需要检查,如果有一种方法获得每个Excel工作表的名称(我已经在每个文件上的各种表)?

的问候,

巴勃罗