http://blog.csdn.net/shuilan0066/article/details/7925023
示例---将所有单元格设置为文本格式:
- _Application app; //Excel应用程序接口
- Workbooks books; //工作薄集合
- _Workbook book; //工作薄
- Worksheets sheets; //工作表集合
- _Worksheet sheet; //工作表
- Range range; //Excel中针对单元格的操作都应先获取其对应的Range对象
- Font font;
- Range cols;
- /*
- COleVariant类为VARIANT数据类型的包装,在自动化程序中,通常都使用
- VARIANT数据类型进行参数传递。故下列程序中,函数参数都是通过COleVariant
- 类来转换了的。
- */
- //covOptional 可选参数的VARIANT类型
- COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
- if( !app.CreateDispatch(L"Excel.Application") ){
- this->MessageBox(L"无法创建Excel应用!");
- return;
- }
- //获取工作薄集合
- books=app.GetWorkbooks();
- //添加一个工作薄
- book=books.Add(covOptional);
- //获取工作表集合
- sheets=book.GetSheets();
- //获取第一个工作表
- sheet=sheets.GetItem(COleVariant((short)1));
- range.AttachDispatch(sheet.GetCells(),TRUE);//加载所有单元格
- range.SetNumberFormat(COleVariant(L"@")); //将单元格设置为文本类型
- //合并单元格
- //加载要合并的单元格
- range.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("D1"))),TRUE);
- range.Merge(COleVariant((long)0));
- range.AttachDispatch(sheet.GetCells(),TRUE);//加载所有单元格
- range.SetItem(COleVariant((long)1),COleVariant((long)1),COleVariant(_T("数学系研究生课程统计"))); //A1
- range.SetItem(COleVariant((long)2),COleVariant((long)1),COleVariant(_T("课程名"))); //A2
- range.SetItem(COleVariant((long)2),COleVariant((long)2),COleVariant(_T("课时"))); //B2
函数 SetNumberFormat() 用于设置单元格的格式,但是首先我们必须知道所有格式的标记。
文本类: |
数值类: |
日期类: |
百分比: |
详细请打开Excel2003,单元格右键,设置单元格格式,选一种格式,点自定义即可看到该格式的格式串;有的Excel格式串后有带”_”,在使用时,必须去掉。 |
设置篇 |
1 设置单元格的值
1) 选中指定单元格,使用SetValue设置值 CellName.Format(_T("A%d"),i);//单元格的名称 range.AttachDispatch(sheet.GetRange(COleVariant(CellName),COleVariant(CellName)));//加载单元格range.SetValue(COleVariant(subFileName));
CellName.Format(_T("C%d"),i);//单元格的名称 range.AttachDispatch(sheet.GetRange(COleVariant(CellName),COleVariant(CellName)));//加载单元格 range.SetValue(COleVariant((long)i));
2) 选中所有的单元格, 使用SetItem 设置指定单元格的值
range.AttachDispatch(sheet.GetCells(),TRUE);//加载所有单元格 //设置第I行 第1、2、3列的值 range.SetItem(COleVariant((long)(i)),COleVariant((long)1),COleVariant(subFileName)); //第一列 range.SetItem(COleVariant((long)(i)),COleVariant((long)2),COleVariant(unicodeStr)); //第二列 range.SetItem(COleVariant((long)(i)),COleVariant((long)3),COleVariant((long)i)); //第三列
|
2 设置行高列宽
选中某列 设置列宽 //获得所有列 range.AttachDispatch(sheet.GetColumns(),true); //设置第一列的列宽 Range cols cols.AttachDispatch(range.GetItem(COleVariant((long)1),vtMissing).pdispVal,TRUE); cols.SetColumnWidth(COleVariant((long)10)); //设置列宽
//设置第4列的列宽 cols.AttachDispatch(range.GetItem(COleVariant((long)4),vtMissing).pdispVal,TRUE); cols.SetColumnWidth(COleVariant((long)10)); //设置列宽
//设置列宽为自动适应 cols.AutoFit();
设置行高
Range rows;
range.AttachDispatch(sheet.GetRows(),TRUE); //选择第一行 rows.AttachDispatch(range.GetItem(COleVariant((long)1),vtMissing).pdispVal); //设置行高 rows.SetRowHeight(COleVariant((long)60));
注意: 行高列宽使用的单位不一样
|
3 设置单元格类型
range.AttachDispatch(sheet.GetCells(),TRUE);//加载所有单元格 range.SetNumberFormat(COleVariant(L"@")); //将单元格设置为文本类型
|
4 设置单元格字体
Font ft;
//设置第一列的字体 range.AttachDispatch(sheet.GetColumns(),true); range.AttachDispatch(range.GetItem(COleVariant((long)1),vtMissing).pdispVal,TRUE);
//字体作用范围 ft.AttachDispatch(range.GetFont()); ft.SetName(COleVariant(_T("宋体"))); ft.SetSize(COleVariant((long)48)); ft.SetBold(COleVariant((long)1));//粗体 ft.SetColorIndex(COleVariant((long)2));//设置字体颜色
|
5 设置单元格背景色
range.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("D1")))); //设置底色/ Interior it; it.AttachDispatch(range.GetInterior()); it.SetColorIndex(COleVariant((long)11));//标题底色
表格内容的底色 range.AttachDispatch(sheet.GetRange(COleVariant(_T("A2")),COleVariant(_T("D5")))); it.AttachDispatch(range.GetInterior()); it.SetColorIndex(COleVariant((long)15)); |
6 设置表格边框
1) range.AttachDispatch(sheet.GetRange(COleVariant(_T("A2")),COleVariant(_T("D5")))); //LineStyle=线型Weight=线宽ColorIndex=线的颜色(-4105为自动) range.BorderAround(COleVariant((long)1),(long)2,((long)-4105),vtMissing);//设置边框
2) range.AttachDispatch(sheet.GetRange(COleVariant(_T("A2")),COleVariant(_T("D5")))); _variant_t v1; //线型 _variant_t v2; //宽度 _variant_t v3; //颜色
v1.vt=VT_I2; v1.lVal=2; // 线的样式:- no line; 1-solid; 2-big dot;3-small dot;4-dash dot; 5-dash dot dot;
v2.vt=v1.vt; v2.lVal=3; // 线的粗细程度
v3.vt=v1.vt; v3.lVal=1; // 1-black;2-white;3-red;4-green;5-blue; 6-yellow; 7-pink;8-dark blue;
UnitRge.BorderAround(v1,v2,v3,vtMissing);//设置边框 |
7 合并单元格
1) //合并单元格 //加载要合并的单元格 range.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("D1"))),TRUE); range.Merge(COleVariant((long)0));
2) //将第一个单元格合并成行,列 range.AttachDispatch(sheet.GetCells()); unionRange.AttachDispatch(range.GetItem (COleVariant((long)1),COleVariant((long)1)).pdispVal ); //第一个单元格 unionRange.AttachDispatch(unionRange.GetResize(COleVariant((long)3),COleVariant((long)2))); //GetResize(3,2) 从第一个单元格开始合并行列的所有单元格 unionRange.Merge(COleVariant((long)0)); //合并单元格 |
8 设置单元格文本为自动换行 及排列方式
range.AttachDispatch(sheet.GetUsedRange());//加载已使用的单元格 range.SetWrapText(COleVariant((long)1));//设置单元格内的文本为自动换行
//设置齐方式为水平垂直居中 //水平对齐:默认=1,居中=-4108,左=-4131,右=-4152 //垂直对齐:默认=2,居中=-4108,左=-4160,右=-4107 range.SetHorizontalAlignment(COleVariant((long)-4108)); range.SetVerticalAlignment(COleVariant((long)-4108)); |
9 在单元格中插入公式
//选择A2单元格,插入一个公式"=RAND()*100000",并设置A2数字格式为货币形式 range=sheet.GetRange(COleVariant(L"A2"),COleVariant(L"A2")); range.SetFormula(COleVariant(L"=RAND()*100000")); range.SetNumberFormat(COleVariant(L"$0.00"));
|
10 在单元格中插入图片
Shapes shapes = sheet.GetShapes();// 从Sheet对象上获得一个Shapes range.AttachDispatch(sheet.GetRange(COleVariant(L"E5"),COleVariant(L"E5"))); // 获得Range对象,用来插入图片 shapes.AddPicture( L"d:\\pic.bmp " , false , true , (float)range.GetLeft().dblVal ,(float)range.GetTop().dblVal,(float)range.GetWidth().dblVal,(float)range.GetHeight().dblVal); ShapeRange sRange = shapes.GetRange(_variant_t(long(1))); sRange.SetHeight(float(30)); //在RANGE范围内 设置图片宽高 |
11 对选取的区域进行排序
#define xlAscending (long) 1 #define xlDescending (long) 2 #define vOpt COleVariant((long) DISP_E_PARAMNOTFOUND, VT_ERROR) #define xlHeader (long) 1 // 选取的区域有标题 #define xlNoHeader (long) 2 // 选取的区域无标题 一定要正确确定是否有标题,否则排序可能不成功 #define xlMatchCase COleVariant((long) 1) #define xlIgnoreCase COleVariant((long) 0) #define xlTopToBottom (long) 1 // 垂直方向进行排序 #define xlLeftToRight (long) 2 // 水平方向进行排序 #define xlPinYin (long) 1 // this is the default // 按字符的中文拼音进行排序 #define xlStroke (long) 2 // 按每个字符中的笔画数进行排序
VARIANT key1; // these lines set up first arg (key1) to sort V_VT(&key1) = VT_DISPATCH; // 排序时,关键字的vt设置为VT_DISPATCH V_DISPATCH(&key1) = sheet.GetRange(COleVariant(L"A1"),COleVariant(L"A1")); // 设置按哪个关键字进行排序 选择单元意为:按此列(或行)为主关键字进行排序 range=sheet.GetRange(COleVariant(L"A1"),COleVariant(CellName)); // 选择对哪些区域内的单元格进行排序 range.Sort(key1, xlAscending, vOpt, vOpt, xlAscending, vOpt,xlAscending,xlNoHeader,vOpt,xlIgnoreCase,xlTopToBottom,xlPinYin); //设置排序 无标题时一定要设置为xlNoHeader 否则不起作用 |
选择篇 |
1 选择单元格
//选择一个单元格 range.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("A1"))),TRUE);
//选择多个单元格 range.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("D1"))),TRUE);
//使用变量表示单元格 CString CellName; Int i=1;j=1; CellName.Format(_T(“%c%d”),j+64,i); //A–Z 65-90
//加载单元格 rnge.AttachDispatch(range.GetRange(COleVariant(CellName),COleVariant(CellName))); |
2 选择某行
1) //选择第一行 range.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("IV1"))),TRUE);
//选择前5行 range.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("IV5"))),TRUE);
2)先选择某行中的某个单元格,然后再选择整行 Range rows;
rows.AttachDispatch(sheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("A1"))),TRUE); rows=rows.GetEntireRow();
3)获得所有的行,然后再选择指定行 Range rows;
range.AttachDispatch(sheet.GetRows(),TRUE); //选择第一行 rows.AttachDispatch(range.GetItem(COleVariant((long)1),vtMissing).pdispVal); rows.SetRowHeight(COleVariant((long)60)); |
3 选择某一列
1) range.AttachDispatch(sheet.GetRange(COleVariant(L"A1"),COleVariant(L"A65536"))); //第一列
2)先选择某列中的某个单元格,然后再选择整列
range.AttachDispatch(sheet.GetRange(COleVariant(L"A1"),COleVariant(L"A1"))); //第一列 range=range.GetEntireColumn();
3)先获得所有列,然后再选择某一列 //获得所有列 range.AttachDispatch(sheet.GetColumns(),true); //选择第一列 range.AttachDispatch(range.GetItem(COleVariant((long)1),vtMissing).pdispVal,TRUE);
|
4 选择全部CELLS
range.AttachDispatch(sheet.GetCells(),TRUE);//加载所有单元格
|
5 选择已使用的单元格 range.AttachDispatch(sheet.GetUsedRange());//加载已使用的单元格
|
6 获取单元格的值 1) range=sheet.GetRange(COleVariant("A1"),COleVariant("A1")); COleVariant rValue;
2)
//读取第一个单元格的值 range.AttachDispatch(sheet.GetCells()); range.AttachDispatch(range.GetItem (COleVariant((long)1),COleVariant((long)1)).pdispVal );
vResult =range.GetValue();
CString str; if(vResult.vt == VT_BSTR) //字符串 { str=vResult.bstrVal; } else if (vResult.vt==VT_R8) //8字节的数字 { str.Format(L"%f",vResult.dblVal); } else if(vResult.vt==VT_DATE) //时间格式 { SYSTEMTIME st; VariantTimeToSystemTime((long)&vResult.date, &st); } else if(vResult.vt==VT_EMPTY) //单元格空的 { str=""; } |
读取xls文件示例 :
//变量定义 _Application app; //Excel应用程序接口 Workbooks books; //工作薄集合 _Workbook book; //工作薄 Worksheets sheets; //工作表集合 _Worksheet sheet; //工作表 Range range; //Excel中针对单元格的操作都应先获取其对应的Range对象 Font font; Range cols; Range iCell; LPDISPATCH lpDisp; COleVariant vResult; COleVariant covTrue((short)TRUE), covFalse((short)FALSE), covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
//初始化 if( !app.CreateDispatch(L"Excel.Application") ){ this->MessageBox(L"无法创建Excel应用!"); return; } app.SetVisible(TRUE); //可见 app.SetUserControl(TRUE); //用户可控制
//打开XLS文件 books.AttachDispatch(app.GetWorkbooks()); lpDisp = books.Open(L"d:\\3.xls", 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(); //已经使用的行数
range.AttachDispatch(usedRange.GetColumns()); long iColNum=range.GetCount(); //已经使用的列数
long iStartRow=usedRange.GetRow(); //已使用区域的起始行,从开始 long iStartCol=usedRange.GetColumn(); //已使用区域的起始列,从开始
|
//读取第一个单元格的值 range.AttachDispatch(sheet.GetCells()); range.AttachDispatch(range.GetItem (COleVariant((long)1),COleVariant((long)1)).pdispVal );
vResult =range.GetValue();
CString str; if(vResult.vt == VT_BSTR) //字符串 { str=vResult.bstrVal; } else if (vResult.vt==VT_R8) //8字节的数字 { str.Format(L"%f",vResult.dblVal); } else if(vResult.vt==VT_DATE) //时间格式 { SYSTEMTIME st; VariantTimeToSystemTime((long)&vResult.date, &st); } else if(vResult.vt==VT_EMPTY) //单元格空的 { str=""; }
|
//读取第一个单元格的对齐方式,数据类型:VT_I4 //读取水平对齐方式 range.AttachDispatch(sheet.GetCells()); iCell.AttachDispatch((range.GetItem (COleVariant(long(1)), COleVariant(long(1)))).pdispVal); vResult.lVal=0; vResult=iCell.GetHorizontalAlignment();
if(vResult.lVal!=0) { switch (vResult.lVal) { case 1: //默认 break; case -4108: //居中 break; case -4131 : //*左 break; case -4152 : //*右 break; }
}
//垂直对齐方式 iCell.AttachDispatch((range.GetItem (COleVariant(long(1)), COleVariant(long(1)))).pdispVal); vResult.lVal=0; vResult=iCell.GetVerticalAlignment(); if(vResult.lVal!=0) { switch (vResult.lVal) { case -4160 : //*上 break; case -4108 : //居中 break; case -4107 : //*下 break; }
}
|
//设置第一个单元格字体颜色:红色
range.AttachDispatch(sheet.GetCells()); range.AttachDispatch((range.GetItem (COleVariant(long(1)), COleVariant(long(1)))).pdispVal);
font.AttachDispatch(range.GetFont()); font.SetColor(COleVariant((long)0xFF0000));
|
//合并单元格的处理 //包括判断第一个单元格是否为合并单元格,以及将第一个单元格进行合并 Range unionRange; range.AttachDispatch(sheet.GetCells()); unionRange.AttachDispatch(range.GetItem (COleVariant((long)1),COleVariant((long)1)).pdispVal );
vResult=unionRange.GetMergeCells(); if(vResult.boolVal==-1) //是合并的单元格 { //合并单元格的行数 range.AttachDispatch (unionRange.GetRows ()); long iUnionRowNum=range.GetCount ();
//合并单元格的列数 range.AttachDispatch (unionRange.GetColumns ()); long iUnionColumnNum=range.GetCount ();
//合并区域的起始行,列 long iUnionStartRow=unionRange.GetRow(); //起始行,从开始 long iUnionStartCol=unionRange.GetColumn(); //起始列,从开始
} else if(vResult.boolVal==0) {
//不是合并的单元格 }
//将第一个单元格合并成行,列 range.AttachDispatch(sheet.GetCells()); unionRange.AttachDispatch(range.GetItem (COleVariant((long)1),COleVariant((long)1)).pdispVal ); //第一个单元格 unionRange.AttachDispatch(unionRange.GetResize(COleVariant((long)3),COleVariant((long)2))); //GetResize(3,2) 从第一个单元格开始合并行列的所有单元格 unionRange.Merge(COleVariant((long)0)); //合并单元格
|
//将文件保存为.xls book.SaveAs(COleVariant(L"C:\\2.xls"),covOptional,covOptional, covOptional,covOptional,covOptional,0, covOptional,covOptional,covOptional,covOptional);
book.Close (covOptional,COleVariant(L"d:\\3.xls"),covOptional); books.Close(); |
//释放对象(相当重要!) range.ReleaseDispatch(); cols.ReleaseDispatch(); sheet.ReleaseDispatch(); sheets.ReleaseDispatch(); book.ReleaseDispatch(); books.ReleaseDispatch(); //App一定要释放,否则程序结束后还会有一个Excel进程驻留在内存中,而且程序重复运行的时候会出错 app.ReleaseDispatch(); app.Quit(); |
一、加载
1、 在VC6.0里创建一个MFC工程
2、打开MFCClassWizard窗口(查看—>建立类向导),选择Automation,单击AddClass按钮,选择Froma type library...,弹出文件选择对话框,之后定位到C:\Program Files\MicrosoftOffice\OFFICE11\EXCEL.EXE,在生成类中添加所有的对象(其实添加需要的即可,为了简便,不出错保留了冗余),如下图。
3 、返回编辑器,查看工程文件,可发现多了 EXCEL.9H 及 EXCEL9.CPP 两个文件,拷贝出来,放在 VS2005 需要使用excel的工程文件中。
4. 打开stdafx.h头文件确保包含如下头文件:
#include <afxdisp.h>(这个一般有了)
#include "excel.h" (手动添加这个即可)
5. 打开TestExcel.cpp文件,修改CTestExcelApp::InitInstance(),加入如下代码:
if(!AfxOleInit() ){
AfxMessageBox("初始化Ole出错!");
return FALSE;
}
为保证编译时不产生重复定义错误(可以验证一下是否成功加载,没有也能正常执行),我编译时出现了很多“类重复定义”异常,打开excel.h文件,在文件开始位置加入如下代码:
#if !defined _HEAD_FILE_EXCEL9_
#define _HEAD_FILE_EXCEL9_
相应的,在文件末尾加入:
#endif
成功
Excel接口 | 导入类 | 头文件 | 说明 |
_Application | CApplicaton | Application.h | Excel应用程序。 |
Workbooks | CWorkbooks | Workbooks.h | 工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。 |
_Workbook | CWorkbook | Workbook.h | 单个工作簿。 |
Worksheets | CWorksheets | Worksheets.h | 单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。 |
_Worksheet | CWorksheet | Worksheet.h | 单个Sheet表格。 |
Range | CRange | Range.h | 一定数量的单元格,可对单元格进行单个或多个单元格进行操作。 |
在MSDN中,很少有excel方面的资料,但是在http://msdn.microsoft.com/zh-cn/ms348103.aspx中可以找到C#控制EXCEL方面的说明
二、操作EXCEL文件
1. 新建一个excel表,并填充两个单元格的实例
- void CTestExcelDlg::OnButton1()
- {
- //Workbooks—>Workbook —>Worksheets—>Worksheet —>Range
- _Application app; //Excel应用程序接口
- Workbooks books; //工作薄集合
- _Workbook book; //工作薄
- Worksheets sheets; //工作表集合
- _Worksheet sheet; //工作表
- Range range; //Excel中针对单元格的操作都应先获取其对应的Range对象
- Font font;
- Range cols;
- /*
- COleVariant类为VARIANT数据类型的包装,在自动化程序中,通常都使用
- VARIANT数据类型进行参数传递。故下列程序中,函数参数都是通过COleVariant
- 类来转换了的。
- */
- //covOptional 可选参数的VARIANT类型
- COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
- if( !app.CreateDispatch("Excel.Application") ){
- this->MessageBox("无法创建Excel应用!");
- return;
- }
- //获取工作薄集合
- books=app.GetWorkbooks();
- //添加一个工作薄
- book=books.Add(covOptional);
- //获取工作表集合
- sheets=book.GetSheets();
- //获取第一个工作表
- sheet=sheets.GetItem(COleVariant((short)1));
- //选择工作表中A1:A1单元格区域
- range=sheet.GetRange(COleVariant("A1"),COleVariant("A1"));
- //设置A1=HELLO EXCEL!"
- range.SetValue(COleVariant("HELLO EXCEL!"));
- //调整格式,设置粗体
- font=range.GetFont();
- font.SetBold(COleVariant((short)TRUE));
- //选择A2单元格,插入一个公式"=RAND()*100000",并设置A2数字格式为货币形
- 式
- range=sheet.GetRange(COleVariant("A2"),COleVariant("A2"));
- range.SetFormula(COleVariant("=RAND()*100000"));
- range.SetNumberFormat(COleVariant("$0.00"));
- //选择A:A列,设置宽度为自动适应
- cols=range.GetEntireColumn();
- cols.AutoFit();
- //显示Excel表格,并设置状态为用户可控制
- app.SetVisible(TRUE);
- app.SetUserControl(TRUE);
2. 打开一个已有的excel表格实例
- CString strPath;
- strPath += "C:\\template.xlt"; // 模板的路径
- CFileFind filefind;
- if( !filefind.FindFile( strPath ) )
- {
- AfxMessageBox( "没有找到模版文档,请其查找" );
- return;
- }
- LPDISPATCH lpDisp; //接口指针
- books=app.GetWorkbooks();
- lpDisp = books.Open(m_filepath,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional
- ); //与的不同,是个参数的,直接在后面加了两个covOptional成功了
- book.AttachDispatch(lpDisp);
3. 保存一个excel文件实例
- book.SetSaved(TRUE);
4. 另存一个excel文件实例
- book.SaveAs(COleVariant(m_filename),covOptional,
- covOptional,covOptional,
- covOptional,covOptional,(long)0,
- covOptional,covOptional,covOptional,
- covOptional,covOptional); //与的不同,是个参数的,直接在后面加了两个covOptional成功了
5. 释放一个excel文件实例
经试验证实,不释放第二次使用excel时会中断,放在类的析构里面有时调用不到,主动调用最保险。(有没有AttachDispatch()过都要释放,否则报错)
- //释放对象(相当重要!)
- Rang.ReleaseDispatch();
- sheet.ReleaseDispatch();
- sheets.ReleaseDispatch();
- book.ReleaseDispatch();
- books.ReleaseDispatch();
- //退出程序
- app.Quit();
- //m_ExlApp一定要释放,否则程序结束后还会有一个Excel进程驻留在内存中,而且程序重复运行的时候会出错
- app.ReleaseDispatch();
6. 修改一个excel单元格
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- range.SetValue2(COleVariant(value));
7. 取出一个excel单元格
实现Variant数据类型转换为CString类,这个只是一个示例,转换较为简单。
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- COleVariant rValue;
- rValue=COleVariant(range.GetValue2());
- rValue.ChangeType(VT_BSTR);
- return CString(rValue.bstrVal);
8. 还有释放问题是最重要的问题:
首先变量必须全释放,无论当初是否绑定过;
其次,程序释放和程序关闭的顺序必须是
- app.Quit();
- app.ReleaseDispatch();
- 如果顺如颠倒如下:
- app.ReleaseDispatch();
- app.Quit();
- 出现的后果是程序关闭后,excel进程仍然运行,所以无法正常打开程序曾经打开excel表格。
附录(操作类源码):
- #include "../Stdafx.h"
- #include "OptExcel.h"
- #include "excel.h"
- #include "comdef.h"
- _Application app;
- Workbooks books;
- _Workbook book;
- Worksheets sheets;
- _Worksheet sheet;
- Range range;
- Range cell;
- Font font;
- COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
- ///Function: COptExcel
- ///Description: 初始化函数,初始化中附加excel应用程序
- ///Call: app.CreateDispatch(_T("Excel.Application")
- COptExcel::COptExcel(void)
- {
- if (::CoInitialize( NULL ) == E_INVALIDARG)
- {
- AfxMessageBox(_T("初始化Com失败!"));
- return;
- }
- //验证office文件是否可以正确运行
- if( !app.CreateDispatch(_T("Excel.Application")) )
- {
- AfxMessageBox(_T("无法创建Excel应用!"));
- return;
- }
- //在程序执行文件路径名中,剪掉执行文件名,得到程序路径,追加模板文件名,得到模板完整路径
- }
- ///Function: ~COptExcel
- ///Description: 析构函数,释放对象,非常重要,不全部释放,占用内存,下
- /// 一次使用此类时会中断
- ///Call: ReleaseDispatch()
- COptExcel::~COptExcel(void)
- {
- books.ReleaseDispatch();
- book.ReleaseDispatch();
- sheets.ReleaseDispatch();
- sheet.ReleaseDispatch();
- range.ReleaseDispatch();
- font.ReleaseDispatch();
- cell.ReleaseDispatch();
- app.Quit();
- app.ReleaseDispatch();
- ::CoUninitialize();
- }
- ///Function: OpenExcelBook
- ///Description: 打开表名为filename的文件,注意,文件路径非自动生成,以后
- /// 考虑从下处理方法
- ///Call: GetAppPath()
- ///Input: CString filename 文件名
- bool COptExcel::OpenExcelBook(CString filename)
- {
- CFileFind filefind;
- if( !filefind.FindFile(filename) )
- {
- AfxMessageBox(_T("文件不存在"));
- return false;
- }
- LPDISPATCH lpDisp; //接口指针
- books=app.GetWorkbooks();
- lpDisp = books.Open(filename,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional
- ); //与office 2000的不同,是个参数的,直接在后面加了两个covOptional成功了
- book.AttachDispatch(lpDisp);
- sheets=book.GetSheets();
- sheet=sheets.GetItem(COleVariant((short)1)); //与的不同,是个参数的,直接在后面加了两个covOptional成功了
- return true;
- }
- void COptExcel::NewExcelBook()
- {
- books=app.GetWorkbooks();
- book=books.Add(covOptional);
- sheets=book.GetSheets();
- sheet=sheets.GetItem(COleVariant((short)1)); //与的不同,是个参数的,直接在后面加了两个covOptional成功了
- }
- ///Function: OpenExcelApp
- ///Description: 打开应用程序(要注意以后如何识别用户要打开的是哪个文件)
- void COptExcel::OpenExcelApp(void)
- {
- app.SetVisible(TRUE);
- app.SetUserControl(TRUE);
- }
- ///Function: SaveExcel
- ///Description: 用于打开数据文件,续存数据后直接保存
- void COptExcel::SaveExcel(void)
- {
- book.SetSaved(TRUE);
- }
- ///Function: SaveAsExcel
- ///Description: 保存excel文件
- void COptExcel::SaveAsExcel(CString filename)
- {
- book.SaveAs(COleVariant(filename),covOptional,
- covOptional,covOptional,
- covOptional,covOptional,(long)0,covOptional,covOptional,covOptional,
- covOptional,covOptional);
- }
- ///Function: SetCellValue
- ///Description: 修改单元格内的值
- ///Call: IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串
- ///Input: int row 单元格所在行
- /// int col 单元格所在列
- /// int Align 对齐方式默认为居中
- void COptExcel::SetCellValue(int row, int col,int Align)
- {
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- range.SetValue2(COleVariant(value));
- cell.AttachDispatch((range.GetItem (COleVariant(long(1)), COleVariant(long(1)))).pdispVal);
- cell.SetHorizontalAlignment(COleVariant((short)Align));
- }
- ///Function: GetCellValue
- ///Description: 得到的单元格中的值
- ///Call: IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串
- ///Input: int row 单元格所在行
- /// int col 单元格所在列
- ///Return: CString 单元格中的值
- CString COptExcel::GetCellValue(int row, int col)
- {
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- COleVariant rValue;
- rValue=COleVariant(range.GetValue2());
- rValue.ChangeType(VT_BSTR);
- return CString(rValue.bstrVal);
- }
- ///Function: SetRowHeight
- ///Description: 设置行高
- ///Call: IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串
- ///Input: int row 单元格所在行
- void COptExcel::SetRowHeight(int row, CString height)
- {
- int col = 1;
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- range.SetRowHeight(COleVariant(height));
- }
- ///Function: SetColumnWidth
- ///Description: 设置列宽
- ///Call: IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串
- ///Input: int col 要设置列宽的列
- /// CString 宽值
- void COptExcel::SetColumnWidth(int col,CString width)
- {
- int row = 1;
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- range.SetColumnWidth(COleVariant(width));
- }
- ///Function: SetRowHeight
- ///Description: 设置行高
- ///Call: IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串
- ///Input: int row 单元格所在行
- CString COptExcel::GetColumnWidth(int col)
- {
- int row = 1;
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- VARIANT width = range.GetColumnWidth();
- CString strwidth;
- strwidth.Format(CString((LPCSTR)(_bstr_t)(_variant_t)width));
- return strwidth;
- }
- ///Function: GetRowHeight
- ///Description: 设置行高
- ///Call: IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串
- ///Input: int row 要设置行高的行
- /// CString 宽值
- CString COptExcel::GetRowHeight(int row)
- {
- int col = 1;
- range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
- VARIANT height = range.GetRowHeight();
- CString strheight;
- strheight.Format(CString((LPCSTR)(_bstr_t)(_variant_t)height));
- return strheight;
- }
- ///Function: IndexToString
- ///Description: 得到的单元格在EXCEL中的定位名称字符串
- ///Input: int row 单元格所在行
- /// int col 单元格所在列
- ///Return: CString 单元格在EXCEL中的定位名称字符串
- CString COptExcel::IndexToString( int row, int col )
- {
- CString strResult;
- if( col > 26 )
- {
- strResult.Format(_T("%c%c%d"),'A' + (col-1)/26-1,'A' + (col-1)%26,row);
- }
- else
- {
- strResult.Format(_T("%c%d"), 'A' + (col-1)%26,row);
- }
- return strResult;
- }
- ///Function: LastLineIndex
- ///Description: 得到表格总第一个空行的索引
- ///Return: int 空行的索引号
- int COptExcel::LastLineIndex()
- {
- int i,j,flag=0;
- CString str;
- for(i=1;;i++)
- {
- flag = 0;
- //粗略统计,认为前列都没有数据即为空行
- for(j=1;j<=5;j++)
- {
- str.Format(_T("%s"),this->GetCellValue(i,j).Trim());
- if(str.Compare(_T(""))!=0)
- {
- flag = 1;
- break;
- }
- }
- if(flag==0)
- return i;
- }
- }
1. VS2005添加COM
Project-> addclass -> MFC -> MFC CLASS FROM TypeLib
选择:_Application/_Workbook/_Worksheet/Workbooks/Worksheet/Range
点击finish 后生成
CApplication.h
CWorkbook.h
CWorkbooks.h
CWorksheet.h
CWorksheets.h
CRange.h
删掉这些文件,导入excel9.h,excel9.cpp
- <strong>2. 在对应的程序文件中添加头文件#include "excel9.h"
- 在程序中启用COM服务库</strong>
- // 初始化 OLE 库
- if (!AfxOleInit())
- {
- AfxMessageBox(L"Could not initialize COM dll");
- return FALSE;
- }
- if (CoInitialize(NULL) != S_OK)
- return -1;
- <strong>下面是一个处理EXCEL的程序例子,可直接调用:</strong>
- void OnBnClickedButtonCaln()
- {
- // TODO: 在此添加控件通知处理程序代码
- // TODO: Add your control notification handler code here
- Range m_ExlRge;
- _Worksheet m_ExlSheet;
- Worksheets m_ExlSheets;
- _Workbook m_ExlBook;
- Workbooks m_ExlBooks;
- _Application m_ExlApp;
- //用m_ExlApp对象创建Excel2003进程
- if(!m_ExlApp.CreateDispatch(_T("Excel.Application"),NULL))
- {
- AfxMessageBox(_T("创建Excel服务失败!"));
- return;
- }
- //设置为可见
- m_ExlApp.SetVisible(TRUE);
- ///下面得到应用程序所在的路径///
- CString theAppPath,theAppName;
- // char Path[MAX_PATH];
- // GetModuleFileName(NULL,Path,MAX_PATH);//得到应用程序的全路径
- GetModuleFileName(NULL,_T("D:\\1.xlt"),MAX_PATH);//得到应用程序的全路径
- //theAppPath=(CString)Path;
- theAppPath=_T("D:\\1.xlt");
- theAppName=AfxGetApp()->m_pszAppName;
- theAppName+=_T(".exe");
- //把最后的文件名去掉
- int length1,length2;
- length1=theAppPath.GetLength();
- length2=theAppName.GetLength();
- theAppPath.Delete(length1-length2,length2);
- CString TempPath=_T("");
- //TempPath=theAppPath+_T("Template.xls");//EXCEL模板的路径
- TempPath=theAppPath;
- m_ExlBooks.AttachDispatch(m_ExlApp.GetWorkbooks(),TRUE);
- m_ExlBook.AttachDispatch(m_ExlBooks.Add((COleVariant)TempPath),TRUE);//加载EXCEL模板
- m_ExlSheets.AttachDispatch(m_ExlBook.GetSheets(),TRUE);//加载Sheet页面
- //添加新的Sheet页面
- m_ExlSheets.Add(vtMissing,vtMissing,COleVariant((long)1),vtMissing);
- //删除第二个Sheet页面
- m_ExlSheet.AttachDispatch(m_ExlSheets.GetItem(COleVariant((long)2)),TRUE);
- m_ExlSheet.Delete();
- //把第一个Sheet页面的名字改变为TestSheet
- m_ExlSheet.AttachDispatch(m_ExlSheets.GetItem(COleVariant((long)1)),TRUE);
- m_ExlSheet.SetName(_T("TestSheet"));
- ///合并第一行单元格A1至D1//
- //加载要合并的单元格
- m_ExlRge.AttachDispatch(m_ExlSheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("D1"))),TRUE);
- m_ExlRge.Merge(COleVariant((long)0));
- 设置表格内容
- m_ExlRge.AttachDispatch(m_ExlSheet.GetCells(),TRUE);//加载所有单元格
- m_ExlRge.SetItem(COleVariant((long)1),COleVariant((long)1),COleVariant(_T("数学系研究生课程统计")));
- m_ExlRge.SetItem(COleVariant((long)2),COleVariant((long)1),COleVariant(_T("课程名")));
- m_ExlRge.SetItem(COleVariant((long)2),COleVariant((long)2),COleVariant(_T("课时")));
- m_ExlRge.SetItem(COleVariant((long)2),COleVariant((long)3),COleVariant(_T("难度")));
- m_ExlRge.SetItem(COleVariant((long)2),COleVariant((long)4),COleVariant(_T("教学方式")));
- m_ExlRge.SetItem(COleVariant((long)3),COleVariant((long)1),COleVariant(_T("泛函分析")));
- m_ExlRge.SetItem(COleVariant((long)3),COleVariant((long)2),COleVariant(_T("60")));
- m_ExlRge.SetItem(COleVariant((long)3),COleVariant((long)3),COleVariant(_T("普通")));
- m_ExlRge.SetItem(COleVariant((long)3),COleVariant((long)4),COleVariant(_T("老师讲课")));
- m_ExlRge.SetItem(COleVariant((long)4),COleVariant((long)1),COleVariant(_T("微分流形")));
- m_ExlRge.SetItem(COleVariant((long)4),COleVariant((long)2),COleVariant(_T("40")));
- m_ExlRge.SetItem(COleVariant((long)4),COleVariant((long)3),COleVariant(_T("变态难")));
- m_ExlRge.SetItem(COleVariant((long)4),COleVariant((long)4),COleVariant(_T("自学")));
- m_ExlRge.SetItem(COleVariant((long)5),COleVariant((long)1),COleVariant(_T("二阶椭圆型方程与方程组")));
- m_ExlRge.SetItem(COleVariant((long)5),COleVariant((long)2),COleVariant(_T("60")));
- m_ExlRge.SetItem(COleVariant((long)5),COleVariant((long)3),COleVariant(_T("很难")));
- m_ExlRge.SetItem(COleVariant((long)5),COleVariant((long)4),COleVariant(_T("讨论")));
- m_ExlRge.AttachDispatch(m_ExlSheet.GetUsedRange());//加载已使用的单元格
- m_ExlRge.SetWrapText(COleVariant((long)1));//设置单元格内的文本为自动换行
- //设置齐方式为水平垂直居中
- //水平对齐:默认=1,居中=-4108,左=-4131,右=-4152
- //垂直对齐:默认=2,居中=-4108,左=-4160,右=-4107
- m_ExlRge.SetHorizontalAlignment(COleVariant((long)-4108));
- m_ExlRge.SetVerticalAlignment(COleVariant((long)-4108));
- ///设置整体的字体、字号及颜色//
- Font ft;
- ft.AttachDispatch(m_ExlRge.GetFont());
- ft.SetName(COleVariant(_T("宋体")));//字体
- ft.SetColorIndex(COleVariant((long)11));//字的颜色
- ft.SetSize(COleVariant((long)12));//字号
- ///设置标题字体及颜色//
- m_ExlRge.AttachDispatch(m_ExlSheet.GetRange(COleVariant(_T("A1")),COleVariant(_T("D1"))));
- ft.AttachDispatch(m_ExlRge.GetFont());
- ft.SetBold(COleVariant((long)1));//粗体
- ft.SetSize(COleVariant((long)13));
- ft.SetColorIndex(COleVariant((long)2));
- // CellFormat cf;
- // cf.AttachDispatch(m_ExlRge.GetCells());
- //设置底色/
- Interior it;
- it.AttachDispatch(m_ExlRge.GetInterior());
- it.SetColorIndex(COleVariant((long)11));//标题底色
- 表格内容的底色
- m_ExlRge.AttachDispatch(m_ExlSheet.GetRange(COleVariant(_T("A2")),COleVariant(_T("D5"))));
- it.AttachDispatch(m_ExlRge.GetInterior());
- it.SetColorIndex(COleVariant((long)15));
- //为表格设置边框/
- Range UnitRge;
- CString CellName;
- for(int i=1;i<=4;i++)
- {
- for(int j=1;j<=4;j++)
- {
- CellName.Format(_T("%c%d"),j+64,i);//单元格的名称
- UnitRge.AttachDispatch(m_ExlRge.GetRange(COleVariant(CellName),COleVariant(CellName)));//加载单元格
- //LineStyle=线型 Weight=线宽 ColorIndex=线的颜色(-4105为自动)
- UnitRge.BorderAround(COleVariant((long)1),(long)2,((long)-4105),vtMissing);//设置边框
- }
- }
- //释放对象(相当重要!)
- m_ExlRge.ReleaseDispatch();
- m_ExlSheet.ReleaseDispatch();
- m_ExlSheets.ReleaseDispatch();
- m_ExlBook.ReleaseDispatch();
- m_ExlBooks.ReleaseDispatch();
- //m_ExlApp一定要释放,否则程序结束后还会有一个Excel进程驻留在内存中,而且程序重复运行的时候会出错
- m_ExlApp.ReleaseDispatch();
- //退出程序 m_ExlApp.Quit();
- }