在Visual C++ 中调读取和控制Excel详细教程

在Visual C++ 中调读取和控制Excel详细教程
在Visual C++ 中调读取和控制Excel详细教程

在Visual C++ 中调用Excel 2000

程蓬

在开发软件时,经常要将数据输出到Excel 2000中,在Excel 2000中对该数据进行进一步地格式化处理或进行计算处理。在Visual Basic中处理起来较简单,Excel 2000的VB编程帮助中有较为详细的介绍。在Visual C++中如何进行处理了?利用Excel 2000的ActiveX Automate功能,处理起来同VB中类似。但要注意以下几点:

对于对象的属性值的读取或赋值,需要用GetProperty()或SetProperty(NewValue)函数,不能象VB 中直接通过属性名称取值或赋值。例如:Worksheet.GetCount(), Worksheet.SetName(“Sheet1”)。

对集合对象中的成员对象的引用,必须使用集合对象的GetItem()函数。例如:Worksheets.GetItem(ColeVariant((long)1))或Worksheets.GetItem(ColeVariant(“Sheet1”))取得第一个工作表。

在COM接口中,时常用到V ariant,BSTR,SafeArray数据类型。Variant数据类型是一个联合,可表示几乎所有的类型的数据,具体用法见MSDN中的相关介绍,类_variant_t是对V ARIANT数据类型的封装。在Excel 2000的VB编程帮助中,如果提到某函数或属性需要一个值,该值的数据类型通常是Variant,在封装Excel 2000对象的类定义中,说明了具体需要的数据类型。BSTR是一个包括了字符串和字符串长度的数据结构,类_bstr_t是对BSTR数据类型的封装。在Excel 2000的VB编程帮助中提到的字符串通常指BSTR。具体函数参数或属性的数据类型,见封装该对象的类的定义。SafeArray是一个包括数组和数组边界的结构,数组边界外的内容不允许访问。在Excel 2000的VB编程帮助中提到的数组是指SafeArray。关于SafeArray的处理,请见MSDN的相关帮助。

对于缺省参数和缺省值。在VB中,函数的参数可以空缺,在VC++中不允许,必须将所有的参数填写完全。如果你希望指定某个参数为缺省值,根据参数数据类型的不同,可指定不同的缺省值。当参数数据类型为字符串时,可以用长度为0的字符串。如果参数是Variant类型,可用常量vtMissing,该常量在comdef.h中定义。也可用_variant_t(DISP_E_PARAMNOTFOUND, VT_ERROR)产生一个Variant对象。

Excel对象中的集合对象有时包括的子对象是不一定的,例如:Range对象,可以表示Cell的集合,也可以表示Column的集合或Row的集合,Range.GetItem(1)可以返回Cell或Column或Row对象。

对对象的引用或传递对象,使用IDispatch类对象,有时利用Variant对IDispatch进行包装。

以下是一段源程序,演示如何启动Excel 2000,利用一个模板文件产生一个新文档,在该文档的”Sheet1”工作表的第一个单元中填写一段文字,设置第一列的列宽,然后调用一个模板中的宏,执行一段程序,最后打印预览该Excel文档。模板文件名称:MyTemplate.xlt。程序在Visual C++ 6.0 sp4,Windows 2000 Professional sp-1下调试通过。

首先利用Visual C++ 6.0,建立一个MFC基于对话框的工程项目,共享DLL,Win32平台。工程名称ExcelTest。在主对话框中加入一个按钮,

ID IDC_EXCELTEST

Caption Test Excel

双击该按钮,增加成员函数void CExcelTestDlg::OnExceltest()。

在BOOL CExcelTestApp::InitInstance()中,dlg.DoModal();之前增加代码:

if (CoInitialize(NULL)!=0)

{

AfxMessageBox("初始化COM支持库失败!");

exit(1);

}

在return FALSE; 语句前,加入:

CoUninitialize();

选择Menu->View->ClassWizade,打开ClassWizade窗口,选择Add Class->From a type library,选择D:\Program Files\Microsoft Office\office\Excel9.OLB(D:\Program Files\Microsoft Office\是本机上Microsoft Office 2000的安装目录,可根据个人机器上的实际安装目录修改)。选择_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range,加入新类,分别为_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range,头文件Excel9.h,源文件Excel9.cpp。

在ExcelTestDlg.cpp文件的头部,#include "ExcelTestDlg.h"语句之下,增加:

#include "comdef.h"

#include "Excel9.h"

在void CExcelTestDlg::OnExceltest() 函数中增加如下代码:

void CExcelTestDlg::OnExceltest()

{

_Application ExcelApp;

Workbooks wbsMyBooks;

_Workbook wbMyBook;

Worksheets wssMysheets;

_Worksheet wsMysheet;

Range rgMyRge;

//创建Excel 2000服务器(启动Excel)

if (!ExcelApp.CreateDispatch("Excel.Application",NULL))

{

AfxMessageBox("创建Excel服务失败!");

exit(1);

}

//利用模板文件建立新文档

wbsMyBooks.AttachDispatch(ExcelApp.GetWorkbooks(),true);

wbMyBook.AttachDispatch(wbsMyBooks.Add(_variant_t("g:\\exceltest\\MyTemplate.xlt")));

//得到Worksheets

wssMysheets.AttachDispatch(wbMyBook.GetWorksheets(),true);

//得到sheet1

wsMysheet.AttachDispatch(wssMysheets.GetItem(_variant_t("sheet1")),true);

//得到全部Cells,此时,rgMyRge是cells的集合

rgMyRge.AttachDispatch(wsMysheet.GetCells(),true);

//设置1行1列的单元的值

rgMyRge.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t("This Is A Excel Test Program!")); //得到所有的列

rgMyRge.AttachDispatch(wsMysheet.GetColumns(),true);

//得到第一列

rgMyRge.AttachDispatch(rgMyRge.GetItem(_variant_t((long)1),vtMissing).pdispVal,true);

//设置列宽

rgMyRge.SetColumnWidth(_variant_t((long)200));

//调用模板中预先存放的宏

ExcelApp.Run(_variant_t("CopyRow"),_variant_t((long)10),vtMissing,vtMissing,

vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,

vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,

vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,

vtMissing,vtMissing,vtMissing,vtMissing,vtMissing,vtMissing);

//打印预览

wbMyBook.SetSaved(true);

ExcelApp.SetVisible(true);

wbMyBook.PrintPreview(_variant_t(false));

//释放对象

rgMyRge.ReleaseDispatch();

wsMysheet.ReleaseDispatch();

wssMysheets.ReleaseDispatch();

wbMyBook.ReleaseDispatch();

wbsMyBooks.ReleaseDispatch();

ExcelApp.ReleaseDispatch();

}

添加完以上程序后,可运行看结果。

例子:

如今Excel是越来越重要了,在我们自己开发的程序中不免要和Excel打交道了。利用Automation技术,我们可以在不去了解数据库的情况下玩转Excel,而且你会发现一切竟如此轻松!

好了,咱们开始吧,我不喜欢用长篇累牍的代码来故弄玄虚,所以下面的代码都是切中要害的片段,总体上是个连贯的过程,包括启动Excel,读取数据,写入数据,以及最后的关闭Excel,其中还包括了很多人感兴趣的合并单元格的处理。

特别说明以下代码需要MFC的支持,而且工程中还要包含EXCEL2000的定义文件:EXCEL9.H,EXCEL9.CPP

******************************************************************************

//*****

//变量定义

_Application app;

Workbooks books;

_Workbook book;

Worksheets sheets;

_Worksheet sheet;

Range range;

Range iCell;

LPDISPATCH lpDisp;

COleVariant vResult;

COleVariant

covTrue((short)TRUE),

covFalse((short)FALSE),

covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

//*****

//初始化COM的动态连接库

if(!AfxOleInit())

{

AfxMessageBox("无法初始化COM的动态连接库!");

return ;

}

//*****

//创建Excel 2000服务器(启动Excel)

if(!app.CreateDispatch("Excel.Application"))

AfxMessageBox("无法启动Excel服务器!");

return;

}

app.SetVisible(TRUE); //使Excel可见

app.SetUserControl(TRUE); //允许其它用户控制Excel

//*****

//打开c:\1.xls

books.AttachDispatch(app.GetWorkbooks());

lpDisp = books.Open("C:\\1.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(); //已使用区域的起始行,从1开始

long iStartCol=usedRange.GetColumn(); //已使用区域的起始列,从1开始

//*****

//读取第一个单元格的值

range.AttachDispatch(sheet.GetCells());

range.AttachDispatch(range.GetItem (COleVariant((long)1),COleVariant((long)1)).pdispVal ); COleVariant vResult =range.GetValue();

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="";

}

//*****

//读取第一个单元格的对齐方式,数据类型: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;

}

}

//*****

//设置第一个单元格的值"HI,EXCEL!"

range.SetItem(COleVariant(1),COleVariant(1),COleVariant("HI,EXCEL!"));

//*****

//设置第一个单元格字体颜色:红色

Font font;

range.AttachDispatch(sheet.GetCells());

range.AttachDispatch((range.GetItem (COleVariant(long(1)), COleVariant(long(1)))).pdispVal); 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(); //起始行,从1开始

long iUnionStartCol=unionRange.GetColumn(); //起始列,从1开始

}

else if(vResult.boolVal==0)

{//不是合并的单元格}

//将第一个单元格合并成2行,3列

range.AttachDispatch(sheet.GetCells());

unionRange.AttachDispatch(range.GetItem (COleVariant((long)1),COleVariant((long)1)).pdispVal ); unionRange.AttachDispatch(unionRange.GetResize(COleVariant((long)2),COleVariant((long)3))); unionRange.Merge(COleVariant((long)0)); //合并单元格

//*****

//将文件保存为2.xls

book.SaveAs(COleVariant("C:\\2.xls"),covOptional,covOptional, \

covOptional,covOptional,covOptional,0,\

covOptional,covOptional,covOptional,covOptional);

//*****

//关闭所有的book,退出Excel

book.Close (covOptional,COleVariant(OutFilename),covOptional);

books.Close();

app.Quit();

Excel培训教材(全)

Excel培训教材 目录 1 Excel简介 5 1.1 Excel界面简介 6 1.2 输入和编辑数据8 1.2.1 选定操作区域8 1.2.2 定位的使用9 1.2.3 复制、移动和删除9 1.2.4 撤消和恢复10 1.2.5 查找和替换10 1.2.6 在单元格中输入数据11 1.2.7 其他填充方式12 1.2.8 简单的计算13 1.2.9 相对引用和绝对引用14 1.2.10 名称的使用15 1.3 添加、删除单元格、行和列15 1.4 改变列宽和行高16 1.5 设置工作表的格式17 1.5.1 单元格的格式设置17 1.5.2 数据表的美化18 1.5.3 样式的使用和设置19 1.5.4 格式的复制和删除19 1.5.5 条件格式的设置19 1.5.6 隐藏行和列19 1.5.7 拼音的设置20 1.5.8 自动套用格式20 1.6 改变字体21 1.7 设置页面属性、预览和打印22

1.7.1 打印预览22 1.7.2 页面设置22 1.7.3 设置打印区域26 1.7.4 打印选项27 2 Excel的自定义功能 27 2.1 启动选项27 2.2 设置Excel选项28 2.3 自定义屏幕29 2.3.1 调色板的使用30 2.3.2 使用全屏视图30 2.3.3 储存当前工作簿中的视图30 2.4 录制和使用宏31 2.4.1 定义宏的键盘快捷键31 2.5 保存自定义工具栏的布局32 2.5.1 创建常规自定义工具栏32 3 EXCEL先进的浏览和选择功能33 3.1 移动浏览33 3.1.1 知道所处的位置33 3.1.2 键盘浏览33 3.1.3 跳转到定义名称34 3.1.4 用滚动条浏览34 3.2 选择的技巧35 3.2.1 Shift键的使用35 3.2.2 Ctrl键的使用35 3.2.3 在选区内浏览35 3.2.4 进行选择的快捷键35 3.3 数据输入36 3.3.1 正确输入36 3.3.2 从邻近的单元格复制数据36 3.3.3 充分利用“记忆式键入”功能36

相关主题
相关文档
最新文档