C++读取excel表格

爱被打了一巴掌 2023-07-09 02:13 159阅读 0赞

1 创建mfc程序(这里以vs2013为例)

20141225111940943

20141225111946562

20141225111953517

到这里直接点击完成即可。

2 添加读取excel文件用到的类

2.1 打开类向导

20141225111959133

2.2 添加类

20141225112004312

将_Application、_Workbook、_Worksheet、Workbooks、Worksheets添加到“生成的类”中

3 添加完成后,找到相关头文件,注释/删除

  1. #import "D:\\software\\office2010\\Office14\\EXCEL.EXE"no_namespace

4 再次编译还是有错误

定位错误信息,将DialogBox()改为_DialogBox()

5 添加源码(最重要的一步)

5.1.Excel.h

  1. //Excel.h
  2. #pragma once
  3. #include "CApplication.h"
  4. #include "CRange.h"
  5. #include "CWorkbook.h"
  6. #include "CWorkbooks.h"
  7. #include "CWorksheet.h"
  8. #include "CWorksheets.h"
  9. class Excel
  10. {
  11. private:
  12. CString openFileName;
  13. CWorkbook workBook;//当前处理文件
  14. CWorkbooks books;//ExcelBook集合,多文件时使用
  15. CWorksheet workSheet;//当前使用sheet
  16. CWorksheets sheets;//Excel的sheet集合
  17. CRange currentRange;//当前操作区域
  18. bool isLoad;//是否已经加载了某个sheet数据
  19. COleSafeArray safeArray;
  20. protected:
  21. static CApplication application;//Excel进程实例
  22. public:
  23. Excel();
  24. virtual ~Excel();
  25. void show(bool bShow);
  26. //检查一个cell是否为字符串
  27. bool isCellString(long iRow, long iColumn);
  28. //检查一个cell是否为数值
  29. bool isCellInt(long iRow, long iColumn);
  30. //得到一个cell的string
  31. CString getCellString(long iRow, long iColumn);
  32. //得到一个cell的整数
  33. int getCellInt(long iRow, long iColumn);
  34. //得到一个cell的double数据
  35. double getCellDouble(long iRow, long iColumn);
  36. //取得行的总数
  37. int getRowCount();
  38. //取得列的整数
  39. int getColumnCount();
  40. //使用某个shell
  41. bool loadSheet(long tableId, bool preLoaded = false);
  42. bool loadSheet(CString sheet, bool preLoaded = false);
  43. //通过序号取得某个shell的名称
  44. CString getSheetName(long tableID);
  45. //得到sheel的总数
  46. int getSheetCount();
  47. //打开excel文件
  48. bool open(const char* fileName);
  49. //关闭打开的excel文件
  50. void close(bool ifSave = false);
  51. //另存为一个excel文件
  52. void saveAsXLSFile(const CString &xlsFile);
  53. //取得打开文件的名称
  54. CString getOpenFileName();
  55. //取得打开sheel的名称
  56. CString getOpenSheelName();
  57. //向cell中写入一个int值
  58. void setCellInt(long iRow, long iColumn,int newInt);
  59. //向cell中写入一个字符串
  60. void setCellString(long iRow, long iColumn, CString newString);
  61. public:
  62. //初始化 Excel_OLE
  63. static bool initExcel();
  64. //释放Excel_OLE
  65. static void release();
  66. //取得列的名称
  67. static char* getColumnName(long iColumn);
  68. protected:
  69. void preLoadSheet();
  70. };

5.2.Excel.cpp

  1. //Excel.cpp
  2. #include "stdafx.h"
  3. #include <tchar.h>
  4. #include "Excel.h"
  5. COleVariant
  6. covTrue((short)TRUE),
  7. covFalse((short)FALSE),
  8. covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  9. CApplication Excel::application;
  10. Excel::Excel() :isLoad(false)
  11. {
  12. }
  13. Excel::~Excel()
  14. {
  15. //close();
  16. }
  17. bool Excel::initExcel()
  18. {
  19. //创建Excel 2000服务器(启动Excel)
  20. AfxOleInit(); //先初始化ole
  21. if (!application.CreateDispatch(_T("Excel.application"),nullptr))
  22. {
  23. MessageBox(nullptr,_T("创建Excel服务失败,你可能没有安装EXCEL,请检查!"),_T("错误"),MB_OK);
  24. return FALSE;
  25. }
  26. application.put_DisplayAlerts(FALSE);
  27. return true;
  28. }
  29. void Excel::release()
  30. {
  31. application.Quit();
  32. application.ReleaseDispatch();
  33. application = nullptr;
  34. }
  35. bool Excel::open(const char* fileName)
  36. {
  37. //先关闭文件
  38. close();
  39. //利用模板建立新文档
  40. books.AttachDispatch(application.get_Workbooks(), true);
  41. LPDISPATCH lpDis = nullptr;
  42. lpDis = books.Add(COleVariant(CString(fileName)));
  43. if (lpDis)
  44. {
  45. workBook.AttachDispatch(lpDis);
  46. sheets.AttachDispatch(workBook.get_Worksheets());
  47. openFileName = fileName;
  48. return true;
  49. }
  50. return false;
  51. }
  52. void Excel::close(bool ifSave)
  53. {
  54. //如果文件已经打开,关闭文件
  55. if (!openFileName.IsEmpty())
  56. {
  57. //如果保存,交给用户控制,让用户自己存,如果自己SAVE,会出现莫名的等待
  58. if (ifSave)
  59. {
  60. //show(true);
  61. }
  62. else
  63. {
  64. workBook.Close(COleVariant(short(FALSE)), COleVariant(openFileName), covOptional);
  65. books.Close();
  66. }
  67. //清空打开文件名称
  68. openFileName.Empty();
  69. }
  70. sheets.ReleaseDispatch();
  71. workSheet.ReleaseDispatch();
  72. currentRange.ReleaseDispatch();
  73. workBook.ReleaseDispatch();
  74. books.ReleaseDispatch();
  75. }
  76. void Excel::saveAsXLSFile(const CString &xlsFile)
  77. {
  78. workBook.SaveAs(COleVariant(xlsFile),
  79. covOptional,
  80. covOptional,
  81. covOptional,
  82. covOptional,
  83. covOptional,
  84. 0,
  85. covOptional,
  86. covOptional,
  87. covOptional,
  88. covOptional,
  89. covOptional);
  90. return;
  91. }
  92. int Excel::getSheetCount()
  93. {
  94. return sheets.get_Count();
  95. }
  96. CString Excel::getSheetName(long tableID)
  97. {
  98. CWorksheet sheet;
  99. sheet.AttachDispatch(sheets.get_Item(COleVariant((long)tableID)));
  100. CString name = sheet.get_Name();
  101. sheet.ReleaseDispatch();
  102. return name;
  103. }
  104. void Excel::preLoadSheet()
  105. {
  106. CRange used_range;
  107. used_range = workSheet.get_UsedRange();
  108. VARIANT ret_ary = used_range.get_Value2();
  109. if (!(ret_ary.vt & VT_ARRAY))
  110. {
  111. return;
  112. }
  113. //
  114. safeArray.Clear();
  115. safeArray.Attach(ret_ary);
  116. }
  117. //按照名称加载sheet表格,也可提前加载所有表格
  118. bool Excel::loadSheet(long tableId, bool preLoaded)
  119. {
  120. LPDISPATCH lpDis = nullptr;
  121. currentRange.ReleaseDispatch();
  122. currentRange.ReleaseDispatch();
  123. lpDis = sheets.get_Item(COleVariant((long)tableId));
  124. if (lpDis)
  125. {
  126. workSheet.AttachDispatch(lpDis, true);
  127. currentRange.AttachDispatch(workSheet.get_Cells(), true);
  128. }
  129. else
  130. {
  131. return false;
  132. }
  133. isLoad = false;
  134. //如果进行预先加载
  135. if (preLoaded)
  136. {
  137. preLoadSheet();
  138. isLoad = true;
  139. }
  140. return true;
  141. }
  142. bool Excel::loadSheet(CString sheet, bool preLoaded)
  143. {
  144. LPDISPATCH lpDis = nullptr;
  145. currentRange.ReleaseDispatch();
  146. currentRange.ReleaseDispatch();
  147. lpDis = sheets.get_Item(COleVariant(sheet));
  148. if (lpDis)
  149. {
  150. workSheet.AttachDispatch(lpDis, true);
  151. currentRange.AttachDispatch(workSheet.get_Cells(), true);
  152. }
  153. else
  154. {
  155. return false;
  156. }
  157. isLoad = false;
  158. //如果进行预先加载
  159. if (preLoaded)
  160. {
  161. preLoadSheet();
  162. isLoad = true;
  163. }
  164. return true;
  165. }
  166. int Excel::getColumnCount()
  167. {
  168. CRange range;
  169. CRange usedRange;
  170. usedRange.AttachDispatch(workSheet.get_UsedRange(), true);
  171. range.AttachDispatch(usedRange.get_Columns(), true);
  172. int count = range.get_Count();
  173. usedRange.ReleaseDispatch();
  174. range.ReleaseDispatch();
  175. return count;
  176. }
  177. int Excel::getRowCount()
  178. {
  179. CRange range;
  180. CRange usedRange;
  181. usedRange.AttachDispatch(workSheet.get_UsedRange(), true);
  182. range.AttachDispatch(usedRange.get_Rows(), true);
  183. int count = range.get_Count();
  184. usedRange.ReleaseDispatch();
  185. range.ReleaseDispatch();
  186. return count;
  187. }
  188. bool Excel::isCellString(long iRow, long iColumn)
  189. {
  190. CRange range;
  191. range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
  192. COleVariant vResult = range.get_Value2();
  193. //VT_BSTR标示字符串
  194. if (vResult.vt == VT_BSTR)
  195. {
  196. return true;
  197. }
  198. return false;
  199. }
  200. bool Excel::isCellInt(long iRow, long iColumn)
  201. {
  202. CRange range;
  203. range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
  204. COleVariant vResult = range.get_Value2();
  205. //VT_BSTR标示字符串
  206. if (vResult.vt == VT_INT || vResult.vt == VT_R8)
  207. {
  208. return true;
  209. }
  210. return false;
  211. }
  212. CString Excel::getCellString(long iRow, long iColumn)
  213. {
  214. COleVariant vResult;
  215. CString str;
  216. //字符串
  217. if (isLoad == false)
  218. {
  219. CRange range;
  220. range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
  221. vResult = range.get_Value2();
  222. range.ReleaseDispatch();
  223. }
  224. //如果数据依据预先加载了
  225. else
  226. {
  227. long read_address[2];
  228. VARIANT val;
  229. read_address[0] = iRow;
  230. read_address[1] = iColumn;
  231. safeArray.GetElement(read_address, &val);
  232. vResult = val;
  233. }
  234. if (vResult.vt == VT_BSTR)
  235. {
  236. str = vResult.bstrVal;
  237. }
  238. //整数
  239. else if (vResult.vt == VT_INT)
  240. {
  241. str.Format(_T("%d"), vResult.pintVal);
  242. }
  243. //8字节的数字
  244. else if (vResult.vt == VT_R8)
  245. {
  246. str.Format(_T("%0.0f"), vResult.dblVal);
  247. }
  248. //时间格式
  249. else if (vResult.vt == VT_DATE)
  250. {
  251. SYSTEMTIME st;
  252. VariantTimeToSystemTime(vResult.date, &st);
  253. CTime tm(st);
  254. str = tm.Format(_T("%Y-%m-%d"));
  255. }
  256. //单元格空的
  257. else if (vResult.vt == VT_EMPTY)
  258. {
  259. str = "";
  260. }
  261. return str;
  262. }
  263. double Excel::getCellDouble(long iRow, long iColumn)
  264. {
  265. double rtn_value = 0;
  266. COleVariant vresult;
  267. //字符串
  268. if (isLoad == false)
  269. {
  270. CRange range;
  271. range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
  272. vresult = range.get_Value2();
  273. range.ReleaseDispatch();
  274. }
  275. //如果数据依据预先加载了
  276. else
  277. {
  278. long read_address[2];
  279. VARIANT val;
  280. read_address[0] = iRow;
  281. read_address[1] = iColumn;
  282. safeArray.GetElement(read_address, &val);
  283. vresult = val;
  284. }
  285. if (vresult.vt == VT_R8)
  286. {
  287. rtn_value = vresult.dblVal;
  288. }
  289. return rtn_value;
  290. }
  291. int Excel::getCellInt(long iRow, long iColumn)
  292. {
  293. int num;
  294. COleVariant vresult;
  295. if (isLoad == FALSE)
  296. {
  297. CRange range;
  298. range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true);
  299. vresult = range.get_Value2();
  300. range.ReleaseDispatch();
  301. }
  302. else
  303. {
  304. long read_address[2];
  305. VARIANT val;
  306. read_address[0] = iRow;
  307. read_address[1] = iColumn;
  308. safeArray.GetElement(read_address, &val);
  309. vresult = val;
  310. }
  311. //
  312. num = static_cast<int>(vresult.dblVal);
  313. return num;
  314. }
  315. void Excel::setCellString(long iRow, long iColumn, CString newString)
  316. {
  317. COleVariant new_value(newString);
  318. CRange start_range = workSheet.get_Range(COleVariant(_T("A1")), covOptional);
  319. CRange write_range = start_range.get_Offset(COleVariant((long)iRow - 1), COleVariant((long)iColumn - 1));
  320. write_range.put_Value2(new_value);
  321. start_range.ReleaseDispatch();
  322. write_range.ReleaseDispatch();
  323. }
  324. void Excel::setCellInt(long iRow, long iColumn, int newInt)
  325. {
  326. COleVariant new_value((long)newInt);
  327. CRange start_range = workSheet.get_Range(COleVariant(_T("A1")), covOptional);
  328. CRange write_range = start_range.get_Offset(COleVariant((long)iRow - 1), COleVariant((long)iColumn - 1));
  329. write_range.put_Value2(new_value);
  330. start_range.ReleaseDispatch();
  331. write_range.ReleaseDispatch();
  332. }
  333. void Excel::show(bool bShow)
  334. {
  335. application.put_Visible(bShow);
  336. application.put_UserControl(bShow);
  337. }
  338. CString Excel::getOpenFileName()
  339. {
  340. return openFileName;
  341. }
  342. CString Excel::getOpenSheelName()
  343. {
  344. return workSheet.get_Name();
  345. }
  346. char* Excel::getColumnName(long iColumn)
  347. {
  348. static char column_name[64];
  349. size_t str_len = 0;
  350. while (iColumn > 0)
  351. {
  352. int num_data = iColumn % 26;
  353. iColumn /= 26;
  354. if (num_data == 0)
  355. {
  356. num_data = 26;
  357. iColumn--;
  358. }
  359. column_name[str_len] = (char)((num_data - 1) + 'A');
  360. str_len++;
  361. }
  362. column_name[str_len] = '\0';
  363. //反转
  364. _strrev(column_name);
  365. return column_name;
  366. }

6.使用示例

  1. //使用excel类
  2. Excel excl;
  3. bool bInit = excl.initExcel();
  4. char path[MAX_PATH];
  5. GetCurrentDirectoryA(MAX_PATH, path);//获取当前工作目录
  6. strcat_s(path, "\\data.xlsx");//设置要打开文件的完整路径
  7. bool bRet = excl.open(path);//打开excel文件
  8. CString strSheetName = excl.getSheetName(1);//获取sheet名
  9. bool bLoad = excl.loadSheet(strSheetName);//装载sheet
  10. int nRow = excl.getRowCount();//获取sheet中行数
  11. int nCol = excl.getColumnCount();//获取sheet中列数
  12. CString cell;
  13. for (int i = 1; i <= nRow; ++i)
  14. {
  15. for (int j = 1; j <= nCol; ++j)
  16. {
  17. cell = excl.getCellString(i, j);
  18. }
  19. }
  20. 

补充:

在原文中作者初始化excel服务时,在比如xp机器上会出现创建excel服务失败的情况,作为补充,我在初始化excel服务时添加了ole的初始化方法,

  1. AfxOleInit();

原文链接:https://blog.csdn.net/u013507368/article/details/42143913

发表评论

表情:
评论列表 (有 0 条评论,159人围观)

还没有评论,来说两句吧...

相关阅读