C++環境下讀取excel表格,親測可用
在VS2015環境中,個人對以下程式和步驟進行了測試,結果表明完全可以讀取excel資料。
相關的完整程式可以在https://download.csdn.net/download/cxd3341/12683449中獲取
以下為程式建立步驟:
1、新建MFC程式:
新建基於對話方塊的MFC程式:
單擊完成,即完成基於MFC對話方塊的程式的建立。
2.新增讀取excel資料的介面類:
新增讀取excel的介面類:
3、新增完成後,找到這幾個介面類的標頭檔案,註釋/刪除 下圖紅框中的引入語句
注意:每個介面類的標頭檔案都需進行處理。
4、新增原始檔
excel.h檔案:
#pragma once #include "CApplication.h" #include "CRange.h" #include "CWorkbook.h" #include "CWorkbooks.h" #include "CWorksheet.h" #include "CWorksheets.h" #include "stdafx.h" class Excel { public: Excel(); ~Excel(); void show(bool bShow); //檢查一個cell是否為字串 bool isCellString(long iRow, long iColumn); //檢查一個cell是否為數值 bool isCellInt(long iRow, long iColumn); //得到一個cell的string CString getCellString(long iRow, long iColumn); //得到一個cell的總數 int getCellInt(long iRow, long iColumn); //得到一個cell的double資料 double getCellDouble(long iRow, long iColumn); //取得行的總數 int getRowCount(); //取得列的總數 int getColumnCount(); //使用某個shell bool loadSheet(long tableId, bool preLoaded = false); bool loadSheet(CString sheet, bool preLoaded = false); //通過序號取得某個sheet的名稱 CString getSheetName(long tableID); //得到sheet的總數 int getSheetCount(); //開啟excel檔案 bool open(const char* fileName); //關閉開啟的excel檔案 void close(bool ifSave = false); //另存為一個excel檔案 void saveAsXLSFile(const CString &xlsFile); //取得開啟檔案的名稱 CString getOpenFileName(); //取得開啟sheel的名稱 CString getOpenSheelName(); //向cell中寫入一個int值 void setCellInt(long iRow, long iColumn, int newInt); //向cell中寫入一個字串 void setCellString(long iRow, long iColumn, CString newString); public: //初始化 Excel_OLE static bool initExcel(); //釋放Excel_OLE static void release(); //取得列的名稱 static char* getColumnName(long iColumn); protected: void preLoadSheet(); private: CString openFileName; CWorkbook workBook; //當前處理的檔案 CWorkbooks books; //ExcelBook集合,多檔案時使用 CWorksheet workSheet; //當前使用sheet CWorksheets sheets; //Excel的sheet集合 CRange currentRange; //當前操作區域 bool isLoad; //是否已經載入了某個sheet資料 COleSafeArray safeArray; protected: static CApplication application; //Excel程序例項 };
excel.cpp檔案
//Excel.cpp #include "stdafx.h" #include <tchar.h> #include "Excel.h" COleVariant covTrue((short)TRUE), covFalse((short)FALSE), covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); CApplication Excel::application; Excel::Excel() :isLoad(false) { } Excel::~Excel() { //close(); } bool Excel::initExcel() { //建立Excel 2000伺服器(啟動Excel) if (!application.CreateDispatch(_T("Excel.application"), nullptr)) { MessageBox(nullptr, _T("建立Excel服務失敗,你可能沒有安裝EXCEL,請檢查!"), _T("錯誤"), MB_OK); return FALSE; } application.put_DisplayAlerts(FALSE); return true; } void Excel::release() { application.Quit(); application.ReleaseDispatch(); application = nullptr; } bool Excel::open(const char* fileName) { //先關閉檔案 close(); //利用模板建立新文件 books.AttachDispatch(application.get_Workbooks(), true); LPDISPATCH lpDis = nullptr; lpDis = books.Add(COleVariant(CString(fileName))); if (lpDis) { workBook.AttachDispatch(lpDis); sheets.AttachDispatch(workBook.get_Worksheets()); openFileName = fileName; return true; } return false; } void Excel::close(bool ifSave) { //如果檔案已經開啟,關閉檔案 if (!openFileName.IsEmpty()) { //如果儲存,交給使用者控制,讓使用者自己存,如果自己SAVE,會出現莫名的等待 if (ifSave) { //show(true); } else { workBook.Close(COleVariant(short(FALSE)), COleVariant(openFileName), covOptional); books.Close(); } //清空開啟檔名稱 openFileName.Empty(); } sheets.ReleaseDispatch(); workSheet.ReleaseDispatch(); currentRange.ReleaseDispatch(); workBook.ReleaseDispatch(); books.ReleaseDispatch(); } void Excel::saveAsXLSFile(const CString &xlsFile) { workBook.SaveAs(COleVariant(xlsFile), covOptional, covOptional, covOptional, covOptional, covOptional, 0, covOptional, covOptional, covOptional, covOptional, covOptional); return; } int Excel::getSheetCount() { return sheets.get_Count(); } CString Excel::getSheetName(long tableID) { CWorksheet sheet; sheet.AttachDispatch(sheets.get_Item(COleVariant((long)tableID))); CString name = sheet.get_Name(); sheet.ReleaseDispatch(); return name; } void Excel::preLoadSheet() { CRange used_range; used_range = workSheet.get_UsedRange(); VARIANT ret_ary = used_range.get_Value2(); if (!(ret_ary.vt & VT_ARRAY)) { return; } // safeArray.Clear(); safeArray.Attach(ret_ary); } //按照名稱載入sheet表格,也可提前載入所有表格 bool Excel::loadSheet(long tableId, bool preLoaded) { LPDISPATCH lpDis = nullptr; currentRange.ReleaseDispatch(); currentRange.ReleaseDispatch(); lpDis = sheets.get_Item(COleVariant((long)tableId)); if (lpDis) { workSheet.AttachDispatch(lpDis, true); currentRange.AttachDispatch(workSheet.get_Cells(), true); } else { return false; } isLoad = false; //如果進行預先載入 if (preLoaded) { preLoadSheet(); isLoad = true; } return true; } bool Excel::loadSheet(CString sheet, bool preLoaded) { LPDISPATCH lpDis = nullptr; currentRange.ReleaseDispatch(); currentRange.ReleaseDispatch(); lpDis = sheets.get_Item(COleVariant(sheet)); if (lpDis) { workSheet.AttachDispatch(lpDis, true); currentRange.AttachDispatch(workSheet.get_Cells(), true); } else { return false; } isLoad = false; //如果進行預先載入 if (preLoaded) { preLoadSheet(); isLoad = true; } return true; } int Excel::getColumnCount() { CRange range; CRange usedRange; usedRange.AttachDispatch(workSheet.get_UsedRange(), true); range.AttachDispatch(usedRange.get_Columns(), true); int count = range.get_Count(); usedRange.ReleaseDispatch(); range.ReleaseDispatch(); return count; } int Excel::getRowCount() { CRange range; CRange usedRange; usedRange.AttachDispatch(workSheet.get_UsedRange(), true); range.AttachDispatch(usedRange.get_Rows(), true); int count = range.get_Count(); usedRange.ReleaseDispatch(); range.ReleaseDispatch(); return count; } bool Excel::isCellString(long iRow, long iColumn) { CRange range; range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true); COleVariant vResult = range.get_Value2(); //VT_BSTR標示字串 if (vResult.vt == VT_BSTR) { return true; } return false; } bool Excel::isCellInt(long iRow, long iColumn) { CRange range; range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true); COleVariant vResult = range.get_Value2(); //VT_BSTR標示字串 if (vResult.vt == VT_INT || vResult.vt == VT_R8) { return true; } return false; } CString Excel::getCellString(long iRow, long iColumn) { COleVariant vResult; CString str; //字串 if (isLoad == false) { CRange range; range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true); vResult = range.get_Value2(); range.ReleaseDispatch(); } //如果資料依據預先載入了 else { long read_address[2]; VARIANT val; read_address[0] = iRow; read_address[1] = iColumn; safeArray.GetElement(read_address, &val); vResult = val; } if (vResult.vt == VT_BSTR) { str = vResult.bstrVal; } //整數 else if (vResult.vt == VT_INT) { str.Format(_T("%d"), vResult.pintVal); } //8位元組的數字 else if (vResult.vt == VT_R8) { str.Format(_T("%0.0f"), vResult.dblVal); } //時間格式 else if (vResult.vt == VT_DATE) { SYSTEMTIME st; VariantTimeToSystemTime(vResult.date, &st); CTime tm(st); str = tm.Format(_T("%Y-%m-%d")); } //單元格空的 else if (vResult.vt == VT_EMPTY) { str = ""; } return str; } double Excel::getCellDouble(long iRow, long iColumn) { double rtn_value = 0; COleVariant vresult; //字串 if (isLoad == false) { CRange range; range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true); vresult = range.get_Value2(); range.ReleaseDispatch(); } //如果資料依據預先載入了 else { long read_address[2]; VARIANT val; read_address[0] = iRow; read_address[1] = iColumn; safeArray.GetElement(read_address, &val); vresult = val; } if (vresult.vt == VT_R8) { rtn_value = vresult.dblVal; } return rtn_value; } int Excel::getCellInt(long iRow, long iColumn) { int num; COleVariant vresult; if (isLoad == FALSE) { CRange range; range.AttachDispatch(currentRange.get_Item(COleVariant((long)iRow), COleVariant((long)iColumn)).pdispVal, true); vresult = range.get_Value2(); range.ReleaseDispatch(); } else { long read_address[2]; VARIANT val; read_address[0] = iRow; read_address[1] = iColumn; safeArray.GetElement(read_address, &val); vresult = val; } // num = static_cast<int>(vresult.dblVal); return num; } void Excel::setCellString(long iRow, long iColumn, CString newString) { COleVariant new_value(newString); CRange start_range = workSheet.get_Range(COleVariant(_T("A1")), covOptional); CRange write_range = start_range.get_Offset(COleVariant((long)iRow - 1), COleVariant((long)iColumn - 1)); write_range.put_Value2(new_value); start_range.ReleaseDispatch(); write_range.ReleaseDispatch(); } void Excel::setCellInt(long iRow, long iColumn, int newInt) { COleVariant new_value((long)newInt); CRange start_range = workSheet.get_Range(COleVariant(_T("A1")), covOptional); CRange write_range = start_range.get_Offset(COleVariant((long)iRow - 1), COleVariant((long)iColumn - 1)); write_range.put_Value2(new_value); start_range.ReleaseDispatch(); write_range.ReleaseDispatch(); } void Excel::show(bool bShow) { application.put_Visible(bShow); application.put_UserControl(bShow); } CString Excel::getOpenFileName() { return openFileName; } CString Excel::getOpenSheelName() { return workSheet.get_Name(); } char* Excel::getColumnName(long iColumn) { static char column_name[64]; size_t str_len = 0; while (iColumn > 0) { int num_data = iColumn % 26; iColumn /= 26; if (num_data == 0) { num_data = 26; iColumn--; } column_name[str_len] = (char)((num_data - 1) + 'A'); str_len++; } column_name[str_len] = '\0'; //反轉 _strrev(column_name); return column_name; }
5、在對話方塊中新增按鈕和靜態文字框:
為靜態文字框IDC_STATIC1控制元件新增控制元件變數
在readexcelDlg.h中新增對excel類的引用,
在readexcelDlg.h中宣告一個excel類的物件
Excel excel;
編譯程式,可能會彈出如下的錯誤:
在DialogBox前加下劃線即:_DialogBox (具體原理不知道)
再次編譯就OK了。
6、使用excel類
在button的單擊事件中完成下述程式碼:
void CreadexcelDlg::OnBnClickedButton1() { // TODO: 在此新增控制元件通知處理程式程式碼 //使用excel類 bool bInit = m_excel.initExcel(); char path[MAX_PATH]; GetCurrentDirectoryA(MAX_PATH, path);//獲取當前工作目錄 strcat_s(path,"\\data\\001.xlsx");//設定要開啟檔案的完整路徑 bool bRet = m_excel.open(path);//開啟excel檔案 CString strSheetName = m_excel.getSheetName(1);//獲取sheet名 m_sheetname.SetWindowTextW(strSheetName); //顯示讀取excel的資料表名 bool bLoad = m_excel.loadSheet(strSheetName);//裝載sheet int nRow = m_excel.getRowCount();//獲取sheet中行數 int nCol = m_excel.getColumnCount();//獲取sheet中列數 CString cell; for (int i = 1; i <= nRow; ++i) { for (int j = 1; j <= nCol; ++j) { cell = m_excel.getCellString(i, j); } } }
下圖為專案資料夾下data資料夾中的excel檔案001.xlsx
7、執行程式,結果如下圖所示,成功讀取excel資料表的相關資訊。
注:文章轉自如下地址
https://blog.csdn.net/cxd3341/article/details/107779314?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param