天天看點

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/excel等office元素,那麼需要對必要的類型庫進行導入.下面是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

<span style="white-space:pre">	</span>_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();
           
<span style="white-space:pre">	</span>}
           

其它:下面是網上一個人封裝的一個類大家可以參考一下(當然不如BasicExcel了哈哈,下期講這個類哈)

<span style="white-space:pre">	</span>.h檔案:
<span style="white-space:pre">	</span>#include "comdef.h" 
<span style="white-space:pre">	</span>#include "excel.h"
<span style="white-space:pre">	</span>class ExcelFile 
<span style="white-space:pre">	</span>{
<span style="white-space:pre">	</span>public:
<span style="white-space:pre">		</span>void ShowInExcel(bool bShow);
<span style="white-space:pre">		</span>CString GetCell(int iRow, int iColumn);
<span style="white-space:pre">		</span>int     GetCellInt(int iRow, int iColumn);
<span style="white-space:pre">		</span>int GetRowCount();
<span style="white-space:pre">		</span>int GetColumnCount();
<span style="white-space:pre">		</span>bool LoadSheet(int iIndex);
<span style="white-space:pre">		</span>CString GetSheetName(int iIndex);
<span style="white-space:pre">		</span>static void InitExcel();
<span style="white-space:pre">		</span>static void ReleaseExcel();
<span style="white-space:pre">		</span>int GetSheetCount();
<span style="white-space:pre">		</span>bool Open(CString FileName);
<span style="white-space:pre">		</span>ExcelFile();
<span style="white-space:pre">		</span>virtual ~ExcelFile();
<span style="white-space:pre">	</span>protected:
<span style="white-space:pre">	</span>private:
<span style="white-space:pre">	</span>static _Application m_ExcelApp;

<span style="white-space:pre">	</span>Workbooks    m_Books; 
<span style="white-space:pre">	</span>_Workbook    m_Book; 
<span style="white-space:pre">	</span>Worksheets   m_sheets; 
<span style="white-space:pre">	</span>_Worksheet   m_sheet; 
<span style="white-space:pre">	</span>Range        m_Rge; 
<span style="white-space:pre">	</span>};
           
<span style="white-space:pre">	</span>.cpp檔案:
<span style="white-space:pre">	</span>ExcelFile::ExcelFile()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>ExcelFile::~ExcelFile()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>m_Rge.ReleaseDispatch(); 
<span style="white-space:pre">		</span>m_sheet.ReleaseDispatch(); 
<span style="white-space:pre">		</span>m_sheets.ReleaseDispatch(); 
<span style="white-space:pre">		</span>m_Book.ReleaseDispatch(); 
<span style="white-space:pre">		</span>m_Books.ReleaseDispatch(); 
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>void ExcelFile::InitExcel()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>//建立Excel 2000伺服器(啟動Excel) 
<span style="white-space:pre">		</span>if (!m_ExcelApp.CreateDispatch("Excel.Application",NULL)) 
<span style="white-space:pre">		</span>{ 
<span style="white-space:pre">			</span>AfxMessageBox("建立Excel服務失敗!"); 
<span style="white-space:pre">			</span>exit(1); 
<span style="white-space:pre">		</span>} 
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>void ExcelFile::ReleaseExcel()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>m_ExcelApp.ReleaseDispatch();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool ExcelFile::Open(CString FileName)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>//打開excel檔案
<span style="white-space:pre">		</span>//利用模闆檔案建立新文檔 
<span style="white-space:pre">		</span>m_Books.AttachDispatch(m_ExcelApp.GetWorkbooks(),true); 
<span style="white-space:pre">		</span>LPDISPATCH lpDis = NULL;
<span style="white-space:pre">		</span>lpDis = m_Books.Add(_variant_t(FileName)); // 如何判斷檔案是否打開?
<span style="white-space:pre">		</span>if (lpDis)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>m_Book.AttachDispatch(lpDis); 
<span style="white-space:pre">			</span>//得到Worksheets 
<span style="white-space:pre">			</span>m_sheets.AttachDispatch(m_Book.GetWorksheets(),true); 
<span style="white-space:pre">			</span>return true;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return false;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>int ExcelFile::GetSheetCount()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return m_sheets.GetCount();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>CString ExcelFile::GetSheetName(int iIndex)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>_Worksheet sheet;
<span style="white-space:pre">		</span>sheet.AttachDispatch(m_sheets.GetItem(_variant_t((long)iIndex)),true);
<span style="white-space:pre">		</span>CString name = sheet.GetName();
<span style="white-space:pre">		</span>sheet.ReleaseDispatch();
<span style="white-space:pre">		</span>return name;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>bool ExcelFile::LoadSheet(int iIndex)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>LPDISPATCH lpDis = NULL;
<span style="white-space:pre">		</span>m_Rge.ReleaseDispatch();
<span style="white-space:pre">		</span>m_sheet.ReleaseDispatch();
<span style="white-space:pre">		</span>lpDis = m_sheets.GetItem(_variant_t((long)iIndex));
<span style="white-space:pre">		</span>if (lpDis)
<span style="white-space:pre">		</span>{
   		<span style="white-space:pre">	</span>m_sheet.AttachDispatch(lpDis,true);
   		<span style="white-space:pre">	</span>m_Rge.AttachDispatch(m_sheet.GetCells(), true);
   		<span style="white-space:pre">	</span>return true;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return false;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>int ExcelFile::GetColumnCount()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>Range range;
<span style="white-space:pre">		</span>Range usedRange;
<span style="white-space:pre">		</span>usedRange.AttachDispatch(m_sheet.GetUsedRange(), true);
<span style="white-space:pre">		</span>range.AttachDispatch(usedRange.GetColumns(), true);
<span style="white-space:pre">		</span>int count = range.GetCount();
<span style="white-space:pre">		</span>usedRange.ReleaseDispatch();
<span style="white-space:pre">		</span>range.ReleaseDispatch();
<span style="white-space:pre">		</span>return count;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>int ExcelFile::GetRowCount()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>Range range;
<span style="white-space:pre">		</span>Range usedRange;
<span style="white-space:pre">		</span>usedRange.AttachDispatch(m_sheet.GetUsedRange(), true);
<span style="white-space:pre">		</span>range.AttachDispatch(usedRange.GetRows(), true);
<span style="white-space:pre">		</span>int count = range.GetCount();
<span style="white-space:pre">		</span>usedRange.ReleaseDispatch();
<span style="white-space:pre">		</span>range.ReleaseDispatch();
<span style="white-space:pre">		</span>return count;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>CString ExcelFile::GetCell(int iRow, int iColumn)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>Range range;
<span style="white-space:pre">		</span>range.AttachDispatch(m_Rge.GetItem (COleVariant((long)iRow),COleVariant((long)iColumn)).pdispVal, true);
 	<span style="white-space:pre">	</span>COleVariant vResult =range.GetValue2();
<span style="white-space:pre">		</span>CString str;
<span style="white-space:pre">		</span>if(vResult.vt == VT_BSTR)       //字元串
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>str=vResult.bstrVal;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>else if (vResult.vt==VT_INT)
<span style="white-space:pre">		</span>{
   		<span style="white-space:pre">	</span>str.Format("%d",vResult.pintVal);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>else if (vResult.vt==VT_R8)     //8位元組的數字 
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>str.Format("%f",vResult.dblVal);
<span style="white-space:pre">			</span>//str.Format("%.0f",vResult.dblVal);
<span style="white-space:pre">			</span>//str.Format("%1f",vResult.fltVal);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>else if(vResult.vt==VT_DATE)    //時間格式
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>SYSTEMTIME st;
<span style="white-space:pre">			</span>VariantTimeToSystemTime(vResult.date, &st);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>else if(vResult.vt==VT_EMPTY)   //單元格空的
<span style="white-space:pre">		</span>{
 	<span style="white-space:pre">		</span>str="(NULL)";
<span style="white-space:pre">		</span>} 
<span style="white-space:pre">		</span>range.ReleaseDispatch();
<span style="white-space:pre">		</span>return str;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>int ExcelFile::GetCellInt(int iRow, int iColumn)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>Range range;
<span style="white-space:pre">		</span>range.AttachDispatch(m_Rge.GetItem(COleVariant((long)iRow),COleVariant((long)iColumn)).pdispVal, true);
<span style="white-space:pre">		</span>COleVariant vResult =range.GetValue2();
<span style="white-space:pre">		</span>int num;
<span style="white-space:pre">		</span>num = (int)vResult.date;
<span style="white-space:pre">		</span>range.ReleaseDispatch();
<span style="white-space:pre">		</span>return num;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>void ExcelFile::ShowInExcel(bool bShow)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>m_ExcelApp.SetVisible(bShow);
<span style="white-space:pre">	</span>}
           

繼續閱讀