使用MFC操作EXCEL文件

若对您有所启发

欢迎打赏

古典小说网

致力于打造极致阅读体验


首创卡拉OK读书方式


首创,桌面大屏幕TXT阅读方式



承接软件定制

联系方式: 

官网:www.gudianxiaoshuo.com

微信:gudianxiaoshuo

QQ:869321632

QQ群: 331506725 (刚建 欢迎加入)

邮箱: [email protected]






一、加载

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 (这个一般有了)

#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;
		
	}
}
 




如果此文对您有所帮助,还望点击一下以下网站:


    360导航

    2345导航        

   古典小说网,本人的网站

你可能感兴趣的:(EXCEL)