VS2010环境下连续可控制的读取Excel文件中数据

来源:互联网 发布:昆仑数据科技面试 编辑:程序博客网 时间:2024/04/30 14:11
 

前几天由于需要从Excel文件中读取数据并进行相应运算,于是上网搜了很多怎么在VC中读取Excel文件数据的方法,大抵上这些方法都介绍了如何读取某个(大多是第一个)单元格的数据,但是基本上没有介绍如何连续读取若干个数据的方法。

我自己也摸索了一下,总结出来了一种连续读取一系列单元格数据的方法,以期对网上现有的内容形成一个补充。

在写方法之前,先说一下,我要实现的目标,我的目标是要实现将一个Excel文件中的A1:A61单元格的数据读入到内存的一个数组中,数据位浮点数,数组类型为double。

 

1.建立一个基于对话框的MFC工程;

2.Excel相关处理类的导入;

   a.project->add class->MFC class from typelib (项目->添加类->Typelib中的MFC类),来源里面请选择“注册表”  然后再可选择的类型库中选择“Microsoft Excel ****”这样容易不出错。

   b.选中以下几项_Application,_WorkSheet,_WorkBook,WorkSheets,WorkBooks,Range,然后导入;

   c.导入后自动在工程中添加CApplication,CWorkSheet,CWorkBook,CWorkSheets,CWorkBooks,CRange这些类;然后需要把这些类的头文件中的第一句话 #import ".......EXCEL.EXE" nonamespace 删除; 

   d.在stdafx.h中加入如下头文件

 

#include "CApplication.h"#include "CRange.h"#include "CWorkbook.h"#include "CWorkbooks.h"#include "CWorksheet.h"#include "CWorksheets.h"


    上述步骤完成之后,编译会遇到预想中的错误,Not enough actual parameters for macro 'DialogBoxW'.

    解决方法是在CRange类中:

  

VARIANT DialogBox(){VARIANT result;InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT, (void*)&result, NULL);return result;}


  将DialogBox()改为_DialogBox()即可。

 

3.获取Excel文件名和路径

   可以设置一个打开文件按钮,点击这个按钮,弹出Windows的文件选择对话框,选定某一个Excel文件。我的“打开”按钮响应函数是这样的:

 

void CGussianFitDlg::OnBnClickedButtonOpen(){// TODO: 在此添加控件通知处理程序代码CFileDialog file(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_T("EXCEL文件t(*.xls;*.xlsx)|*.xls;*.xlsx||"),AfxGetMainWnd());if(file.DoModal()==IDOK){strPath=file.GetPathName();m_Path.SetWindowTextW(strPath);}}


文件名和路径存储在名为strPath的CString类型的变量中,该变量是对话框类的成员变量。

 

4.读取Excel文件中A1:A61的数据,先贴代码,再讲解。

void CGussianFitDlg::OnBnClickedButtonRead(){// TODO: 在此添加控件通知处理程序代码COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);if (!app.CreateDispatch(_T("Excel.Application"))){MessageBox(_T("Error!Creat Excel Application Server Faile!"));exit(1);}books.AttachDispatch(app.get_Workbooks(),true); //lpDisp = books.Open(strPath,covOptional,covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional,covOptional);   book.AttachDispatch(books.Add(_variant_t(strPath)));//)获取第三步中选定的Excel文件sheets.AttachDispatch(book.get_Worksheets(),true);//获取文件中的所有sheet(因为一个Excel文件有几个sheet)//lpDisp=book.get_ActiveSheet();//sheet.AttachDispatch(sheets.get_Item(_variant_t("sheet1")),true);//获取sheet1区域,当然也可以获取sheet2等等  range.AttachDispatch(sheet.get_Cells(),true);//获取sheet1的所有单元格range.AttachDispatch(range.get_Item (COleVariant((long)1),COleVariant((long)1)).pdispVal ); //获取A1  vResult =range.get_Value2();//获取A1单元的值Waves[0]=vResult.dblVal;//将A1单元的值读入数组的第一个元素for(int i=1;i<=60;i++)//实现连续读取从A2到A61的数据{range.AttachDispatch(range.get_Item (COleVariant((long)2),COleVariant((long)1)).pdispVal ); //<span style="color:#ff0000;">这个地方有点费解,表示获取”当前区域“的第一列第二行的数据,注意是“当前区域”,后面会说说。  </span>vResult =range.get_Value2();   Waves[i]=vResult.dblVal;}42book.ReleaseDispatch();//释放文件   43books.ReleaseDispatch();   //释放啥啥啥44app.ReleaseDispatch();//释放啥啥啥45app.Quit();//Over}


对于上述红色字体所说的“当前区域”,我是这样理解的,假设已经读了A1单元格,A1单元格的实际就是第1行第1列,当前区域就是第一行(包括第一行)一下,第一列(包括第1列)以右的的区域,range.AttachDispatch(range.get_Item (COleVariant((long)2),COleVariant((long)1)).pdispVal );这一句表示获取“当前区域”的第2行第1列的数据。

又比如,当已经读入A3时,“当前区域”就变成了第3行(包括第3行)以下,第1列(包括第1列)以右的区域了,那么获取“当前区域”的第2行第1列也就是获取A4了。

所以,不能把上面的for循环写成

for(int i=1;i<=60;i++){range.AttachDispatch(range.get_Item (COleVariant((long i),COleVariant((long)1)).pdispVal );   vResult =range.get_Value2();   Waves[i]=(vResult.dblVal-1550);}

这样表面上看是对的,实际上读取来的数据非常的不符合你的预期,你的预期就是A1:A61连续读取。这也正是我当时纠结了很久的地方,觉得为什么会这样,为什么会这样?!

 

但是正确的写法感觉很不直观,如果你想直观的像那种错误的写,也有办法。办法就是每次循环开始前,都将“当前区域”置为从A1开始。

for(int i=1;i<=60;i++){range.AttachDispatch(sheet.get_Cells(),true);//这就是重置“当前区域”为A1的那一句了
range.AttachDispatch(range.get_Item (COleVariant((long i),COleVariant((long)1)).pdispVal );   vResult =range.get_Value2();   Waves[i]=(vResult.dblVal-1550);} 

   

至此,顺利完成了读取Excel文件中A1:A61中的数据了。

 

这篇文章的前三步参考了下面的博客

点击打开链接   http://blog.csdn.net/fkzh2651/article/details/12185611

最后一步是自己摸索出来的,写在这里,一是为了以后自己查阅方便,二也是总结一下,方便他人。

0 0
原创粉丝点击