VC中实现读取Excel表数据总结

利用VC对Excel进行操作。主要的函数是从网上找的,有些东西自己做了修改。可以对一个目录下的所有Excel表进行处理。主要代码如下:
 
//获取一个目录下所有Excel表名,并加入到一个数组中。
char oldPath[MAX_PATH];
 getcwd(oldPath,MAX_PATH);
 chdir(m_strDirectory);
 CFileFind fileFind;
 BOOL bExist=FALSE;
 bExist=fileFind.FindFile("*.xls");
 while(bExist)
 {
  bExist=fileFind.FindNextFile();
  CString strTitle=fileFind.GetFileTitle(); 
  m_strTableAll.Add(strTitle);
 }
 fileFind.Close();
 chdir(oldPath);
 
 
//处理所有Excel数据,并把所有数据加入到一个二维数组中
CString m_strArray[i][j]
 
CoInitialize(NULL);
 int i,j;  //用来循环
 // 获得EXCEL的CLSID
 CLSID clsid;
 HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
 
 if(FAILED(hr)) {
  AfxMessageBox("CLSIDFromProgID() 函数调用失败!");
  return;
 }
 
 // 创建实例
 IDispatch *pXlApp;
 hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pXlApp);
 if(FAILED(hr)) {
  AfxMessageBox("请检查是否已经安装EXCEL!");
  return;
 }
 
 // 显示,将Application.Visible属性置1
 /VARIANT x;
 x.vt = VT_I4;
 x.lVal = 1;
 AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L"Visible", 1, x);
 // 获取Workbooks集合
 IDispatch *pXlBooks;
 {
  VARIANT result;
  VariantInit(&result);
  AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"Workbooks", 0);
  pXlBooks = result.pdispVal;
 }
 
 CString strName;  //Excel表完整路径
 CString strTmp;   //临时变量,保存单元格数据中的CString型
 double dblTmp;   //临时变量,保存单元格数据中的double型
 //用来保存信息的数组
 VARIANT arr;
 arr.vt = VT_ARRAY | VT_VARIANT;
 SAFEARRAYBOUND sab[2];
 sab[0].lLbound = 1; sab[0].cElements = 40;
 sab[1].lLbound = 1; sab[1].cElements = 16;
 arr.parray = SafeArrayCreate(VT_VARIANT, 2, sab);
 int tableNum;
 int nCount=m_DataConn.m_strTableAll.GetSize(); 
 for(tableNum=0;tableNum<nCount;tableNum++)
 {
  strName.Format("%s//%s",m_DataConn.m_strDirectory,m_DataConn.m_strTableAll.GetAt(tableNum));
    
  // 调用Workbooks.Open()方法,打开一个已经存在的Workbook
  IDispatch *pXlBook;
  {
   VARIANT parm;
   parm.vt = VT_BSTR;
   // parm.bstrVal = ::SysAllocString(L"'strName'");
   parm.bstrVal=strName.AllocSysString();
   VARIANT result;
   VariantInit(&result);
   AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBooks, L"Open", 1,parm);
   pXlBook = result.pdispVal;
  }
  
  // 初始化数组内容
  /*
  for(int i=1; i<=15; i++) {
  for(int j=1; j<=15; j++) {
  VARIANT tmp;
  tmp.vt = VT_BSTR;
  wsprintfW(szTmp,L"%i,%i",i,j);
  tmp.bstrVal = SysAllocString(szTmp);
  // 添加数据到数组中
  long indices[] = {i,j};
  SafeArrayPutElement(arr.parray, indices, (void *)&tmp);
  }
  }
  */
  // 从Application.ActiveSheet属性获得Worksheet对象
  IDispatch *pXlSheet;
  {
   VARIANT result;
   VariantInit(&result);
   AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"ActiveSheet", 0);
   pXlSheet = result.pdispVal;
  }
  
  // 选择一个16x40大小的Range
  IDispatch *pXlRange;
  {
   VARIANT parm;
   parm.vt = VT_BSTR;
   parm.bstrVal = ::SysAllocString(L"A1:P40");
   
   VARIANT result;
   VariantInit(&result);
   AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheet, L"Range", 1, parm);
   VariantClear(&parm);
   
   pXlRange = result.pdispVal;
  }
  // 用这个Range读取数据
  AutoWrap(DISPATCH_PROPERTYGET, &arr, pXlRange, L"Value",0);
  for(i=1; i<=40; i++)
  {
   for(j=1; j<=16; j++)
   {
    VARIANT tmp;
    //tmp.vt = VT_BSTR;
    // 添加数据到数组中
    long indices[] = {i,j};
    SafeArrayGetElement(arr.parray, indices, (void *)&tmp);
    if(tmp.vt ==VT_BSTR)
    {
     strTmp=tmp.bstrVal;
    }
    else if(tmp.vt==VT_R8)
    {
     dblTmp=tmp.dblVal;
     strTmp.Format("%f",dblTmp);
    }
    else if(tmp.vt=VT_NULL)
    {
     strTmp="";
    }
    _bstr_t str1=strTmp; 
    WCHAR *str2=str1;
    pDoc->m_strArray[tableNum*40+i][j]=str2;
   }
  }
  AutoWrap(DISPATCH_METHOD, NULL, pXlBook, L"Close", 0);
  VariantClear(&arr);
  pXlRange->Release();
  pXlSheet->Release();
  pXlBook->Release();
 }
 // 退出,调用Application.Quit()方法
 // 释放所有的接口以及变量
 AutoWrap(DISPATCH_METHOD, NULL, pXlApp, L"Quit", 0);
 pXlBooks->Release();
 pXlApp->Release();
 
 // 注销COM库
 CoUninitialize();
 
//**********************//
// AutoWrap 函数的正体
// 先声明:这个函数不是偶写的
// AutoWrap() - Automation helper function...
HRESULT CExcelView::AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...)
{
    // Begin variable-argument list...
    va_list marker;
    va_start(marker, cArgs);
    if(!pDisp) {    
  AfxMessageBox("NULL IDispatch passed to AutoWrap()");
        _exit(0);
    }
    // Variables used...
    DISPPARAMS dp = { NULL, NULL, 0, 0 };
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    DISPID dispID;
    HRESULT hr;
    char buf[200];
    char szName[200];
    // Convert down to ANSI
    WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
    // Get DISPID for name passed...
    hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
    if(FAILED(hr)) {
        sprintf(buf, "IDispatch::GetIDsOfNames(/"%s/") failed w/err 0x%08lx", szName, hr);
        AfxMessageBox(buf);
        _exit(0);
        return hr;
    }
    // Allocate memory for arguments...
    VARIANT *pArgs = new VARIANT[cArgs+1];
    // Extract arguments...
    for(int i=0; i<cArgs; i++) {
        pArgs[i] = va_arg(marker, VARIANT);
    }
    // Build DISPPARAMS
    dp.cArgs = cArgs;
    dp.rgvarg = pArgs;
    // Handle special-case for property-puts!
    if(autoType & DISPATCH_PROPERTYPUT) {
        dp.cNamedArgs = 1;
        dp.rgdispidNamedArgs = &dispidNamed;
    }
    // Make the call!
    hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL);
    if(FAILED(hr)) {
        sprintf(buf, "IDispatch::Invoke(/"%s/"=%08lx) failed w/err 0x%08lx", szName, dispID, hr);
        AfxMessageBox(buf);
        _exit(0);
        return hr;
    }
    // End variable-argument section...
    va_end(marker);
    delete [] pArgs;
    return hr;
}
 
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【前言】 工作或学习可能需要实现基于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. 【后记】 本程序主要基于网络CSDN---“Excel封装库V2.0”---完成,下载地址是:http://download.csdn.net/detail/yeah2000/3576494,在此示感谢!同时, 1)在其基础上作了小改动,改正了几个小错误,添加了几个小接口; 2)添加了如何使用的例子,原程序是没有的; 3)详细的注释 发现不足之处,还请大家多多指教!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值