使用Microsoft Office所帶的控件來實現代碼操作excel表格。
最近由於工作需要,不得不操作Excel,包括基本的數據輸入輸出、字體設置、顏色設置、單元格的合併、填充色的設置,當然還包括圖表的生成以及漸近線的操作等。折騰了許久,項目終於完成了^_^。現在將學習操作Excel的點點滴滴記錄下來和大家一同分享,也作爲自己的一次總結。
1、Excel的對象模型(有人稱其爲層次結構)
打開一個Excel工作表,點擊“工具”->“宏”->“Visual Basic 編輯器”選項打開VB的編輯器,打開幫助文檔,裏面“Microsoft Excel Visual Basic 參考”下的“Microsoft Excel 對象模型”展示了完整的Excel的層次結構,是不是有點類似於MFC的繼承圖表啊?利用幫助文檔我們可以找到一些需要的知識,下面介紹一些類:
_Application:表示整個的Excel應用程序,包含一個工作簿集合
Workbooks:工作簿集合,包含N個工作簿(Workbook)
_Workbook:工作簿,包含一個工作表(sheets)集合
Worksheets:工作表集合,包含N個工作表
_Worksheet:工作表,也就是我們在Excel中看到的Sheet1、Sheet2、Sheet3,它是我們操作Excel的基本單位
Range:這是單元格的集合,我們知道Excel是由一個個的單元格組成的,通過Range來操作單元格
Font:用於設置單元格的字體、顏色、字號、粗體設置
Interior:設置底色
Boards:設置區域內所有單元格的邊框,如果要設置一組區域的外邊框的話用Rang->BorderAround設置
下面用一個具體的例子來說明怎麼通過MFC來操作Excel
2、Excel庫的插入
在我們MFC的工程中,按Ctrl+W打開MFC類嚮導對話框,點擊“Add Class...”->“From a type Library...”,找到你所使用的excel類型庫,我使用的在目錄C:/Program Files/Microsoft Office/OFFICE11下的“EXCEL.EXE”文件,查找時文件類型選“All Files”,然後添加我們所需要的類,通常以上列舉的前6類是必須的,其它的需要時再添加。我不認爲全部添加是一種好的做法,一個我覺得很亂,另外生成的excel.cpp文件會很大。我建議瀏覽一遍這些類,這樣當你做些操作時可以更清楚的知道需要添加哪些類。添加完需要的類後,我們就可以來做一些基本的操作了。
3、Com支持庫的初始化
通常在App的InitInstance()裏面加入初始化和關閉COM庫的操作,在DoModal()調用之前加入初始化的代碼:
- if (CoInitialize(NULL) != 0)
- {
- AfxMessageBox("初始化COM支持庫失敗!");
- exit(1);
- }
在return之前加入CoUninitialize(); 關閉CON庫。
4、代碼演示一些基本的操作
首先別忘了包含頭文件“excel.h”,若用到_variant_t()時,需要包含頭文件“comdef.h”和“comutil.h”,否則會出現錯誤:
“error C2065: '_variant_t' : undeclared identifier”。
下面的代碼包括了一些基本的操作:
- // 變量的定義
- _Application app;
- Workbooks books;
- _Workbook book;
- Worksheets sheets;
- _Worksheet sheet;
- Range range;
- LPDISPATCH lpDisp;
- COleVariant vResult;
- CString str = "";
- COleVariant
- covTrue((short)TRUE),
- covFalse((short)FALSE),
- covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
- //創建Excel 2003服務器(啓動Excel)
- if (!app.CreateDispatch("Excel.Application",NULL))
- {
- AfxMessageBox("Create Excel service failure!");
- return;
- }
- // 設置爲FALSE時,後面的app.Quit();註釋要打開
- // 否則EXCEL.EXE進程會一直存在,並且每操作一次就會多開一個進程
- app.SetVisible(TRUE);
- books.AttachDispatch(app.GetWorkbooks(),true);
- /*
- * 打開一個工作簿。
- * Excel 2000 只需要13個參數就行,Excel 2003需要15個參數
- */
- lpDisp = books.Open("E://test.xls",
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional, covOptional, covOptional,
- covOptional, covOptional);
- ASSERT(lpDisp);
- book.AttachDispatch(lpDisp);
- // 得到Worksheets
- sheets.AttachDispatch(book.GetWorksheets(),true);
- // 得到Worksheet
- sheet.AttachDispatch(sheets.GetItem(_variant_t((short)(1))));
- // 得到全部Cells
- range.AttachDispatch(sheet.GetCells(),true);
- // 往單元格A1裏寫入字符串數據,就像操作矩陣一樣,第1行第1列
- range.SetItem(_variant_t((LONG)1),_variant_t((LONG)1),_variant_t("hello word!"));
- // 往單元格A2裏寫入時間數據
- range.AttachDispatch(sheet.GetRange(_variant_t("A2"), _variant_t("A2")),true);
- range.SetValue2(_variant_t("2011/02/15"));
- // 往單元格A3~A6裏寫入浮點數據
- range.AttachDispatch(sheet.GetRange(_variant_t("A3"), _variant_t("A6")),true);
- range.SetValue2(_variant_t((double)3.14));
- // 設置單元格的列寬爲12
- range.AttachDispatch(sheet.GetRange(_variant_t("A1"), _variant_t("A1")),true);
- range.SetColumnWidth(_variant_t((long)12));
- // 所有單元格居中顯示
- range.AttachDispatch(sheet.GetCells(),true);
- range.SetHorizontalAlignment(_variant_t((long)-4108)); // -4108:居中,-4131:靠左,-4152:靠右
- range.SetVerticalAlignment(_variant_t((long)-4108)); // -4108:居中,-4160:靠上,-4107:靠下
- // 讀取單元格的數據,第4行第1列
- range.AttachDispatch(range.GetItem(_variant_t((long)(4)),_variant_t((long)(1))).pdispVal );
- vResult =range.GetValue(covOptional);
- switch (vResult.vt)
- {
- case VT_BSTR: // 字符串
- str=vResult.bstrVal;
- break;
- case VT_R8: // 8字節的數字
- str.Format("%f",vResult.dblVal);
- break;
- case VT_DATE: // 時間格式
- SYSTEMTIME st;
- VariantTimeToSystemTime(vResult.date, &st);
- break;
- case VT_EMPTY: // 單元格空的
- str="";
- break;
- }
- //MessageBox(str);
- Font ft; // 要插入excel類庫裏面的Font類,下面類似
- range.AttachDispatch(sheet.GetRange(_variant_t("A3"), _variant_t("A5")),true);
- ft.AttachDispatch(range.GetFont());
- ft.SetName(_variant_t("華文行楷")); // 字體
- ft.SetSize(_variant_t((long)12)); // 字號
- //ft.SetColorIndex(_variant_t((long)3)); // 字的顏色: 紅色
- ft.SetColor( _variant_t((long) RGB(255, 0, 0) ) );
- ft.SetBold(_variant_t((long)1)); // 1:粗體,0:非粗體
- Interior it; // 底色設置
- range.AttachDispatch(sheet.GetRange(_variant_t("C3"), _variant_t("E6")),true);
- it.AttachDispatch(range.GetInterior());
- it.SetColorIndex(_variant_t((long)20)); // 底色設置爲淺青色
- Borders borders; // 先設置區域內所有單元格的邊框
- borders = range.GetBorders();
- borders.SetColorIndex(_variant_t((long)1));
- borders.SetLineStyle(_variant_t((long)1));
- borders.SetWeight(_variant_t((long)2));
- // 然後設置外邊框
- // LineStyle=線型(1~13) Weight=線寬 ColorIndex=線的顏色(-4105爲自動, 1爲黑色)
- range.BorderAround(_variant_t((long)9),_variant_t((long)1),_variant_t((long)1),vtMissing);
- range.AttachDispatch(sheet.GetRange(_variant_t("C8"), _variant_t("D9")),true);
- // 合併單元格
- range.Merge(_variant_t((long)0));
- book.Save(); // 保存Excel的內容
- // app.SetDisplayAlerts(false); // 不彈出對話框詢問是否保存
- // app.Quit(); // 退出
- //釋放對象
- range.ReleaseDispatch();
- sheet.ReleaseDispatch();
- sheets.ReleaseDispatch();
- book.ReleaseDispatch();
- books.ReleaseDispatch();
-
app.ReleaseDispatch();
- .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);
- }