Excel和vs2010 的连接(续)
通过VS实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文通过OLE/COM实现对Excel表格的操作。
1. 建立MFC工程,MDI(基于对话框),其他默认即可。
2. 操作Excel文件的配置:
a.项目->添加类->TypeLib中的MFC类,导入Excel.exe,一般都在C:\Program Files\Microsoft Office\Office14\EXCEL.EXE路径下(即选择你的office安装路径下的excel.exe加入)。
b.选中以下几项_Application,_WorkSheet,_WorkBook,WorkSheets,WorkBooks,Range导入,导入后自动在工程中添加CApplication, CWorkSheet, CWorkBook, CWorkSheets, CWorkBooks, CRange这些类。
c.把这些类的头文件中的第一句话 #import ".......EXCEL.EXE" nonamespace 删除;这行代码的作用是导入Excel整个类型库到工程中。
d.引入之后如果编译遇到错误,Not enough actual parameters for macro 'DialogBoxW'。解决方法是在CRange类中,DialogBox()前面添加下划线变成_DialogBox()。
VARIANT _DialogBox() { VARIANT result; InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT, (void*)&result, NULL); return result; }
3.操作excel文件
在XXX.cpp头文件下添加:
#include "CApplication.h" #include "CRange.h" #include "CWorkbook.h" #include "CWorkbooks.h" #include "CWorksheet.h" #include "CWorksheets.h"
在对话框中添加“新建”按钮,编写事件响应函数如下:
void Cvs_excelDlg::OnBnClickedNew() { // TODO: 在此添加控件通知处理程序代码 //Excel初始化 CApplication app; CWorkbooks books; CWorkbook book; CWorksheets sheets; CWorksheet sheet; CRange range; LPDISPATCH lpDisp; //COleVariant vResult; COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); if(!app.CreateDispatch("Excel.Application")) { AfxMessageBox("无法启动Excel服务器!"); return; } books.AttachDispatch(app.get_Workbooks(),TRUE); book=books.Add(covOptional); sheets.AttachDispatch(book.get_Worksheets(),TRUE); sheet=sheets.get_Item(COleVariant((short)1)); range.AttachDispatch(sheet.get_Cells()); //Excel文件头 range.put_Item(_variant_t(1),_variant_t(1), _variant_t("序号")); range.put_Item(_variant_t(1),_variant_t(2), _variant_t("识别时间")); range.put_Item(_variant_t(1),_variant_t(3), _variant_t("原始图片文件名称")); range.put_Item(_variant_t(1),_variant_t(4), _variant_t("识别后电话号码")); //Excel宽度 range = sheet.get_Range(COleVariant(_T("A1")),COleVariant(_T("A1"))); range.put_ColumnWidth(_variant_t((long)8)); range = sheet.get_Range(COleVariant(_T("B1")),COleVariant(_T("B1"))); range.put_ColumnWidth(_variant_t((long)19)); range = sheet.get_Range(COleVariant(_T("C1")),COleVariant(_T("C1"))); range.put_ColumnWidth(_variant_t((long)25)); range = sheet.get_Range(COleVariant(_T("D1")),COleVariant(_T("D1"))); range.put_ColumnWidth(_variant_t((long)17)); //时间 CTime tm=CTime::GetCurrentTime(); CString sttime=tm.Format("%Y/%m/%d"); //保存结果至EXCEL range.AttachDispatch(sheet.get_Cells()); range.put_NumberFormat(COleVariant("@")); range.put_Item(_variant_t(2),_variant_t(1), _variant_t("1")); range.put_Item(_variant_t(2),_variant_t(2), _variant_t(sttime)); range.put_Item(_variant_t(2),_variant_t(3), _variant_t("C:\\test")); range.put_Item(_variant_t(2),_variant_t(4), _variant_t("8810769206")); //保存Excel文件 book.SaveCopyAs(COleVariant("C:\\test.xlsx")); book.put_Saved(true); books.Close(); //释放对象 range.ReleaseDispatch(); sheet.ReleaseDispatch(); sheets.ReleaseDispatch(); book.ReleaseDispatch(); books.ReleaseDispatch(); app.Quit(); // 退出 app.ReleaseDispatch(); }
在对话框中添加“打开”按钮,编写事件响应函数如下:
void Cvs_excelDlg::OnBnClickedOpen() { // TODO: 在此添加控件通知处理程序代码 CApplication app; CWorkbooks books; CWorkbook book; CWorksheets sheets; CWorksheet sheet; CRange range; LPDISPATCH lpDisp; COleVariant vResult; COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); if(!app.CreateDispatch("Excel.Application")) { AfxMessageBox("无法启动Excel服务器!"); return; } books.AttachDispatch(app.get_Workbooks());lpDisp = books.Open("C:\\test.xlsx",covOptional, covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional,covOptional);
//得到Workbook book.AttachDispatch(lpDisp); //得到Worksheets sheets.AttachDispatch(book.get_Worksheets()); //得到当前活跃sheet //如果有单元格正处于编辑状态中,此操作不能返回,会一直等待 //lpDisp=book.get_ActiveSheet(); //sheet.AttachDispatch(lpDisp); sheet=sheets.get_Item(COleVariant((short)1)); //读取第一个单元格的值 range.AttachDispatch(sheet.get_Cells()); range.AttachDispatch(range.get_Item (COleVariant((long)2),COleVariant((long)1)).pdispVal ); vResult =range.get_Value2(); CString str; if(vResult.vt == VT_BSTR) //字符串 { str=vResult.bstrVal; } else if (vResult.vt==VT_R8) //8字节的数字 { str.Format("%f",vResult.dblVal); } /*else if(vResult.vt==VT_DATE) //时间格式 { SYSTEMTIME st; VariantTimeToSystemTime(&vResult.date, &st); } else if(vResult.vt==VT_EMPTY) //单元格空的 { str=""; }*/ books.Close(); //释放对象 range.ReleaseDispatch(); sheet.ReleaseDispatch(); sheets.ReleaseDispatch(); book.ReleaseDispatch(); books.ReleaseDispatch(); app.Quit(); // 退出
app.ReleaseDispatch();
MessageBox(str);
}
这样便实现了Excel的读写操作,具体功能比较简单,详见代码吧。
4.如果你想要的到更多的功能实现可以参考:http://blog.csdn.net/fullsail/article/details/8449448。它对Excel的操作做了进一步的类封装,比较完善。