VS2010对Excel2010进行操作

本文详细介绍如何使用VC通过OLE/COM接口操作Excel,包括创建、读写Excel文件及图表,适用于Windows平台下的自动化办公场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://blog.youkuaiyun.com/xiaoxiangyuan123456/article/details/70941588


1.引言
通过VC实现对Excel表格的操作的方法有多种,如:通过ODBC数据库实现,通过解析Excel表格文件,通过OLE/COM的实现。本文主要研究通过OLE/COM实现对Excel表格的操作。

 

本文源码的应用环境说明:

Windows7 X64

Microsoft Visual Studio 2010

Microsoft Office Excel 2010

 

2.准备工作
1.导入并封装Excel的接口
Excel作为OLE/COM库插件,定义好了各类交互的接口,这些接口是跨语言的接口。VC可以通过导入这些接口,并通过接口来对Excel的操作。由于本文只关心对Excel表格中的数据的读取,主要关注几个_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range等几个接口。Excel的各类接口的属性、方法可以通过MSDN的Office Development进行查询。VS2010导入OLE/COM组件的接口的步骤为:Project->ClassWizard->Add Class->MFC Class From TypeLib,先选择要导入的组件所在的路径,即Excel.exe所在的路径,然后再选择要导入的Excel类型库中的接口。具体操作如图所示:

在完成接口导入后,VS2010将自动为导入的接口创建相应的实现类,用于对接口属性和方法的实现。由于标准的C++没有属性访问器,只能添加一个两个存取函数来实现对属性的访问,通过在属性名称前加上get_和put_前缀分别实现对属性的读写操作。即,由VC自动完成C++类对接口的封装。

本文所导入的接口对应的类和头文件的说明如下所示:

Application

CApplicaton

Application.h

Excel应用程序。

Workbooks

CWorkbooks

Workbooks.h

工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。

_Workbook

CWorkbook

Workbook.h

单个工作簿。

Worksheets

CWorksheets

Worksheets.h

单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。

_Worksheet

CWorksheet

Worksheet.h

单个Sheet表格。

Range

CRange

Range.h

一定数量的单元格,可对单元格进行单个或多个单元格进行操作。

备注:1.导入接口类后,将CApplication、CWorkbooks、CWorkbook、CWorksheet、CWorksheets、CRange类头文件中的#import语句屏蔽。如下所示:

    2.在stafx.h文件中加入以下头文件包含语句:

#include <afxdisp.h>        // MFCAutomation classes

#include "CApplication.h"

#include "CRange.h"

#include "CWorkbook.h"

#include "CWorkbooks.h"

#include "CWorksheet.h"

#include "CWorksheets.h"

2. 添加OLE/COM支持
应用程序必须添加对OLE/COM的支持,才能导入OLE/COM组件。本文使用的是MFC对话框程序,在创建工程的向导中选中Automation选项即可为程序自动添加相应的头文件和OLE库初始化代码。在App类中的InitInstance()加入如下语句:

      if (CoInitialize(NULL)!= 0)

      {

           AfxMessageBox(_T("初始化失败"));

           exit(1);

      }

用ClassWizard给App类添加虚函数ExitInstance(),在ExitInstance()中加入如下语句,进行com库资源释放.

CoUninitialize();  //释放com资源

现在运行程序会出现一个错误,双击错误提示,定位在错误行,

VARIANT DialogBox()

{

VARIANT result;

InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT, (void*)&result, NULL);

return result;

}

将该函数名“DialogBox()”前面加“_”下划线,即“_DialogBox()”,这样就可以编译成功了。

3.操作Excel
1.原理


Excel操作原理图

其中Application是Excel应用程序,每个Application都有一个工作薄容器Workbooks,工作薄容器中存放着所有的工作簿Workbook,我们平常打开的Excel都是一个工作簿;而每个工作簿中都有一个工作表容器Worksheets,工作表容器中存放着所有的工作表Worksheet;每个工作表中都许多有单元格Range。往Excel单元格中写入内容的过程就是这样一层层往下遍历。

2.操作Excel
操作Excel的主要步骤如下:

(1)创建一个Excel应用程序。

(2)得到Workbook的容器。

(3)打开一个Workbook或者创建一个Workbook。

(4)得到Workbook中的Worksheet的容器。

(5)打开一个Worksheet或者创建一个WorkSheet。

(6)通过Range对WorkSheet中的单元格进行读写操作。

(7)保存Excel。

(8)释放资源。

 具体代码如下所示:

    CApplication ExcelApp;
    CWorkbooks wbsMyBooks;
    CWorkbook wbMyBook;
    CWorksheets wsMySheets;
    CWorksheet wsMySheet; 
    CRange rgMyRge;
    CChart chart;
    CChartObjects chartObjects;        //图表容器对象
    CChartObject chartObject;        //图表对象
 
    COleVariant
        covTrue((short)TRUE),
        covFalse((short)FALSE),
        covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
 
    LPDISPATCH lpDisp = NULL;
 
    //创建一个EXCEL应用程序实例
    if (!ExcelApp.CreateDispatch(_T("Excel.Application"), NULL))
    {
        AfxMessageBox(_T("创建Excel程序失败"));
        exit(1);
    }
 
    ExcelApp.put_Visible(TRUE);   //使程序可见
    ExcelApp.put_UserControl(FALSE);
 
    //将工作簿容器对象与应用程序工作簿关联
    wbsMyBooks.AttachDispatch(ExcelApp.get_Workbooks());
 
    //打开一个工作簿,如果不存在,则新增一个工作簿
    CString strFile = _T("C:\\Users\\Administrator\\Desktop\\123.xlsx");
 
    try
    {
        //打开一个工作簿
        lpDisp = wbsMyBooks.Open(strFile, vtMissing, vtMissing, vtMissing, vtMissing,
                    vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
                    vtMissing, vtMissing, vtMissing, vtMissing, vtMissing);
        //将工作簿对象和打开的工作簿关联
        wbMyBook.AttachDispatch(lpDisp);
    }
    catch (...)
    {
        //增加一个新的工作簿
        lpDisp = wbsMyBooks.Add(vtMissing);
        wbMyBook.AttachDispatch(lpDisp);
    }
 
    //获得工作表容器对象实例
    wsMySheets.AttachDispatch(wbMyBook.get_Sheets());
 
    //打开一个工作表,如果不存在则新增一个
    CString strSheetName = _T("NewSheet");
 
    try
    {
        //打开一个已有的工作表(wooksheet)
        lpDisp = wsMySheets.get_Item(_variant_t(strSheetName));
        wsMySheet.AttachDispatch(lpDisp);
    }
    catch(...)
    {
        lpDisp = wsMySheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
        wsMySheet.AttachDispatch(lpDisp);
        wsMySheet.put_Name(strSheetName);     //创建工作表名
    }
 
    system("pause");
 
    /************************************************************************/
    /* 添加单元格数据之方法二                                                                     */
    /************************************************************************/
    //设置单元格的范围为全部区域
    lpDisp = wsMySheet.get_Cells();
    rgMyRge.AttachDispatch(lpDisp);
 
    //插入标题
    rgMyRge.put_Item(_variant_t((LONG)1),_variant_t((LONG)1),_variant_t("X"));
    rgMyRge.put_Item(_variant_t((LONG)1),_variant_t((LONG)2),_variant_t("Y1"));
    rgMyRge.put_Item(_variant_t((LONG)1),_variant_t((LONG)3),_variant_t("Y2"));
 
    // 将数据填入Excel表格
    for (int i = 0; i < 8; i++)
    {
        rgMyRge.put_Item(_variant_t((LONG)(2+i)),_variant_t((LONG)1),_variant_t((long)(i+1)));
        rgMyRge.put_Item(_variant_t((LONG)(2+i)),_variant_t((LONG)2),_variant_t((long)((i+1)*(i+1))));
        rgMyRge.put_Item(_variant_t((LONG)(2+i)),_variant_t((LONG)3),_variant_t((long)((i+1)*2)));
    }
 
    //////////////////////////////////////////////图表操作//////////////////////////////////////////
    //图表chart
    double left = 200;
    double top = 160;
    double width = 450;
    double height = 260;
 
    //关联图表容器对象
    lpDisp = wsMySheet.ChartObjects(covOptional);
    ASSERT(lpDisp);
    chartObjects.AttachDispatch(lpDisp);
 
    //新建一个图表对象
    chartObject = chartObjects.Add(left, top, width, height);
 
    //关联图表对象
    lpDisp = chartObject.get_Chart();
    chart.AttachDispatch(lpDisp);
 
    chart.put_ChartType(72);   //设置图表类型
 
    //设置数据的有效区域
    lpDisp = wsMySheet.get_Range(COleVariant(_T("B1")), COleVariant(_T("C9")));
    ASSERT(lpDisp);
 
    VARIANT var;
    var.vt = VT_DISPATCH;
    var.pdispVal = lpDisp;
 
    chart.ChartWizard(var,                // Source.
        covOptional,  // Gallery
        covOptional,   // Format: 1~6.
        COleVariant((short)2),   // PlotBy: 指定系列中的数据是来自行(1)还是来自列(2).
        COleVariant((short)0),   // CategoryLabels.
        COleVariant((short)1),   // SeriesLabels.
        COleVariant((short)TRUE),  // HasLegend.
        COleVariant(_T("chart title")),  // Title.
        COleVariant(_T("XXX")),    // CategoryTitle.
        COleVariant(_T("YYY")),  // ValueTitles.
        covOptional              // ExtraTitle.
        );
 
    system("pause");
    ////////////////////////////////////////////////////////////////////////////////////////////
 
    /*根据文件的后缀名选择保存文件的格式*/
    CString strSaveAsName = _T("C:\\new.xlsx");
 
    wbMyBook.SaveCopyAs(_variant_t(strSaveAsName));
    wbMyBook.put_Saved(TRUE);
    ExcelApp.put_Visible(TRUE);
 
    system("pause");
 
    //释放资源
    chart.ReleaseDispatch();
    chartObject.ReleaseDispatch();
    chartObjects.ReleaseDispatch();
    rgMyRge.ReleaseDispatch();
    wsMySheet.ReleaseDispatch();
    wsMySheets.ReleaseDispatch();
    wbMyBook.ReleaseDispatch();
    wbsMyBooks.ReleaseDispatch(); 
    ExcelApp.ReleaseDispatch();
    ExcelApp.Quit();
4.参考文献
1.http://www.cnblogs.com/xianyunhe/archive/2011/09/25/2190485.html

2.http://www.cnblogs.com/yaowen/archive/2013/01/22/2870762.html

3.http://blog.youkuaiyun.com/stephen_kong/article/details/1362469
--------------------- 
作者:时光小偷的老巢 
来源:优快云 
原文:https://blog.youkuaiyun.com/xiaoxiangyuan123456/article/details/70941588 
版权声明:本文为博主原创文章,转载请附上博文链接!

【前言】 工作或学习中可能需要实现基于VC读\写Excel文件的功能,本人最近也遇到了该问题。中间虽经波折,但是最终还是找到了解决问题的办法。 在此跟大家分享,希望对跟我同样迷茫过的同学们有所帮助。 1、程序功能 1)打开一个excel文件; 2)显示到CListCtrl上; 3)新建一个Excel文件。 以上均在对话框中实现。 2、平台 VC++2010 3、实现方法 常用的Excel打开方式有两种 1)通过数据库打开; 2)OLE方式打开。 由于方式1)操作繁琐,经常出现莫名的错误,这里选用方式2). 4、准备步骤 首先新建一个Dialog窗体程序,添加list control和两个按钮 1)将ExcelLib文件夹拷贝到程序目录下; 2)将Export2Excel.h,Export2Excel.cpp两个文件添加到项目; 3)包含头文件,#include "ExcelLib/Export2Excel.h" 通过以上步骤在程序中引入了可以读取Excle文件的CExport2Excel类; 5、打开excel文件 通过按钮点击打开 void CExcelTestDlg::OnBnClickedButtonOpenExcel() { //获取文件路径 CFileDialog* lpszOpenFile; CString szGetName; lpszOpenFile = new CFileDialog(TRUE,"","",OFN_FILEMUSTEXIST|OFN_HIDEREADONLY,"Excel File(*.xlsx;*.xls)|*.xls;*.xlsx",NULL); if (lpszOpenFile->DoModal()==IDOK) { szGetName = lpszOpenFile->GetPathName(); SetWindowText(szGetName); delete lpszOpenFile; } else return; //打开文件 //文件中包含多个sheet时,默认打开第一个sheet CExport2Excel Excel_example; Excel_example.OpenExcel(szGetName); //获取sheet个数 int iSheetNum = Excel_example.GetSheetsNumber(); //获取已使用表格行列数 int iRows = Excel_example.GetRowCount(); int iCols = Excel_example.GetColCount(); //获取单元格的内容 CString cs_temp = Excel_example.GetText(1,1); //AfxMessageBox(cs_temp); //List control上显示 //获取工作表列名(第一行) CStringArray m_HeadName; m_HeadName.Add(_T("ID")); for (int i=1;iGetItemCount()>0) { m_list.DeleteColumn(0); } //初始化ClistCtrl,加入列名 InitList(m_list,m_HeadName); //填入内容 //第一行是标题,所以从第2行开始 CString num; int pos; for (int row = 2;row<=iRows; row++) { pos = m_list.GetItemCount(); num.Format(_T("%d"),pos +1); m_list.InsertItem(pos,num); for (int colum=1;columDoModal()==IDOK) { szGetName = lpszOpenFile->GetPathName(); SetWindowText(szGetName); delete lpszOpenFile; } else return; //文件全名称 CString csFileName = szGetName; //需要添加的两个sheet的名称 CString csSheetName = "newSheet"; CString csSheetName2 = "newSheet2"; // 新建一个excel文件,自己写入文字 CExport2Excel Excel_example; //新建excel文件 Excel_example.CreateExcel(csFileName); //添加sheet,新加的sheet在前,也就是序号为1 Excel_example.CreateSheet(csSheetName); Excel_example.CreateSheet(csSheetName2); //操作最开始添加的sheet:(newSheet) Excel_example.SetSheet(2); //添加表头 Excel_example.WriteHeader(1,"第一列"); Excel_example.WriteHeader(2,"第二列"); //添加核心数据 Excel_example.WriteData(1,1,"数据1"); Excel_example.WriteData(1,2,"数据2"); //保存文件 Excel_example.Save(); //关闭文件 Excel_example.Close(); } 7、注意事项 1)一般单个Excel文件包含多个sheet,程序默认打开第一个; 2)指定操作sheet,使用Excel_example.SetSheet(2)函数; 3)打开文件时最左侧的sheet序号为1,新建excel时最新添加的sheet序号为1. 【后记】 本程序主要基于网络优快云中---“Excel封装库V2.0”---完成,下载地址是:http://download.youkuaiyun.com/detail/yeah2000/3576494,在此表示感谢!同时, 1)在其基础上作了小改动,改正了几个小错误,添加了几个小接口; 2)添加了如何使用的例子,原程序是没有的; 3)详细的注释 发现不足之处,还请大家多多指教!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值