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

magipige

发布日期: 2018-12-26 12:56:58 浏览量: 2202
评分:
star star star star star star star star star star
*转载请注明来自write-bug.com

背景

有一天,一位网友加入了我的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表格中读取数据

  1. // 读取
  2. BOOL MyExcel::ReadExcel()
  3. {
  4. //导入
  5. COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  6. if (!app.CreateDispatch(_T("Excel.Application")))
  7. {
  8. ::MessageBox(NULL, "无法创建Excel应用!", "WARNING", MB_OK);
  9. return TRUE;
  10. }
  11. books = app.get_Workbooks();
  12. //打开Excel,其中pathname为Excel表的路径名
  13. lpDisp = books.Open(_T("C:\\Users\\DemonGan\\Desktop\\test.xlsx"),
  14. covOptional, covOptional, covOptional, covOptional, covOptional,
  15. covOptional, covOptional, covOptional, covOptional, covOptional,
  16. covOptional, covOptional, covOptional, covOptional);
  17. book.AttachDispatch(lpDisp);
  18. sheets = book.get_Worksheets();
  19. sheet = sheets.get_Item(COleVariant((short)1));
  20. //获得坐标为(A,1) -- (A,1)的单元格
  21. range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("A1")));
  22. //获得单元格的内容
  23. COleVariant rValue;
  24. rValue = COleVariant(range.get_Value2());
  25. //转换成宽字符
  26. rValue.ChangeType(VT_BSTR);
  27. //转换格式,并弹窗输出
  28. ::MessageBox(NULL, CString(rValue.bstrVal), "RESULT", MB_OK);
  29. book.put_Saved(TRUE);
  30. // 退出
  31. app.Quit();
  32. app.ReleaseDispatch();
  33. app = NULL;
  34. return TRUE;
  35. }

向EXCEL表格中写入数据

  1. // 写入
  2. BOOL MyExcel::WriteExcel()
  3. {
  4. //导出
  5. COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  6. if (!app.CreateDispatch(_T("Excel.Application")))
  7. {
  8. ::MessageBox(NULL, "无法创建Excel应用!", "WARNING", MB_OK);
  9. return TRUE;
  10. }
  11. books = app.get_Workbooks();
  12. book = books.Add(covOptional);
  13. sheets = book.get_Worksheets();
  14. sheet = sheets.get_Item(COleVariant((short)1));
  15. //获得坐标为(A,1)和(C,3)范围区域的9个单元格
  16. range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("C3")));
  17. //设置单元格类容为World Of Demon
  18. range.put_Value2(COleVariant(_T("CDIY")));
  19. //选择整列,并设置宽度为自适应
  20. cols = range.get_EntireColumn();
  21. cols.AutoFit();
  22. //设置字体为粗体
  23. font = range.get_Font();
  24. font.put_Bold(COleVariant((short)TRUE));
  25. //获得坐标为(D,4)单元格
  26. range = sheet.get_Range(COleVariant(_T("D4")), COleVariant(_T("D4")));
  27. //设置公式“=RAND()*100000”
  28. range.put_Formula(COleVariant(_T("=RAND()*100000")));
  29. //设置数字格式为货币型
  30. range.put_NumberFormat(COleVariant(_T("$0.00")));
  31. //选择整列,并设置宽度为自适应
  32. cols = range.get_EntireColumn();
  33. cols.AutoFit();
  34. //显示Excel表
  35. // app.put_Visible(TRUE);
  36. // app.put_UserControl(TRUE);
  37. // 保存excel表
  38. COleVariant vTrue((short)TRUE),
  39. vFalse((short)FALSE),
  40. vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  41. COleVariant vFileName(_T("C:\\Users\\DemonGan\\Desktop\\test.xlsx"));
  42. book.SaveAs(
  43. vFileName, //VARIANT* FileName
  44. vOptional, //VARIANT* FileFormat
  45. vOptional, //VARIANT* LockComments
  46. vOptional, //VARIANT* Password
  47. vOptional, //VARIANT* AddToRecentFiles
  48. vOptional, //VARIANT* WritePassword
  49. 0, //VARIANT* ReadOnlyRecommended
  50. vOptional, //VARIANT* EmbedTrueTypeFonts
  51. vOptional, //VARIANT* SaveNativePictureFormat
  52. vOptional, //VARIANT* SaveFormsData
  53. vOptional, //VARIANT* SaveAsAOCELetter
  54. vOptional //VARIANT* ReadOnlyRecommended
  55. );
  56. // 退出
  57. app.Quit();
  58. app.ReleaseDispatch();
  59. app = NULL;
  60. return TRUE;
  61. }

程序测试

在 main 函数中调用上述封装好的函数,进行测试。 main 函数为:

  1. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  2. {
  3. int nRetCode = 0;
  4. HMODULE hModule = ::GetModuleHandle(NULL);
  5. if (hModule != NULL)
  6. {
  7. // 初始化 MFC 并在失败时显示错误
  8. if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
  9. {
  10. // TODO: 更改错误代码以符合您的需要
  11. _tprintf(_T("错误: MFC 初始化失败\n"));
  12. nRetCode = 1;
  13. }
  14. else
  15. {
  16. // TODO: 在此处为应用程序的行为编写代码。
  17. MyExcel myExcel;
  18. // 写入数据
  19. myExcel.WriteExcel();
  20. printf("Write OK.\n");
  21. system("pause");
  22. // 读取数据
  23. myExcel.ReadExcel();
  24. printf("Read OK.\n");
  25. system("pause");
  26. }
  27. }
  28. else
  29. {
  30. // TODO: 更改错误代码以符合您的需要
  31. _tprintf(_T("错误: GetModuleHandle 失败\n"));
  32. nRetCode = 1;
  33. }
  34. return nRetCode;
  35. }

测试结果

运行程序,提示写入EXCEL表格成功。

然后,打开生成的“test.xlsx”文件,数据被成功写入。

然后,我们继续执行程序,EXCEL表格中的“A1”个的数据成功读取,并弹窗显示。

总结

这个小程序,主要是前期创建工程的时候需要注意,如果你创建的是MFC,那么就跟着上述步骤,导入操作EXCEL所需的MFC类库。但,如果你创建的是其他工程,例如Win32工程,那么在创建的过程中,就应该选择包含MFC的功能,因为程序需要导入操作EXCEL所需的MFC类库,所以工程必须要支持MFC。

上传的附件 cloud_download Excel_Test.7z ( 641.44kb, 24次下载 )

keyboard_arrow_left上一篇 : python爬取双色球数据更新及数据库使用 基于C语言实现的哈夫曼树问题 : 下一篇keyboard_arrow_right



magipige
2018-12-26 12:56:23
使用VS2013实现对Excel表格的读写
啥都不知道
2021-05-31 12:27:41
代码写在哪个文件里
啥都不知道
2021-05-31 12:28:48
错误 1 error MSB8031: Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. See http://go.microsoft.com/fwlink/p/?LinkId=286820 for more information. C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets 369 5 Excel_Test
南风吹木
2021-06-08 10:29:03
可以
yufan000
2021-06-08 20:46:01
对的,写的很好

发送私信

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

11
文章数
15
评论数
最近文章
eject