前几天要做一个项目,需要读取Excel中的数据。从网上查资料发现,主要是有两种方式。一是把Excel表当成数据库使用ODBC读写,这样操作起来就跟操作Access数据库似的。但这种方式效率比较低。另一种方法是OLE技术(Object Linking and Embedding,对象连接与嵌入)。OLE是一种面向对象的技术,利用这种技术可开发可重复使用的软件组件(COM)。本文主要介绍使用OLE技术对Excel读写的方法。
本文中使用的环境是Windows XP,VS2008,Excel2007。
1) 在你建立的VC工程中点击“项目”->“添加类”->“TypeLib中的MFC类”->点击“确定”
2) 这时会出现一个“从类型库添加类向导”对话框,选中“文件”选项,然后选择文件位置:C:\Program Files\Microsoft Office\Office12\EXCEL.EXE 将接口列表中的_Application,_Workbook,_Worksheet,Range,Ranges,Workbooks,Worksheets等接口添加到右侧。点击“完成”。
3) 给VC工程添加一个新的C++类,命名为CExcel。在excel.h文件中添加以下头文件:
#include "CApplication.h"
#include "CRange.h"
#include "CRanges.h"
#include "CWorkbook.h"
#include "CWorkbooks.h"
#include "CWorksheet.h"
#include "CWorksheets.h"
4)依次打开以上添加的7个头文件,把每个文件中的#import "C:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace 这一行注释掉(否则后面会报错)。另外要把CRange.h文件中第335行VARIANT DialogBox()中的DialogBox换个名字,例如可以换成ExcelDialogBox()。
至此准备工作完毕。首先创建一个Excel服务器,然后就是根据各个头文件中提供的函数,打开Excel,获取workbook,获取worksheet,选择某个单元格,获取该单元格的值。或者是选择某一片区域(Range)然后将该区域内的值输出在一个二维数组里。
//创建操作EXCEL的常用对象
CApplication ExcelApp;
CWorkbooks books;
CWorkbook book;
CWorksheets sheets;
CWorksheet sheet;
CRange range;
LPDISPATCH lpDisp;
lpDisp=NULL;
//创建Excel 服务器(启动Excel)
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
{
AfxMessageBox(_T("启动Excel服务器失败!"));
//return -1;
}
ExcelApp.put_Visible(TRUE);
ExcelApp.put_UserControl(FALSE);
/*得到工作簿容器*/
books.AttachDispatch(ExcelApp.get_Workbooks());
CString strBookPath = _T("C:\\Users\\fan\\Documents\\Tencent Files\\117083090\\FileRecv\\2012.xls");
/*打开一个工作簿*/
lpDisp = books.Open(strBookPath,
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
vtMissing, vtMissing, vtMissing, vtMissing);
book.AttachDispatch(lpDisp);
/*得到工作簿中的Sheet的容器*/
sheets.AttachDispatch(book.get_Sheets());
int sheetcount=sheets.get_Count();
for (int n=1;n<=sheetcount-1;n++)
{
lpDisp = sheets.get_Item(COleVariant((short)n));
sheet.AttachDispatch(lpDisp);
CString sheetname=sheet.get_Name();
//读取已经使用区域的信息,包括已经使用的行数、列数、起始行、起始列
range.AttachDispatch(sheet.get_UsedRange());
range.AttachDispatch(range.get_Rows());
long iRowNum = range.get_Count();
range.AttachDispatch(range.get_Columns());
long iColNum = range.get_Count();
long iStartRow = range.get_Row();
long iStartCol = range.get_Column();
}
/*释放资源*/
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch();
books.ReleaseDispatch();
ExcelApp.Quit();
ExcelApp.ReleaseDispatch();
//获取指定单元格的内容
CString getCellString(long irow, long icolumn)
{
COleVariant vResult ;
CString str;
COleVariant value;
_variant_t varRow(irow);
_variant_t varCol(icolumn);
range.AttachDispatch(sheet.get_Cells(),TRUE);
value=range.get_Item(varRow,varCol); //返回的类型是VT_DISPATCH 这是一个指针
range.AttachDispatch(value.pdispVal,TRUE);
vResult =range.get_Value2();
range.ReleaseDispatch();
//字符串
if(vResult.vt == VT_BSTR)
{
str=vResult.bstrVal;
}
//整数
else if (vResult.vt==VT_INT)
{
str.Format(_T("%d"),vResult.pintVal);
}
//8字节的数字
else if (vResult.vt==VT_R8)
{
str.Format(_T("%0.0f"),vResult.dblVal);
}
//时间格式
else if(vResult.vt==VT_DATE)
{
SYSTEMTIME st;
VariantTimeToSystemTime(vResult.date, &st);
CTime tm(st);
str=tm.Format("%Y-%m-%d");
}
//单元格空的
else if(vResult.vt==VT_EMPTY)
{
str="";
}
return str;
}