magipige的文章

  • 使用VS2013实现对Excel表格的读写

    背景有一天,一位网友加入了我的Q群,然后又通过Q群私信我,向我请教如何使用VS读写excel文件表格的问题。其实,在ta向我请教的时候,我也没有写过这样功能模块或是开发过类似的小程序。但,仍是被ta求知的行为感动了,所以决定花些时间去了解这方面的知识,给ta一个答复。
    于是,经过搜索,找到了相关资料,并写了个示例小程序给ta。当然,那个示例小程序并不是本文给的这个程序,本文的示例小程序是为了配合本文的演示,而故意修改的,更适合初学者使用,两者原理和实现上基本上是一样的。
    现在,我就把这个小程序的实现思路和实现过程,写成文档,分享给大家。
    导入操作EXCEL所需的MFC类库我们需要导入MFC类库,来帮助我们实现对EXCEL表格的操作。那么,就要求我们的项目工程支持MFC。类似,WIN32 控制台程序默认是不支持MFC的,所以,在创建项目的时候,要选择支持MFC。
    现在,本文以WIN32 控制台项目工程为例,讲解导入EXCEL所需类库的操作:
    首先,在“Win32应用程序向导”窗口中,注意要选择“添加公共头文件以用于:MFC”。然后点击“完成”,成功创建项目工程。

    进入项目工程中,选中项目,鼠标右键选择“添加” —> “添加类”。在“添加类”对话框中选择“TypeLib中的MFC类”,即基于类型库添加Microsoft基础类库类。

    接着需要选择OLE/COM 组件的路径,也就是你计算机上excel.exe 所在的路径。我的Microsoft Office是安装在F盘,所以excel.exe路径就是:

    F:\Program Files (x86)\Microsoft Office\Office12\EXCEL.EXE
    路径选择完毕后,需要向项目工程中添加基本的 7 个类( Excel 作为 OLE/COM 库插件,定义好了各类交互的接口,这些接口是跨语言的接口。 VC 可以通过导入这些接口,并通过 接口来对 Excel 的操作), 由于本文只关心对 Excel 表格中的数据的读取,主要关注 7 个接口:_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range、Font。
    添加完毕后,点击“完成”,即可成功添加 7 个类到项目工程中。

    成功添加 7 个类之后,项目工程会新增 7 个类库的头文件:

    但是,如果我们直接编译项目工程的话,会报错的。所以,现在需要对上述生成的 7 个头文件进行修改:
    将每个头文件顶头的:

    “#import “F:\Program Files (x86)\Microsoft Office\Office12\EXCEL.EXE” no_namespace”
    注释掉。并添加头文件:”#include <afxdisp.h>“

    修改完毕后,再编译程序,若报错,而且错误号为“C2059”,则双击错误,跳转到错误代码行。然后将 将VARIANT DialogBox() 改成 VARIANT _DialogBox() ,再次编译,即可编译通过。


    实现原理从EXCEL表格中读取数据
    首先,使用CApplication::CreateDispatch创建Excel.Application对象,并获取工作簿CWorkbooks
    接着,使用CWorkbooks::Open打开excel表格文件,并获取工作表对象CWorksheets
    然后使用CWorksheets::get_Item获取指定的工作表对象CWorksheet。本文是获取第 1 张工作表
    接着,我们可以调用CWorksheet::get_Range获取读取表格的范围。本文是获取 A1—A1 范围的表格
    然后,对表格内容弹窗输出
    最后,关闭对象,进行清理工作

    向EXCEL表格中写入数据
    首先,使用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保存文件
    最后,关闭对象,进行清理工作

    编码实现从EXCEL表格中读取数据// 读取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;}
    向EXCEL表格中写入数据// 写入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。
    1  留言 2018-12-26 12:56:58

发送私信

生活不会因为你是女孩子就善待你

11
文章数
15
评论数
eject