在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