前段时间写个工具需要从Excel文件中读取数据,Excel表格数据列数为确定值,行数不确定,从网上搜了些方法尝试,最终达到目的,总结如下:
1. 新建一个基于对话框的MFC应用程序
2. 添加Excel相关类
打开类向导,添加类下拉框选择类型库中的MFC类,来源选择注册表(不容易出错),可用的类型库选择"Microsoft Excel ..."(根据Excel的版本有所不同);接口选择:_Application,_WorkSheet,_WorkBook,Range,WorkSheets,WorkBooks;添加6个必要的类CApplication,CWorkbook,CWorksheet,CRange,CWorkbooks,CWorksheets
3. 添加完成后,找到相关头文件,注释或删除:
//#import "D:\\Program Files (x86)\\Microsoft Office\\Office14\\EXCEL.EXE" no_namespace
在stdafx.h中添加:
#include "CApplication.h"
#include "CRange.h"
#include "CWorkbook.h"
#include "CWorkbooks.h"
#include "CWorksheet.h"
#include "CWorksheets.h"
4. 编译出现错误:
1>e:\vs2010_project\demo\mfcexcel\crange.h(335): warning C4003: “DialogBoxW”宏的实参不足
1>e:\vs2010_project\demo\mfcexcel\crange.h(335): error C2059: 语法错误:“,”
解决方法:定位错误信息,在CRange类中将DialogBox()改为_DialogBox()
VARIANT _DialogBox()
{
VARIANT result;
InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT, (void*)&result, NULL);
return result;
}
5. 获取Excel文件路径全名(包括文件名)
添加一个打开文件按钮和显示路径的编辑框,按钮单击消息处理函数:
void COfflineDlg::OnBnClickedButtonOpenfile()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog file(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
_T("EXCEL文件(*.xls;*.xlsx)|*.xls;*.xlsx||"),AfxGetMainWnd());
if(file.DoModal()==IDOK)
{
strPath=file.GetPathName();
GetDlgItem(IDC_EDIT_FilePath)->SetWindowText(strPath);
}
}
strPath为CString类型的对话框成员变量,用于存储路径
6. 读取Excel中数据
添加一个读取数据按钮,按钮单击消息处理函数:
void COfflineDlg::OnBnClickedButtonReaddata()
{
// TODO: 在此添加控件通知处理程序代码
if("" == strPath)
{
theApp.ShowInfo(_T("请先选择文件"));
return;
}
GetDlgItem(IDC_BUTTON_ReadData)->EnableWindow(FALSE);
theApp.ShowInfo(_T("读取数据..."));
CApplication app; //Excel程序
CWorkbooks books; //工作簿集合
CWorkbook book; //工作簿
CWorksheets sheets; //工作表集合
CWorksheet sheet; //工作表
CRange range; //使用区域
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
if (!app.CreateDispatch(_T("Excel.Application")))
{
MessageBox(_T("Error!Creat Excel Application Server Fail!"));
exit(1);
}
books.AttachDispatch(app.get_Workbooks(),true);
book.AttachDispatch(books.Add(_variant_t(strPath)));//获取选择的Excel文件
sheets.AttachDispatch(book.get_Worksheets(),true);//获取文件中的所有sheet
sheet.AttachDispatch(sheets.get_Item(_variant_t("sheet1")),true);//获取sheet1区域
vstrCycleSets.clear();
vstrCmdSeque.clear();
vstrSendData.clear();
vstrExpectData.clear();
vstrTimeout.clear();
vstrCheck.clear();
vstrCycleCnt.clear();
CString str;
bool bExit = false;
for(int irow=2;!bExit;irow++)
{
for(int icolumn=1;icolumn<8;icolumn++)
{
range.AttachDispatch(sheet.get_Cells(),true);//获取sheet1所有的单元格,重置当前区域为A1
range.AttachDispatch(range.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal);//获取单元格
switch(icolumn)
{
case 1: str = range.get_Value2();
if(str.IsEmpty())
{
bExit = true;
break;
}
vstrCycleSets.push_back(str);
break;
case 2: str = range.get_Value2();
vstrCmdSeque.push_back(str);
break;
case 3: str = range.get_Value2();
str.Replace(" ", "");
vstrSendData.push_back(str);
break;
case 4: str = range.get_Value2();
str.Replace(" ", "");
vstrExpectData.push_back(str);
break;
case 5: str = range.get_Value2();
vstrTimeout.push_back(str);
break;
case 6: str = range.get_Value2();
vstrCheck.push_back(str);
break;
case 7: str = range.get_Value2();
vstrCycleCnt.push_back(str);
break;
default: ;
}
if(bExit)
{
break;
}
}
}
range.ReleaseDispatch();//释放对象
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch();
books.ReleaseDispatch();
app.ReleaseDispatch();
app.Quit();//退出Excel程序
if(!vstrCycleSets.empty())
{
theApp.ShowInfo(_T("读取数据成功"));
}
else
{
theApp.ShowInfo(_T("读取数据失败"));
}
GetDlgItem(IDC_BUTTON_ReadData)->EnableWindow(TRUE);
}
我读取的Excel表格数据列数固定为7,数据不确定所以行数不确定,第一行为表头,所以从第二行A2单元格开始读,通过Ai是否为空来判断数据是否读完。采用容器来保存数据对象比较方便,容器定义为对话框成员变量:
//存储Excel读取的数据
vector<CString> vstrCycleSets;
vector<CString> vstrCmdSeque;
vector<CString> vstrSendData;
vector<CString> vstrExpectData;
vector<CString> vstrTimeout;
vector<CString> vstrCheck;
vector<CString> vstrCycleCnt;
至此,就完成了从Excel中读取数据。
我们都是站在巨人的肩膀上,参考资料:
http://blog.csdn.net/u013507368/article/details/42143913
http://blog.csdn.net/jason___bourne/article/details/39643419
http://blog.csdn.net/fkzh2651/article/details/12185611
http://blog.csdn.net/tc297520702/article/details/20745457
http://blog.csdn.net/wangzhiyang925/article/details/37572695