最近一个同学说是要做一个报账的软件,总体上要实现的功能就是读写Excel文件,于是自己就开始在网上找读写Excel的方法,首先看到了C/C++读写Excel的几种方法,说是读写的方法有很多,但是反正就是各有利弊,我就选择了以OLE的方式进行Excel的操作(这种方式必须要在电脑上安装Excel程序,否则连最开始的配置就无法完成)。

在网上也看到了很多教程,其中VS2010通过OLE操作Excel2010这篇博客的正文加上下面有个博主的评论就差不多可以实现了,但是都是以文字、方法的方式进行讲解,很难操作,并且自己在弄得时候也遇到了各种各样的问题,所以,我以我自己的实例进行讲解:

1.新建一个MFC工程文件,如下

2.为工程文件导入Excel.exe程序并添加一些必须的类,首先点“文件”,然后找到自己的Excel的安装位置添加过来,最后添加下面 的那几个类(如果前面不小心已经添加了这几个类上面却没有添加Excel.exe程序,这个时候直接把添加的文件直接“删除”即可,如果不删直接添加的话仍然会添加成功,但是添加的就是“CApplication0.h”、“CRange0.h”,这样的话就会跟下面添加的头文件和源文件的类不一致,就会报错)

3.添加完成以后,在“解决方案资源管理器”里面就多了下面6个文件,依次打开每个文件,把右边这个路径给注释掉或者直接删掉

4.这个时候编译时没有问题的

5.为这个工程添加对Excel表格进行操作的头文件“IllusionExcelFile.h”和源文件“IllusionExcelFile.cpp”

头文件(IllusionExcelFile.h):

#pragma once//OLE的头文件
#include "CRange.h"
#include "CWorkbook.h"
#include "CWorkbooks.h"
#include "CWorksheet.h"
#include "CWorksheets.h"
#include "CApplication.h"///
///用于OLE的方式的EXCEL读写,
class IllusionExcelFile
{public://构造函数和析构函数IllusionExcelFile();virtual ~IllusionExcelFile();protected:///打开的EXCEL文件名称CString       open_excel_file_;///EXCEL BOOK集合,(多个文件时)CWorkbooks    excel_books_; ///当前使用的BOOK,当前处理的文件CWorkbook     excel_work_book_; ///EXCEL的sheets集合CWorksheets   excel_sheets_; ///当前使用sheetCWorksheet    excel_work_sheet_; ///当前的操作区域CRange        excel_current_range_; ///是否已经预加载了某个sheet的数据BOOL          already_preload_;///Create the SAFEARRAY from the VARIANT ret.COleSafeArray ole_safe_array_;protected:///EXCEL的进程实例static CApplication excel_application_;
public:///void ShowInExcel(BOOL bShow);///检查一个CELL是否是字符串BOOL    IsCellString(long iRow, long iColumn);///检查一个CELL是否是数值BOOL    IsCellInt(long iRow, long iColumn);///得到一个CELL的StringCString GetCellString(long iRow, long iColumn);///得到整数int     GetCellInt(long iRow, long iColumn);///得到double的数据double  GetCellDouble(long iRow, long iColumn);///取得行的总数int GetRowCount();///取得列的总数int GetColumnCount();///使用某个shet,shit,shitBOOL LoadSheet(long table_index,BOOL pre_load = FALSE);///通过名称使用某个sheet,BOOL LoadSheet(LPCTSTR sheet,BOOL pre_load = FALSE);///通过序号取得某个Sheet的名称CString GetSheetName(long table_index);///得到Sheet的总数int GetSheetCount();///打开文件BOOL OpenExcelFile(LPCTSTR file_name);///关闭打开的Excel 文件,有时候打开EXCEL文件就要void CloseExcelFile(BOOL if_save = FALSE);//另存为一个EXCEL文件void SaveasXSLFile(const CString &xls_file);///取得打开文件的名称CString GetOpenFileName();///取得打开sheet的名称CString GetLoadSheetName();///写入一个CELL一个intvoid SetCellInt(long irow, long icolumn,int new_int);///写入一个CELL一个stringvoid SetCellString(long irow, long icolumn,CString new_string);public:///初始化EXCEL OLEstatic BOOL InitExcel();///释放EXCEL的 OLEstatic void ReleaseExcel();///取得列的名称,比如27->AAstatic char *GetColumnName(long iColumn);protected://预先加载void PreLoadSheet();
};

源文件(IllusionExcelFile.cpp):

#include "StdAfx.h"
#include "IllusionExcelFile.h"COleVariant
covTrue((short)TRUE),
covFalse((short)FALSE),
covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);    //
CApplication IllusionExcelFile::excel_application_;IllusionExcelFile::IllusionExcelFile():already_preload_(FALSE)
{
}IllusionExcelFile::~IllusionExcelFile()
{//CloseExcelFile();
}//初始化EXCEL文件,
BOOL IllusionExcelFile::InitExcel()
{CoUninitialize();if(CoInitialize(NULL)==S_FALSE) { AfxMessageBox(_T("初始化COM支持库失败!")); return FALSE; }//创建Excel 2000服务器(启动Excel) if (!excel_application_.CreateDispatch(_T("Excel.Application"),NULL)) { AfxMessageBox(_T("创建Excel服务失败,你可能没有安装EXCEL,请检查!")); return FALSE;}excel_application_.put_DisplayAlerts(FALSE); return TRUE;
}//
void IllusionExcelFile::ReleaseExcel()
{excel_application_.Quit();excel_application_.ReleaseDispatch();excel_application_=NULL;
}//打开excel文件
BOOL IllusionExcelFile::OpenExcelFile(LPCTSTR file_name)
{//先关闭CloseExcelFile();//利用模板文件建立新文档 excel_books_.AttachDispatch(excel_application_.get_Workbooks(),true); LPDISPATCH lpDis = NULL;lpDis = excel_books_.Add(COleVariant(file_name)); if (lpDis){excel_work_book_.AttachDispatch(lpDis); //得到Worksheets excel_sheets_.AttachDispatch(excel_work_book_.get_Worksheets(),true); //记录打开的文件名称open_excel_file_ = file_name;return TRUE;}return FALSE;
}//关闭打开的Excel 文件,默认情况不保存文件
void IllusionExcelFile::CloseExcelFile(BOOL if_save)
{//如果已经打开,关闭文件if (open_excel_file_.IsEmpty() == FALSE){//如果保存,交给用户控制,让用户自己存,如果自己SAVE,会出现莫名的等待if (if_save){ShowInExcel(TRUE);}else{//excel_work_book_.Close(COleVariant(short(FALSE)),COleVariant(open_excel_file_),covOptional);excel_books_.Close();}//打开文件的名称清空open_excel_file_.Empty();}excel_sheets_.ReleaseDispatch();excel_work_sheet_.ReleaseDispatch();excel_current_range_.ReleaseDispatch();excel_work_book_.ReleaseDispatch();excel_books_.ReleaseDispatch();
}void IllusionExcelFile::SaveasXSLFile(const CString &xls_file)
{excel_work_book_.SaveAs(COleVariant(xls_file),covOptional,covOptional,covOptional,covOptional,covOptional,0,covOptional,covOptional,covOptional,covOptional,covOptional);return;
}int IllusionExcelFile::GetSheetCount()
{return excel_sheets_.get_Count();
}CString IllusionExcelFile::GetSheetName(long table_index)
{CWorksheet sheet;sheet.AttachDispatch(excel_sheets_.get_Item(COleVariant((long)table_index)),true);CString name = sheet.get_Name();sheet.ReleaseDispatch();return name;
}//按照序号加载Sheet表格,可以提前加载所有的表格内部数据
BOOL IllusionExcelFile::LoadSheet(long table_index,BOOL pre_load)
{LPDISPATCH lpDis = NULL;excel_current_range_.ReleaseDispatch();excel_work_sheet_.ReleaseDispatch();lpDis = excel_sheets_.get_Item(COleVariant((long)table_index));if (lpDis){excel_work_sheet_.AttachDispatch(lpDis,true);excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);}else{return FALSE;}already_preload_ = FALSE;//如果进行预先加载if (pre_load){PreLoadSheet();already_preload_ = TRUE;}return TRUE;
}//按照名称加载Sheet表格,可以提前加载所有的表格内部数据
BOOL IllusionExcelFile::LoadSheet(LPCTSTR sheet,BOOL pre_load)
{LPDISPATCH lpDis = NULL;excel_current_range_.ReleaseDispatch();excel_work_sheet_.ReleaseDispatch();lpDis = excel_sheets_.get_Item(COleVariant(sheet));if (lpDis){excel_work_sheet_.AttachDispatch(lpDis,true);excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true);}else{return FALSE;}//already_preload_ = FALSE;//如果进行预先加载if (pre_load){already_preload_ = TRUE;PreLoadSheet();}return TRUE;
}//得到列的总数
int IllusionExcelFile::GetColumnCount()
{CRange range;CRange usedRange;usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);range.AttachDispatch(usedRange.get_Columns(), true);int count = range.get_Count();usedRange.ReleaseDispatch();range.ReleaseDispatch();return count;
}//得到行的总数
int IllusionExcelFile::GetRowCount()
{CRange range;CRange usedRange;usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true);range.AttachDispatch(usedRange.get_Rows(), true);int count = range.get_Count();usedRange.ReleaseDispatch();range.ReleaseDispatch();return count;
}//检查一个CELL是否是字符串
BOOL IllusionExcelFile::IsCellString(long irow, long icolumn)
{CRange range;range.AttachDispatch(excel_current_range_.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;
}//检查一个CELL是否是数值
BOOL IllusionExcelFile::IsCellInt(long irow, long icolumn)
{CRange range;range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true);COleVariant vResult =range.get_Value2();//好像一般都是VT_R8if(vResult.vt == VT_INT || vResult.vt == VT_R8)       {return TRUE;}return FALSE;
}//
CString IllusionExcelFile::GetCellString(long irow, long icolumn)
{COleVariant vResult ;CString str;//字符串if (already_preload_ == FALSE){CRange range;range.AttachDispatch(excel_current_range_.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;ole_safe_array_.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("%Y-%m-%d");}//单元格空的else if(vResult.vt==VT_EMPTY)   {str="";}  return str;
}double IllusionExcelFile::GetCellDouble(long irow, long icolumn)
{double rtn_value = 0;COleVariant vresult;//字符串if (already_preload_ == FALSE){CRange range;range.AttachDispatch(excel_current_range_.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;ole_safe_array_.GetElement(read_address, &val);vresult = val;}if (vresult.vt==VT_R8)     {rtn_value = vresult.dblVal;}return rtn_value;
}//VT_R8
int IllusionExcelFile::GetCellInt(long irow, long icolumn)
{int num;COleVariant vresult;if (already_preload_ == FALSE){CRange range;range.AttachDispatch(excel_current_range_.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;ole_safe_array_.GetElement(read_address, &val);vresult = val;}//num = static_cast<int>(vresult.dblVal);return num;
}void IllusionExcelFile::SetCellString(long irow, long icolumn,CString new_string)
{COleVariant new_value(new_string);CRange start_range = excel_work_sheet_.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 IllusionExcelFile::SetCellInt(long irow, long icolumn,int new_int)
{COleVariant new_value((long)new_int);CRange start_range = excel_work_sheet_.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 IllusionExcelFile::ShowInExcel(BOOL bShow)
{excel_application_.put_Visible(bShow);excel_application_.put_UserControl(bShow);
}//返回打开的EXCEL文件名称
CString IllusionExcelFile::GetOpenFileName()
{return open_excel_file_;
}//取得打开sheet的名称
CString IllusionExcelFile::GetLoadSheetName()
{return excel_work_sheet_.get_Name();
}//取得列的名称,比如27->AA
char *IllusionExcelFile::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;
}//预先加载
void IllusionExcelFile::PreLoadSheet()
{CRange used_range;used_range = excel_work_sheet_.get_UsedRange(); VARIANT ret_ary = used_range.get_Value2();if (!(ret_ary.vt & VT_ARRAY)){return;}//ole_safe_array_.Clear();ole_safe_array_.Attach(ret_ary);
}

6.这个时候再次编译会出现如下问题,双击出现的错误定位到错误的行,只需在“DialogBox()”前面加一个横杠改为“_DialogBox()”即可

7.这个时候已经对工程文件配置好了,下面就开始进行测试,对Excel进行读写:

8.在工程文件的头文件“COperateExcelByOLEDlg.h”中包含我们刚才添加的头文件,并定义一个“IllusionExcelFile”类的对象“excl”如下:

   

9.在源文件“COperateExcelByOLEDlg.cpp”中的“OnInitDialog()”初始化函数中添加如下代码:

AfxOleInit();
excl.InitExcel();

10.在界面上添加一个按钮控件并为这个按钮添加如下代码(代码里面为了测试,我在电脑的F盘新建了一个“Exce”的文件夹并新建了一个“工作簿1.xlsx”文件,自己也可以根据自己的需求改变路径):

 bool bRet = excl.OpenExcelFile("F:\\Excel\\工作簿1.xlsx"); CString strSheetName = excl.GetSheetName(1);    bool bLoad = excl.LoadSheet(strSheetName);int nRow = excl.GetRowCount();int nCol = excl.GetColumnCount();if (bRet == 1){AfxMessageBox("文件打开成功!");for (int i=1; i<10; ++i){         for (int j=1; j<20; ++j){            CString strValue = excl.GetCellString(i,j);  excl.SetCellInt(i,j,9);}     }}else{AfxMessageBox("文件打开失败!");return ;}excl.SaveasXSLFile("F:\\Excel\\工作簿2.xlsx");AfxMessageBox("文件写入成功!");

11.此时按道理讲,应该就可以运行了

  

12.如果运行的时候报错:“服务器出现意外情况”,看到一篇C#操作Excel报错:服务器出现意外情况,就是自己的电脑安装了福熙阅读器这个软件

解决方案:

打开你电脑中的Office-Excel。在“文件”->"选项"->"加载项"->"管理",选择“COM加载项”,点击“转到”按钮。将“复习阅读器”这个选项不勾选即可

最后,我上传了这个实例教程的工程文件,需要的可以自行下载:https://download.csdn.net/my

因为现在上传好像是自己改不了下载所需积分,因此如果没有积分的朋友可以直接下面评论给我说,我再私发也可以的

VS2010 MFC通过OLE方式读写Excel文件(实例+工程文件)相关推荐

  1. 以OLE方式读写EXCEL的C++类【转载】

    ◆C++中的[L"https://msdn.microsoft.com/library"]. 这个是C++标准规定的写法.详见以下链接: http://bbs.csdn.net/t ...

  2. 一文搞定C#关于NPOI类库的使用读写Excel以及io流文件的写出

    一文搞定C#关于NPOI类库的使用读写Excel以及io流文件的写出 今天我们使用NPOI类库读写xlsx文件, 最终实现的效果如图所示 从太平洋官网下载相应的类库,大概4~5MB,不要从github ...

  3. 【C++】(九)作用域、生命期、头文件和工程文件

    文章目录 作用域和生命期 1 局部变量和全局变量 1.1 局部变量 1.2 全局变量 2 作用域 3 生命期 4 内部函数与外部函数 5 头文件与工程文件 作用域和生命期 1 局部变量和全局变量 1. ...

  4. VS用OLE方式对Excel进行读写操作

    OLE技术(Object Linking and Embedding,对象连接与嵌入)OLE是一种面向对象的技术,利用这种技术可开发可重复使用的软件组件(COM). 一.Excel对象模型. Appl ...

  5. Eclipse java工程中添加文件+导入工程文件

    1.添加源文件 在eclipse上建好java工程,想从别的地方把.java文件加进来,先把.java文件拷贝到src目录下,然后,在src文件夹下按F5刷新就可以了. 2.导入存在的工程文件 在开始 ...

  6. makefile文件:编译工程文件

    其本质是用来编译工程文件(内部可以理解为g++命令),用make命令,实现自动化编译.格式如下: 目标:依赖 (tab) 命令 介绍makefile的最初级版本 当前目录下有 main.cpp tem ...

  7. OLE方式保存Excel文件

    #define PG OlePropertyGet #define PS OlePropertySet #define FN OleFunction #define PR OleProcedure t ...

  8. vs2012 Office2013 读写excel文件

    环境:win7 64+VS2012+Office2013+MFC. 说明:读写excel文件,通常包括1.ODBC数据库实现;2.通过解析Excel表格文件;3.通过OLE/COM的几种实现方法.本文 ...

  9. 【MFC】MFC工程文件详解

    00. 目录 文章目录 00. 目录 01. 概述 02. 解决方案相关文件 03. 工程相关文件 04. 头文件和源文件 05. 资源文件 06. 预编译头文件 07. 编译目标和中间文件 08. ...

最新文章

  1. Microsoft Azure_Fabric
  2. python入门需要多久-零基础小白多久能学会python
  3. Code片段 : .properties属性文件操作工具类 JSON工具类
  4. Boost signals(1) 基本介绍
  5. Winform 的一个多线程绑定DataGrid数据源的例子
  6. at指令代码 stm32f030_stm32+ESP8266AT指令详细说明
  7. 李开复写给大学生的第四封信的一些笔录
  8. 国家机构评测主流电视:长虹人工智能语音识别第一
  9. SQLSERVER2000 存储过程与ORACLE存储过程对比
  10. jQuery-zTree插件使用
  11. Matlab遗传算法TSP求解
  12. 51单片机入门学习 第九天
  13. 如何在电脑上彻底删除Oracle客户端?
  14. 论文记载:A Survey on Traffic Signal Control Methods
  15. 前端JS项目实战——瀑布流
  16. 计算机专业毕业论文结尾,计算机毕业论文最后的总结.docx
  17. CentOS-6.3安装配置JDK-7 - Constantin - 博客园
  18. 如何解决商品秒杀超卖问题
  19. 用示波器实现跳舞视频
  20. 突发!三星天津电池工厂爆炸,难道note7的电池还在生产?

热门文章

  1. alexa skill+自定义oauth2服务完整版教程(保姆级图文教程附demo源码)
  2. AWS — VPC 虚拟专用云
  3. 【啃书C++Primer5】-编写一个简单C++程序
  4. 膜拜共享单车数据分析
  5. 《炬丰科技-半导体工艺》多孔硅的冲洗和干燥研究
  6. 【单片机毕业设计】基于单片机的空气质量(烟雾、有害混合气体)的设计
  7. 股指期货的基差为负值说明什么(股指期货的基差为负值说明什么问题)
  8. Taday——图形界面(3)
  9. 数据仓库:如何解决ODS数据零点漂移问题
  10. 基于c++的opencv学习记录