magipige
有一天,一位网友加入了我的Q群,然后又通过Q群私信我,向我请教如何使用VS读写excel文件表格的问题。其实,在ta向我请教的时候,我也没有写过这样功能模块或是开发过类似的小程序。但,仍是被ta求知的行为感动了,所以决定花些时间去了解这方面的知识,给ta一个答复。
于是,经过搜索,找到了相关资料,并写了个示例小程序给ta。当然,那个示例小程序并不是本文给的这个程序,本文的示例小程序是为了配合本文的演示,而故意修改的,更适合初学者使用,两者原理和实现上基本上是一样的。
现在,我就把这个小程序的实现思路和实现过程,写成文档,分享给大家。
我们需要导入MFC类库,来帮助我们实现对EXCEL表格的操作。那么,就要求我们的项目工程支持MFC。类似,WIN32 控制台程序默认是不支持MFC的,所以,在创建项目的时候,要选择支持MFC。
现在,本文以WIN32 控制台项目工程为例,讲解导入EXCEL所需类库的操作:
首先,在“Win32应用程序向导”窗口中,注意要选择“添加公共头文件以用于:MFC”。然后点击“完成”,成功创建项目工程。
进入项目工程中,选中项目,鼠标右键选择“添加” —> “添加类”。在“添加类”对话框中选择“TypeLib中的MFC类”,即基于类型库添加Microsoft基础类库类。
接着需要选择OLE/COM 组件的路径,也就是你计算机上excel.exe 所在的路径。我的Microsoft Office是安装在F盘,所以excel.exe路径就是:
路径选择完毕后,需要向项目工程中添加基本的 7 个类( Excel 作为 OLE/COM 库插件,定义好了各类交互的接口,这些接口是跨语言的接口。 VC 可以通过导入这些接口,并通过 接口来对 Excel 的操作), 由于本文只关心对 Excel 表格中的数据的读取,主要关注 7 个接口:_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range、Font。
添加完毕后,点击“完成”,即可成功添加 7 个类到项目工程中。
成功添加 7 个类之后,项目工程会新增 7 个类库的头文件:
但是,如果我们直接编译项目工程的话,会报错的。所以,现在需要对上述生成的 7 个头文件进行修改:
将每个头文件顶头的:
注释掉。并添加头文件:”#include <afxdisp.h>“
修改完毕后,再编译程序,若报错,而且错误号为“C2059”,则双击错误,跳转到错误代码行。然后将 将VARIANT DialogBox() 改成 VARIANT _DialogBox() ,再次编译,即可编译通过。
首先,使用CApplication::CreateDispatch创建Excel.Application对象,并获取工作簿CWorkbooks
接着,使用CWorkbooks::Open打开excel表格文件,并获取工作表对象CWorksheets
然后使用CWorksheets::get_Item获取指定的工作表对象CWorksheet。本文是获取第 1 张工作表
接着,我们可以调用CWorksheet::get_Range获取读取表格的范围。本文是获取 A1—A1 范围的表格
然后,对表格内容弹窗输出
最后,关闭对象,进行清理工作
首先,使用CApplication::CreateDispatch创建Excel.Application对象,并获取工作簿CWorkbooks
接着,使用CWorkbooks::Add新添加一个工作簿,并使用CWorkbook::get_Worksheets获取工作表对象
然后使用CWorksheets::get_Item获取指定的工作表对象CWorksheet。本文是获取第 1 张工作表
接着,我们可以调用CWorksheet::get_Range获取表格的范围。本文是获取 A1—C3 范围的表格。并调用CRange::put_Value2将表格写入数据,并设置字体以及列宽
然后,调用CWorkbook::SaveAs保存文件
最后,关闭对象,进行清理工作
// 读取
BOOL MyExcel::ReadExcel()
{
//导入
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
if (!app.CreateDispatch(_T("Excel.Application")))
{
::MessageBox(NULL, "无法创建Excel应用!", "WARNING", MB_OK);
return TRUE;
}
books = app.get_Workbooks();
//打开Excel,其中pathname为Excel表的路径名
lpDisp = books.Open(_T("C:\\Users\\DemonGan\\Desktop\\test.xlsx"),
covOptional, covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional);
book.AttachDispatch(lpDisp);
sheets = book.get_Worksheets();
sheet = sheets.get_Item(COleVariant((short)1));
//获得坐标为(A,1) -- (A,1)的单元格
range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("A1")));
//获得单元格的内容
COleVariant rValue;
rValue = COleVariant(range.get_Value2());
//转换成宽字符
rValue.ChangeType(VT_BSTR);
//转换格式,并弹窗输出
::MessageBox(NULL, CString(rValue.bstrVal), "RESULT", MB_OK);
book.put_Saved(TRUE);
// 退出
app.Quit();
app.ReleaseDispatch();
app = NULL;
return TRUE;
}
// 写入
BOOL MyExcel::WriteExcel()
{
//导出
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
if (!app.CreateDispatch(_T("Excel.Application")))
{
::MessageBox(NULL, "无法创建Excel应用!", "WARNING", MB_OK);
return TRUE;
}
books = app.get_Workbooks();
book = books.Add(covOptional);
sheets = book.get_Worksheets();
sheet = sheets.get_Item(COleVariant((short)1));
//获得坐标为(A,1)和(C,3)范围区域的9个单元格
range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("C3")));
//设置单元格类容为World Of Demon
range.put_Value2(COleVariant(_T("CDIY")));
//选择整列,并设置宽度为自适应
cols = range.get_EntireColumn();
cols.AutoFit();
//设置字体为粗体
font = range.get_Font();
font.put_Bold(COleVariant((short)TRUE));
//获得坐标为(D,4)单元格
range = sheet.get_Range(COleVariant(_T("D4")), COleVariant(_T("D4")));
//设置公式“=RAND()*100000”
range.put_Formula(COleVariant(_T("=RAND()*100000")));
//设置数字格式为货币型
range.put_NumberFormat(COleVariant(_T("$0.00")));
//选择整列,并设置宽度为自适应
cols = range.get_EntireColumn();
cols.AutoFit();
//显示Excel表
// app.put_Visible(TRUE);
// app.put_UserControl(TRUE);
// 保存excel表
COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
COleVariant vFileName(_T("C:\\Users\\DemonGan\\Desktop\\test.xlsx"));
book.SaveAs(
vFileName, //VARIANT* FileName
vOptional, //VARIANT* FileFormat
vOptional, //VARIANT* LockComments
vOptional, //VARIANT* Password
vOptional, //VARIANT* AddToRecentFiles
vOptional, //VARIANT* WritePassword
0, //VARIANT* ReadOnlyRecommended
vOptional, //VARIANT* EmbedTrueTypeFonts
vOptional, //VARIANT* SaveNativePictureFormat
vOptional, //VARIANT* SaveFormsData
vOptional, //VARIANT* SaveAsAOCELetter
vOptional //VARIANT* ReadOnlyRecommended
);
// 退出
app.Quit();
app.ReleaseDispatch();
app = NULL;
return TRUE;
}
在 main 函数中调用上述封装好的函数,进行测试。 main 函数为:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(NULL);
if (hModule != NULL)
{
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
MyExcel myExcel;
// 写入数据
myExcel.WriteExcel();
printf("Write OK.\n");
system("pause");
// 读取数据
myExcel.ReadExcel();
printf("Read OK.\n");
system("pause");
}
}
else
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: GetModuleHandle 失败\n"));
nRetCode = 1;
}
return nRetCode;
}
测试结果
运行程序,提示写入EXCEL表格成功。
然后,打开生成的“test.xlsx”文件,数据被成功写入。
然后,我们继续执行程序,EXCEL表格中的“A1”个的数据成功读取,并弹窗显示。
这个小程序,主要是前期创建工程的时候需要注意,如果你创建的是MFC,那么就跟着上述步骤,导入操作EXCEL所需的MFC类库。但,如果你创建的是其他工程,例如Win32工程,那么在创建的过程中,就应该选择包含MFC的功能,因为程序需要导入操作EXCEL所需的MFC类库,所以工程必须要支持MFC。
keyboard_arrow_left上一篇 : 使用VS2013编译Detours库 使用Windows7旗舰版64位来搭建ASP服务器环境 : 下一篇keyboard_arrow_right