近期在忙一個小項目(和同學一起搞的),在這里客戶要求不但讀寫txt,而且可以讀寫excel文件,這里本以為很簡單,結果。。。廢話少說,過程如下:
筆者環境:win7 64+VS2012+Office2013+MFC。
說明:讀寫excel文件,通常包括1.ODBC數據庫實現;2.通過解析Excel表格文件;3.通過OLE/COM的幾種實現方法。本文主要研究通過OLE/COM實現對Excel表格的操作。
步驟:
1.新建MFC對話框。注意勾選自動化,否則后面加入不了需要的庫,導致啟動服務失敗等錯誤。有的博客說需要加入
1 if (!AfxOleInit()) 2 { 3 AfxMessageBox(IDP_OLE_INIT_FAILED); 4 return FALSE; 5 }
筆者實驗發現加不加入都沒有問題,如果后面有人有問題可以加入。
2.向項目工程中添加基本的7個類(Excel作為OLE/COM庫插件,定義好了各類交互的接口,這些接口是跨語言的接口。VC可以通過導入這些接口,並通過 接口來對Excel的操作),由於本文只關心對Excel表格中的數據的讀取,主要關注7個接_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range、Font。
VS2012導入OLE/COM組件的接口的步驟為:項目->類向導->添加類->類型庫中的MFC類,先選擇要導入的組件所在的路徑,即Excel.exe所在的路 徑,然后再選擇要導入的Excel類型庫中的接口。組件路徑一般為C:\Program Files\Microsoft Office\Office15\EXCEL.exe;格式類似。
3. 導入之后需要“#import "C:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace”注釋掉,然后添加頭文 件:#include <afxdisp.h>到上面7個文件中去。
4.如果有錯誤error C2059雙擊error C2059,將VARIANT DialogBox()改成VARIANT _DialogBox()再次編譯,通過!!
5.讀寫excel。
在對話框頭文件中*Dlg.h定義變量
1 //定義接口類變量 2 CApplication app; 3 CWorkbook book; 4 CWorkbooks books; 5 CWorksheet sheet; 6 CWorksheets sheets; 7 CRange range; 8 CMyFont font; 9 CRange cols; 10 LPDISPATCH lpDisp;
a.寫excel,在*Dlg.cpp里面的OnInitDialog函數添加代碼:
1 //導出 2 COleVariant covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR); 3 if (!app.CreateDispatch(_T("Excel.Application"))) 4 { 5 this->MessageBox(_T("無法創建Excel應用!")); 6 return TRUE; 7 } 8 books = app.get_Workbooks(); 9 //打開Excel,其中pathname為Excel表的路徑名 10 11 book = books.Add(covOptional); 12 sheets = book.get_Worksheets(); 13 sheet = sheets.get_Item(COleVariant((short)1)); //獲得坐標為(A,1)和(B,1)的兩個單元格 14 range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("B1"))); //設置單元格類容為Hello Exce 15 range.put_Value2(COleVariant(_T("Hello Excel"))); //選擇整列,並設置寬度為自適應 16 cols = range.get_EntireColumn(); 17 cols.AutoFit(); 18 //設置字體為粗體 19 font = range.get_Font(); 20 font.put_Bold(COleVariant((short)TRUE)); 21 //獲得坐標為(C,2)單元格 22 range = sheet.get_Range(COleVariant(_T("C2")), COleVariant(_T("C2"))); 23 //設置公式“=RAND()*100000” 24 range.put_Formula(COleVariant(_T("=RAND()*100000"))); 25 //設置數字格式為貨幣型 26 range.put_NumberFormat(COleVariant(_T("$0.00"))); 27 //選擇整列,並設置寬度為自適應 28 cols = range.get_EntireColumn(); 29 cols.AutoFit(); 30 //顯示Excel表 31 app.put_Visible(TRUE); 32 app.put_UserControl(TRUE);
結果如下
b.導入excel,同樣在*Dlg的位置添加代碼:
1 //導入 2 COleVariant covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR); 3 if (!app.CreateDispatch(_T("Excel.Application"))) 4 { 5 this->MessageBox(_T("無法創建Excel應用!")); 6 return TRUE; 7 } 8 books = app.get_Workbooks(); 9 //打開Excel,其中pathname為Excel表的路徑名 10 lpDisp = books.Open(_T("D:\\VS2012\\Projects\\TestExcelApp2\\TestExcelApp2\\工作薄1.xlsx"),covOptional ,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional,covOptional); 11 book.AttachDispatch(lpDisp); 12 sheets = book.get_Worksheets(); 13 sheet = sheets.get_Item(COleVariant((short)1)); 14 //獲得坐標為(A,1)的單元格 15 range = sheet.get_Range(COleVariant(_T("A1")) ,COleVariant(_T("A1"))); 16 //獲得單元格的內容 17 COleVariant rValue; 18 rValue = COleVariant(range.get_Value2()); 19 //轉換成寬字符 20 rValue.ChangeType(VT_BSTR); 21 //轉換格式,並輸出 22 this->MessageBox(CString(rValue.bstrVal)); 23 book.put_Saved(TRUE); 24 app.Quit();
效果如下:
excel內容:
讀到第一行第一列元素:
筆者只是需要讀取excel的讀寫功能,所以只是做了這方面的實驗,可以用到自己的項目中,所以共大家分享一下。有什么問題可以留言,共勉!