通过自动化在 Excel 中放置图像






4.70/5 (13投票s)
2004年9月28日
8分钟阅读

233013

8299
如何以编程方式在 Excel 中放置图片
引言
插入文本和公式到 Excel 电子表格的示例非常丰富(参见参考文献)。所以当我面临将图片插入电子表格的任务时,我想一个合适的示例不会难找。哎呀,我错了。这可能是因为我对于搜索引擎来说是个新手。或者,也许对其他人来说,这很容易做到。但是去年一位 CP 朋友发表的一个评论给了我一些信心,认为本文可能还有一些价值。我花了痛苦的两天时间才弄清楚这一切,我希望其他读者也能避免同样的挫折。
本文演示了如何使用 Excel 自动化 API 将一组图片插入 Excel 电子表格。演示应用程序允许用户选择一个 Excel 工作簿、一组图像文件以及要插入图片的其中一个工作表。只需单击一下,图片就会在工作表中垂直堆叠,每张图片都带有一个一像素的完成边框。然后,用户可以选择保存工作簿或关闭它。
注意:该项目是用 Visual Studio .NET 2002 编写并在 WinXP 上测试的。它应该适用于 MS Office 2000 和 XP 版本。使用不同版本的 Visual Studio 和 MS Office 是留给读者的练习。
使用 Excel 自动化 API
在我们开始之前,请允许我说明一件事:我在自动化、COM 及其他此类棘手话题方面是个新手。我所知道的是,自动化是一个花哨的词,代表一个相当简单的概念。借用另一位 CP 朋友提供的一份简单解释的说法,自动化是一个编程接口——更具体地说,是应用程序公开的一个 COM 接口——允许另一个应用程序与之交互。如果您在阅读本节后有兴趣深入探讨自动化或 COM,请从这里开始。
Excel 方便地提供了一个自动化接口,让您可以控制其众多功能。在本例的上下文中,Excel 是自动化服务器,而我的程序是自动化客户端。Excel 的自动化接口封装在随 Excel 分发的类型库(也称为对象库)中。类型库包含类型定义,例如类名,它们描述了自动化/COM 接口。(可以将其想象成一个花哨的头文件。)根据您使用的 Excel 版本,有不同版本的类型库。我拥有并使用 Excel 2000,它使用 9.0 版的类型库(Excel XP 也一样)。早期版本的 Excel 使用 8.0 版的类型库。老实说,我不知道这些版本之间是否存在向后兼容性。但请不要担心:对于许多基本功能,类型库并没有实质性差异。有很多示例(其中一些在参考文献部分有提及)可以帮助您修改我的代码。如果我拥有早期版本的 Excel,我会自己去做。
导入类型库
有了类型库,您可以通过两种方式使用它,将库的内容转换为一组 C++ 类。第一种方法是使用 #import
指令,它看起来像……
#import "C:\Program Files\Microsoft Office\Office\EXCEL9.OLB" \ rename("DialogBox","_DialogBox") \ rename("RGB","_RGB") \ exclude("IFont","IPicture")
这是一种完全可行的方法。然而,令我烦恼的是,在编译时您必须知道类型库的位置。如果我在 Excel 安装在其他地方的机器上构建此代码,那么我就必须去寻找类型库。虽然这可能只需要一个不同的驱动器号,但我很懒惰,当我编写的代码失败时我会感到沮丧。
第二种方法是使用 Visual Studio 中的“添加类”向导。我不会在这里详细介绍,因为 .NET 用户可以在一篇 MSDN 文章中找到步骤,而 Visual Studio 6.0 用户可以在另一篇 MSDN 文章中找到步骤。简而言之,“添加类”向导允许您选择一个类型库(在 .NET 中是预编译列表;在 6.0 中,您仍然必须手动查找库,但只需一次,即在项目首次创建时)。Visual Studio 将愉快地解析该库并生成一组包含类定义的头文件,这些文件可用于创建您的 Excel 自动化客户端。文件生成后,就不需要再次生成它们了。(当然,除非您开始使用不同版本的类型库。)这些文件在我的示例项目中出现在“Spreadsheet”子目录下。看看这些类文件。它们不会透露太多信息,因为它们实际上只是一个巨大的函数查找表。但它们仍然值得一看。
顺便说一句,我想更清楚地说明我的偏见。虽然我有我喜欢的,但我并不想贬低从类型库中提取类定义的第一种方法。事实上,我第一次了解到自动化 Excel 是从一篇CP 文章中学到的,它使用了这种方法。我提到这两种方法是因为我想让人们意识到他们有选择。我自己的选择主要基于我的个人审美,而您可能不认同。
通过包含生成的头文件即可使用类定义。Excel API 中可能有很多类,就像应用程序中的功能一样。(嗯,不完全是,因为单个类可以封装一组通用功能。但确实有很多类。)以下是我在此示例中使用的类的简要摘要。
CApplication |
提供对活动 Excel 进程的句柄。允许您控制 Excel 是否可见,用户是否可以直接控制它等。 |
CWorkbooks |
此类表示可用于处理一组工作簿的函数。更具体地说,它用于打开单个工作簿。 |
CWorkbook |
已打开工作簿的句柄。 |
CWorksheets |
顶级工作表管理器,类似于 CWorkbook s,但用于工作表。 |
CWorksheet |
特定工作表对象的句柄。 |
CRange |
工作表中单元格范围的句柄。 |
CPictures |
顶级图片管理器。 |
CPicture |
特定图片对象的句柄。 |
CBorder |
边框对象的句柄。 |
关于演示程序
我将简要总结演示程序的流程。与其在文章中粘贴大段代码,不如直接指出工作所在的位置。有兴趣的读者可以查看注释过的源代码,了解幕后细节。
初始化 COM 库
构建自动化客户端的第一步是初始化 COM 库。必须通过调用 CoInitialize()
显式加载 COM 库,并在之后通过调用 CoUnitialize()
卸载。一个明智的放置位置是在应用程序的 InitInstance()
函数中。
BOOL CExcelImagesApp::InitInstance()
{
...
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
// main dialog goes modal
CoUnitialize ();
...
}
启动 Excel(自动化服务器)进程
我决定在主对话框的 OnInitDialog()
函数中启动 Excel 进程。您也可以在初始化 COM 库后立即启动它。但由于应用程序的整个生命周期都不需要它,所以没有必要让进程闲置,寻找麻烦。
BOOL CExcelImagesDlg::OnInitDialog();
打开工作簿
从主对话框,用户可以选择要放置图片的电子表格。(我已在演示项目中包含了一个空白电子表格和一组图片,供那些希望立即获得满足感的人使用。)选择后,将通过调用 OpenWorkbook()
(从 OnPostBrowse()
函数)打开工作簿。
void CExcelImagesDlg::OnPostBrowse(NMHDR *pNMHDR, LRESULT *pResult); void CExcelImagesDlg::OpenWorkbook (CString szWorkbook);
如果工作簿打开成功,将检索单个工作表的名称,并用于填充对话框的组合框。然后,用户可以选择其中一个工作表来放置图片。
放置图片
用户浏览选择一系列图片(任何类型都可以),然后按“放置图片”按钮。这会通过调用 InsertPictures()
(通过 OnBnClickedPlaceImages()
)来调用。InsertPictures 通过计算每张图片在行单位的高度来在工作表中垂直堆叠图片。每张图片都带有一个一像素的边框进行修饰。
void CExcelImagesDlg::OnBnClickedPlaceimages(); void CExcelImagesDlg::InsertPictures ();
关闭工作簿
当选择新工作簿或用户关闭对话框时,将关闭已打开的工作簿。这由 CloseWorkbook()
函数处理。
void CExcelImagesDlg::CloseWorkbook();
关闭 Excel
当用户关闭对话框时,Excel 进程最终关闭。这发生在对话框的 OnDestroy()
函数中。
void CExcelImagesDlg::OnDestroy();
参考文献
- 如何使用 Visual C++ .NET 的 Office 自动化类型库(MSKB 307473)
- 如何使用 C++ .NET 和 MFC 自动化 Excel 创建和格式化新工作簿(MSKB 308292)
- 如何使用 MFC 和类型库创建自动化项目(MSKB 178749)
- 如何使用 MFC 创建 Microsoft Excel 图表(MSKB 178783)
- 如何自动化 Excel 然后知道用户已将其关闭(MSKB 192348)
- 如何使用 VC++ 自动化将 Excel 工作表另存为 HTML 文件(MSKB 199691)
- 如何使用 C++ .NET 和 MFC 嵌入和自动化 Excel 工作簿(MSKB 311546)
- 如何使用 C++ .NET 自动化嵌入式 Office ActiveX 文档(MSKB 316587)
- 如何查找和使用 Office 对象模型文档(MSKB 222101)
- 自动化 MS-Office 应用程序
- 在 MFC 应用程序中使用 MS Office
致谢
感谢 PJ Arends 的文件编辑控件。当您浏览工作簿和图像文件时,您会看到它的作用。
其他关于与 MS Office 交互的有趣 CP 文章
- 使用 Excel C API 和 COM 的 Excel 加载项
- 保存 Excel 2.1 工作簿
- CSpreadSheet - 用于读写 Excel 和文本分隔电子表格的类
- 使用 VC++/ATL 构建 Office2K COM 插件
历史
- 版本 1.0 (2004 年 9 月 22 日):它活了……它活了!