{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.Applicationquot";)))){ 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类火灾的燃烧。他们需要我们。他们总是需要我们。历史
第一次修订。