因为用ODBC连接Excel,不能处理任意创建的Excel文件,于是我决定另写一个版本,用Automation技术。其实就是用Excel自己的类库,进行操作。我在实习的时候,用过这种方法,开发AutoCAD图纸签名程序。
说Automation技术,只不过是随着别人叫而已,具体是什么东西,我还不太清楚。慢慢理解吧。
程序参考自:http://blog.youkuaiyun.com/bodybo/archive/2009/05/27/4219242.aspx
开发过程如下:
还是用支持MFC的控制台程序来试验
1、创建一个支持MFC的控制台工程。工程名为ExcelTest。
2、加入Excel组件。菜单选择View ->ClassWizard,添加Excel类库
进入到Office的安装目录:.
文件类型选择为All Files(*.*)。选择EXCEL.EXE:
点“打开”,然后选择要引入的类,_Application、Worksheets、_Worksheet、Workbooks、_Workbook、Range这五个类(其中Worksheets不好找,可以先在键盘上按“W”键,找到Worksheets,然后找到其余几个类,按住ctrl键,将其选中)
点OK按钮,将这几个类引入到工程中。这时工程里面就会多了两个文件,Excel.h和Excel.cpp,以及引入的六个类:
3、在ExcelTest.cpp中引入Excel头文件。
#include "excel.h"
4、在_tmain()函数前面声明一个函数,用来处理Excel。
void CalculateExcel(CString strFile);
5、编写CalculateExcel()函数。
void CalculateExcel(CString strFile)
{
_Application app;
_Workbook book;
_Worksheet sheet;
Workbooks books;
Worksheets sheets;
Range range;
LPDISPATCH lpDisp;
COleVariant vResult;
COleVariant covTrue((short)TRUE);
COleVariant covFalse((short)FALSE);
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
//创建Excel服务器(启动Excel)
if(!app.CreateDispatch("Excel.Application"))
{
AfxMessageBox("无法启动Excel服务器!");
return;
}
app.SetVisible(FALSE); //使Excel不可见
//打开demo.xls
books.AttachDispatch(app.GetWorkbooks());
lpDisp = books.Open(strFile,
covOptional, covFalse, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional);
//得到Workbook
book.AttachDispatch(lpDisp);
//得到Worksheets
sheets.AttachDispatch(book.GetWorksheets());
//得到当前活跃sheet
//如果有单元格正处于编辑状态中,此操作不能返回,会一直等待
lpDisp=book.GetActiveSheet();
sheet.AttachDispatch(lpDisp);
//读取已经使用区域的信息,包括已经使用的行数、列数、起始行、起始列
Range usedRange;
usedRange.AttachDispatch(sheet.GetUsedRange());
range.AttachDispatch(usedRange.GetRows());
long iRowNum=range.GetCount(); //已经使用的行数
long iStartRow=usedRange.GetRow(); //已使用区域的起始行,从1开始
//读取每一行的内容
CString strValue1; // 第一个单元格内容
double dValue2; // 第二个单元格内容
CString strTmp; // 临时存储字符串
double dResult = 0.0; // 计算结果
double dRowIndex; // 目标行
for (int i=iStartRow; i<=iRowNum; i++)
{
// 得到本行第一个单元格的内容(字符串)
range.AttachDispatch(usedRange.GetItem(COleVariant((long)i), COleVariant((long)1)).pdispVal);
vResult = range.GetText();
strValue1 = vResult.bstrVal;
// 得到本行第二个单元格的内容(double)
range.AttachDispatch(usedRange.GetItem(COleVariant((long)i), COleVariant((long)2)).pdispVal);
vResult = range.GetText();
strTmp = vResult.bstrVal;
dValue2 = atof(strTmp);
// 判断本行是不是应该写入计算结果的那一行
if (strValue1 == "call price")
{
dRowIndex = i;
break;
}
strTmp.Format("%d\t%s\t\t%.2f\n", i, strValue1, dValue2);
printf(strTmp);
// 求和
dResult += dValue2;
}
strTmp.Format("\nthe result:\n%s\t%.2f\n", strValue1, dResult);
printf(strTmp);
// 写入计算结果
usedRange.SetItem(COleVariant((long)dRowIndex), COleVariant((long)2), COleVariant((double)dResult));
// 保存
book.Save();
//关闭所有的book,退出Excel
book.Close (covOptional,COleVariant(strFile),covOptional);
books.Close();
app.Quit();
}
6、然后在_tmain()函数中添加如下代码,来调用CalculateExcel函数:
::CoInitialize(NULL);
//初始化COM的动态连接库
if(!AfxOleInit())
{
AfxMessageBox("无法初始化COM的动态连接库!");
return 0;
}
char szCurrPath[300];
::GetCurrentDirectoryA(300, szCurrPath);// 得到程序所在目录
CalculateExcel((CString)szCurrPath + "\\demo.xls");
::CoUninitialize();
7、在工程根目录下,新建一个Excel文件,命名为demo.xls,随便添加几个数据,但是要有一个单元格为call price,以便将计算结果写入到该单元格后面:
8、编译、执行程序