VC++操作Excel

摘要:使用Microsoft Office所带的控件来实现代码操作excel表格。

开发环境:操作系统是Microsoft Windows7 32bit,Office办公套装是Microsoft Office 2003,编程环境是Microsoft Visual Studio 6.0。

使用背景:我最近有个项目中要生成报表,是将数据库中的发证数据查询出来导出到Excel表格中以便打印,所以上网找了这方面的内容,具体内容如下,如错误还请指证。


从平常我们操作一般文件上来看,无非是打开文件,操作文件(读取,写入),然后关闭打开的文件。 操作Excel也就是和操作普通文件将其打开,然后写入/读出数据,然后关闭等操作哦。以下是个例子程序:


操作Excel具体如下:因为Excel格式是微软固有的私有格式,如果我想自己操作Excel是完全不可能,所以只有通过微软给我们COM组件接口来操作。这些COM类型列表如下:

VC++/MFC操作Office必需的类型库参考》

说明:如果需要在VC++/MFC开发程序操作word/exceloffice元素,那么需要对必要的类型库进行导入.下面是office系列的类型库参考,导入类型库时候请选择正确的类型库进行导入.

应用程序

类型库

Microsoft Access 97

Msacc8.olb

Microsoft Jet Database 3.5

DAO350.dll

Microsoft Binder 97

Msbdr8.olb

Microsoft Excel 97

Excel8.olb

Microsoft Graph 97

Graph8.olb

Microsoft Office 97

Mso97.dll

Microsoft Outlook 97

Msoutl97.olb

Microsoft PowerPoint 97

Msppt8.olb

Microsoft Word 97

Msword8.olb

 

 

Microsoft Access 2000

Msacc9.olb

Microsoft Jet Database 3.51

DAO360.dll

Microsoft Binder 2000

Msbdr9.olb

Microsoft Excel 2000

Excel9.olb

Microsoft Graph 2000

Graph9.olb

Microsoft Office 2000

Mso9.dll

Microsoft Outlook 2000

Msoutl9.olb

Microsoft PowerPoint 2000

Msppt9.olb

Microsoft Word 2000

Msword9.olb

 

 

Microsoft Access 2002

Msacc.olb

Microsoft Excel 2002

Excel.exe

Microsoft Graph 2002

Graph.exe

Microsoft Office 2002

MSO.dll

Microsoft Outlook 2002

MSOutl.olb

Microsoft PowerPoint 2002

MSPpt.olb

Microsoft Word 2002

MSWord.olb

 

 

Microsoft Office Access 2003

Msacc.olb

Microsoft Office Excel 2003

Excel.exe

Microsoft Office Graph 2003

Graph.exe

Microsoft Office 2003

MSO.dll

Microsoft Office Outlook 2003

MSOutl.olb

Microsoft Office PowerPoint 2003

MSPpt.olb

Microsoft Office Word 2003

MSWord.olb

注意:这些类型库的默认位置是:

Office 版本

路径

Office 97

C:/Program Files/Microsoft Office/Office

Office 2000

C:/Program Files/Microsoft Office/Office

Office XP

C:/Program Files/Microsoft Office/Office10

Office 2003

C:/Program Files/Microsoft Office/Office11

下面是例子的使用:

首先创建一个程序(我的例子是一个MFC的单文档程序),在程序的入口处和出口处先作初始化COM库,来加载我们需要COM的支持:

在程序入口处CXXXApp:: InitInstance()函数AfxEnableControlContainer();语句之后加入下面几行:

if (CoInitialize(NULL) != 0)

{

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

        exit(1);

}

假如这个条件不通过就不能运行起程序。

在程序的退出释放资源处,也就是与初始化对应的地方:CXXXApp:: ExitInstance()函数return语句之前加入下面这句话:

CoUninitialize(); //来释放COM支持库。

{

CoUninitialize();

}

这样我们就完成了对COM支持库的代码已经完成。

下面要从Office的安装目录中找到对VC操作excel文件的动态库,在某些版本下这个文件是Excel8.olb或者Excel9.olb,在我的版本中是excel.exe这个exe也是动态库的形式,是微软公司主要的文件结果之一。

(和使用普通的COM组件一样)选择VC++的View菜单里面的ClassWizad命令,会弹出一个对话框;然后点击Add Class…按钮选择From a type library,会弹出一个打开对话框,从这里打开Office安装目录下…/Office11/EXCEL.EXE文件,从里面选择几个要用到的类:_Application, Workbooks, _Wrokbook, Worksheets, _WorkSheet, Range,点击OK按钮。会在程序中生成一个excel.h和excel.cpp文件,这些文件中包含了刚才我们选择的几个类的代码。下面介绍一下这几个类:

在VC++操纵Excel的exe动态库里面有好多个对象模型,就是刚才在创建过程中看到的那个列表,但是经常用到的有这么几个:_Application, Workbooks, _Wrokbook, Worksheets, _WorkSheet, Range,Charts和_Chart,最后面的两个是用来操作图表的,我没有用到所以这里也就不记录了。

(a)._Application:这里的Application就是Excel本身,众所周知,一个Excel可以包含多个工作簿,每个工作簿又可以包含多个工作表,而每个工作表又可以包含多个区域或者图表,所以这里他们是树型的结构关系,而application最基本的一个功能就是找到它的子项工作簿。果然,我们在引入我们程序的Application类中看到了这样的成员函数:GetWorkbooks()。既然application就是excel,那么打开程序,退出程序,显示/隐藏程序这些基本的操作都可以在这个类的成员函数中找到,果不其然。

(b).Workbooks:这个对象是一个容器对象,它里面存放着所有打开的工作簿。因此,我们可以猜测它一定有添加,查找,打开/关闭工作簿的功能。(本程序中使用excel的一个xlt模板来生成一个xls文件就是使用了这个容器对象的添加功能。)

(c)._Workbook:这是一个工作簿,也就相当于一个xls文件。Excel可以同时打开多个工作簿,所以工作簿之间必定能够互相切换,每个工作簿可以关联工作表容器并获得工作表的索引。

(d).Worksheets:也是一个容器对象,和Workbooks类似。

(e)._Worksheet:这个就是我们看到的工作表,比如Sheet1,sheet2等等。

(f).Rang:就是我们看到的能选中的方框的大小。而我们所要作的操作基本上是以区域为单位进行的。

 

介绍完这些,我们就来看看一个例子程序吧,就是使用使用微软给我们提供的组件来操作Excel

	{
	_Application _app;
	_Workbook _workBook;
	_Worksheet _workSheet;
	Worksheets workSheets;
	Workbooks workBooks;
	Range range;
	Range copyFrom;
	Range copyTo;
	
	if(!_app.CreateDispatch("Excel.Application", NULL))
	{
		MessageBox("创建Excel服务失败!", "信息提示", MB_OK);
		return;
	}
	//利用模板建立新文档
	workBooks.AttachDispatch(_app.GetWorkbooks());
	_workBook.AttachDispatch(workBooks.Add(_variant_t(vFileName)));//你可以自己创建一个模板,并自由设定目录
	//得到worksheets
	workSheets.AttachDispatch(_workBook.GetWorksheets());
	//得到workSheet
	_workSheet.AttachDispatch(workSheets.GetItem(_variant_t("sheet1")));
	//得到拷贝的母板
	copyFrom.AttachDispatch(_workSheet.GetRange(_variant_t("A3"), _variant_t("Q6")));
	copyTo.AttachDispatch(_workSheet.GetRange(_variant_t("A61"), _variant_t("A61")));
	//得到全部的cells
	range.AttachDispatch(_workSheet.GetCells());
	
	///
	// 上边是头
	
	/*
	中间要做的工作有这两项:设置数据和拷贝格式
	设置数据就是将数据库中查询出来的数据写入表格,拷贝格式就是将表格拷贝到别的地方。
	*/
	//写入数据
	range.SetItem(_variant_t((long)3), _variant_t((long)1), _variant_t("写入数据了"));
	range.SetItem(_variant_t((long)5), _variant_t((long)1), _variant_t("重新写入数据了"));
	//拷贝一段区域到另外的一段区域
	copyFrom.Copy(_variant_t(copyTo));
	range.SetItem(_variant_t((long)61), _variant_t((long)1), _variant_t("123"));
	
	//显示excel表格
		_app.SetVisible(TRUE);
	//保存为文件
	_app.SetDisplayAlerts(FALSE);	//隐藏弹出的对话框
	_workSheet.SaveAs("d://Test.xls",vtMissing,vtMissing,vtMissing,vtMissing,
		vtMissing,vtMissing,vtMissing,vtMissing,vtMissing);
	_app.Quit();
	//下边是尾
	///
	copyFrom.ReleaseDispatch();
	copyTo.ReleaseDispatch();
	range.ReleaseDispatch();
	_workSheet.ReleaseDispatch();
	workSheets.ReleaseDispatch();
	_workBook.ReleaseDispatch();
	workSheets.ReleaseDispatch();
	_app.ReleaseDispatch();
	}


其它:下面是网上一个人封装的一个类大家可以参考一下(当然不如BasicExcel了哈哈,下期讲这个类哈)

	.h文件:
	#include "comdef.h" 
	#include "excel.h"
	class ExcelFile 
	{
	public:
		void ShowInExcel(bool bShow);
		CString GetCell(int iRow, int iColumn);
		int     GetCellInt(int iRow, int iColumn);
		int GetRowCount();
		int GetColumnCount();
		bool LoadSheet(int iIndex);
		CString GetSheetName(int iIndex);
		static void InitExcel();
		static void ReleaseExcel();
		int GetSheetCount();
		bool Open(CString FileName);
		ExcelFile();
		virtual ~ExcelFile();
	protected:
	private:
	static _Application m_ExcelApp;

	Workbooks    m_Books; 
	_Workbook    m_Book; 
	Worksheets   m_sheets; 
	_Worksheet   m_sheet; 
	Range        m_Rge; 
	};

	.cpp文件:
	ExcelFile::ExcelFile()
	{
	}
	ExcelFile::~ExcelFile()
	{
		m_Rge.ReleaseDispatch(); 
		m_sheet.ReleaseDispatch(); 
		m_sheets.ReleaseDispatch(); 
		m_Book.ReleaseDispatch(); 
		m_Books.ReleaseDispatch(); 
	}
	void ExcelFile::InitExcel()
	{
		//创建Excel 2000服务器(启动Excel) 
		if (!m_ExcelApp.CreateDispatch("Excel.Application",NULL)) 
		{ 
			AfxMessageBox("创建Excel服务失败!"); 
			exit(1); 
		} 
	}
	void ExcelFile::ReleaseExcel()
	{
		m_ExcelApp.ReleaseDispatch();
	}
	bool ExcelFile::Open(CString FileName)
	{
		//打开excel文件
		//利用模板文件建立新文档 
		m_Books.AttachDispatch(m_ExcelApp.GetWorkbooks(),true); 
		LPDISPATCH lpDis = NULL;
		lpDis = m_Books.Add(_variant_t(FileName)); // 如何判断文件是否打开?
		if (lpDis)
		{
			m_Book.AttachDispatch(lpDis); 
			//得到Worksheets 
			m_sheets.AttachDispatch(m_Book.GetWorksheets(),true); 
			return true;
		}
		return false;
	}
	int ExcelFile::GetSheetCount()
	{
		return m_sheets.GetCount();
	}
	CString ExcelFile::GetSheetName(int iIndex)
	{
		_Worksheet sheet;
		sheet.AttachDispatch(m_sheets.GetItem(_variant_t((long)iIndex)),true);
		CString name = sheet.GetName();
		sheet.ReleaseDispatch();
		return name;
	}
	bool ExcelFile::LoadSheet(int iIndex)
	{
		LPDISPATCH lpDis = NULL;
		m_Rge.ReleaseDispatch();
		m_sheet.ReleaseDispatch();
		lpDis = m_sheets.GetItem(_variant_t((long)iIndex));
		if (lpDis)
		{
   			m_sheet.AttachDispatch(lpDis,true);
   			m_Rge.AttachDispatch(m_sheet.GetCells(), true);
   			return true;
		}
		return false;
	}
	int ExcelFile::GetColumnCount()
	{
		Range range;
		Range usedRange;
		usedRange.AttachDispatch(m_sheet.GetUsedRange(), true);
		range.AttachDispatch(usedRange.GetColumns(), true);
		int count = range.GetCount();
		usedRange.ReleaseDispatch();
		range.ReleaseDispatch();
		return count;
	}
	int ExcelFile::GetRowCount()
	{
		Range range;
		Range usedRange;
		usedRange.AttachDispatch(m_sheet.GetUsedRange(), true);
		range.AttachDispatch(usedRange.GetRows(), true);
		int count = range.GetCount();
		usedRange.ReleaseDispatch();
		range.ReleaseDispatch();
		return count;
	}
	CString ExcelFile::GetCell(int iRow, int iColumn)
	{
		Range range;
		range.AttachDispatch(m_Rge.GetItem (COleVariant((long)iRow),COleVariant((long)iColumn)).pdispVal, true);
 		COleVariant vResult =range.GetValue2();
		CString str;
		if(vResult.vt == VT_BSTR)       //字符串
		{
			str=vResult.bstrVal;
		}
		else if (vResult.vt==VT_INT)
		{
   			str.Format("%d",vResult.pintVal);
		}
		else if (vResult.vt==VT_R8)     //8字节的数字 
		{
			str.Format("%f",vResult.dblVal);
			//str.Format("%.0f",vResult.dblVal);
			//str.Format("%1f",vResult.fltVal);
		}
		else if(vResult.vt==VT_DATE)    //时间格式
		{
			SYSTEMTIME st;
			VariantTimeToSystemTime(vResult.date, &st);
		}
		else if(vResult.vt==VT_EMPTY)   //单元格空的
		{
 			str="(NULL)";
		} 
		range.ReleaseDispatch();
		return str;
	}
	int ExcelFile::GetCellInt(int iRow, int iColumn)
	{
		Range range;
		range.AttachDispatch(m_Rge.GetItem(COleVariant((long)iRow),COleVariant((long)iColumn)).pdispVal, true);
		COleVariant vResult =range.GetValue2();
		int num;
		num = (int)vResult.date;
		range.ReleaseDispatch();
		return num;
	}
	void ExcelFile::ShowInExcel(bool bShow)
	{
		m_ExcelApp.SetVisible(bShow);
	}


你可能感兴趣的:(Word/Excel,Windows,excel,office,vc++)