none
关于visual c++操作Excel 的问题 RRS feed

  • 问题

  • 我想使用VC++操作EXCEL,找出一张表的所有相同项,并返回其地址,在期间用到Find和FindNext,Find能找到第一个,且返回了地址,用FindNext循环查找,总是找到和Find相同的项,且不往下继续。我怀疑参数设置问题,请高手看看。最好能给出代码,本人初学!谢谢! // TODO: 在此添加控件通知处理程序代码
     //记录工作表总数.
     int iSheetNums=0;
     //记录工作表中找到的行数,列数,找到的MAC地址总数(不能大于1)
     int iNumRows=0,iNumCols=0,iMacNum=0;
     CString strFindFirst(""),strFindNext;
     
     _Application app;
     Workbooks books;
     _Workbook book;
     Worksheets sheets;
     _Worksheet sheet;
     //记录工作表总Range,行Range,列Range
     Range range,rgTotal,rgRows,rgCols,rgtemp;
     Font font;

     //接口指针
     LPDISPATCH lpDisp,lpDispTemp=NULL;

     COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR),covTemp;
     if( !app.CreateDispatch("Excel.Application") )
     {
      this->MessageBox("无法创建Excel应用!");
      return;
     }
     
     app.SetVisible(TRUE);
     books=app.GetWorkbooks();
     lpDisp = books.Open(CStringToFilePath(m_strFilePath),covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional, covOptional, covOptional);
     book.AttachDispatch( lpDisp );
     sheets=book.GetSheets();
     //工作表总数
     iSheetNums=sheets.GetCount();

     for(int i=1;i<=1;i++)
     {
      sheet = sheets.GetItem(COleVariant((short)i));
      sheet.Activate();

      rgTotal.AttachDispatch(sheet.GetUsedRange());
      lpDisp=rgTotal.Find(COleVariant("0018-82B1-69B6"),covOptional,COleVariant((long)-4123),COleVariant((long)2),COleVariant((long)1),(long)1,COleVariant((long)0),COleVariant((long)0),covOptional);
      range.AttachDispatch(lpDisp);
      range.Select();
      range.Activate();
      strFindNext=range.GetAddress(covOptional,covOptional,(long)1,covOptional,covOptional);
      range.SetFormula(COleVariant("tempstring"));
      while(lpDisp)
      {
       if(strFindFirst.IsEmpty())
        strFindFirst=strFindNext;
       else
       {
        lpDisp=rgTotal.FindNext(covOptional);
        range.AttachDispatch(lpDisp);
        range.Select();
        range.Activate();
        strFindNext=range.GetAddress(covOptional,covOptional,(long)1,covOptional,covOptional);
       }
      }
      

     }

    /* for (int i=1;i<=1;i++)
     {
      sheet = sheets.GetItem(COleVariant((short)i));
      sheet.Activate();

      rgTotal.AttachDispatch(sheet.GetUsedRange());
    //  rgCols.AttachDispatch(rgTotal.GetColumns());
    //  rgRows.AttachDispatch(rgTotal.GetRows());

    //  iNumRows=rgRows.GetCount();
    //  iNumCols=rgCols.GetCount();

    //  range.AttachDispatch(sheet.GetUsedRange());
    //  range.AttachDispatch(rgTotal.Find(COleVariant("0018-82B1-69B6"),covOptional,COleVariant((long)-4123),COleVariant((long)2),COleVariant((long)1),(long)1,COleVariant((long)0),COleVariant((long)0),covOptional));
    //  covTemp=rgtemp.Activate();
    //  range.GetAddress(covOptional,covOptional,(long)1,covOptional,covOptional);
      

      lpDisp=rgTotal.Find(COleVariant("0018-82B1-69B6"),covOptional,COleVariant((long)-4123),COleVariant((long)2),COleVariant((long)1),(long)1,COleVariant((long)0),COleVariant((long)0),covOptional);
      range.AttachDispatch(lpDisp);
      range.Select();
      range.Activate();
      strFindFirst=range.GetAddress(covOptional,covOptional,(long)1,covOptional,covOptional);
      CStringToNumString(strFindFirst);
      if(lpDisp)
      {
    //   range.SetFormula(range.GetFormula());
       rgtemp.AttachDispatch(app.GetActiveCell());
       iMacNum=iMacNum+1;
       do
       {
        lpDispTemp=rgTotal.FindNext(rgtemp.Select());
        range.AttachDispatch(lpDispTemp);
    //    range.SetFormula(range.GetFormula());
    //    range.GetFormula();
        strFindNext=range.GetAddress(covOptional,covOptional,(long)1,covOptional,covOptional);
        range.Select();
        range.Activate();
        if(strFindNext!=strFindFirst)
         iMacNum=iMacNum+1;
       }
       while(lpDispTemp!=NULL);
      }
      if(iMacNum>1)
      {
       AfxMessageBox("找到的MAC地址大于1个,不唯一,请仔细检查EXCEL表!");
       book.SetSaved(TRUE);
       book.Close(covOptional,COleVariant(CStringToFilePath(m_strFilePath)),covOptional);
       books.Close();
       app.Quit();
       return;
      }
     }*/
    // sheet=sheets.GetItem(COleVariant((short)1));
    // range=sheet.GetRange(COleVariant("A1"),COleVariant("A1"));
    // COleVariant rValue,gValue;
    // rValue=COleVariant(range.GetValue(gValue));
    // rValue.ChangeType(VT_BSTR);
    // this->MessageBox(CString(rValue.bstrVal));
     book.SetSaved(TRUE);
     book.Close(covOptional,COleVariant(CStringToFilePath(m_strFilePath)),covOptional);
     books.Close();
     app.Quit();
    }

     

    2009年11月3日 3:03

答案

  • 非常感谢各位的热心帮助,有位朋友帮我找到了,我把方法写在下面.
    头文件:
    #include "excel9.h"
    #include <COMUTIL.h>
    #pragma comment(lib, "comsupp.lib")

    然后:
    lpDisp=rgTotal.FindNext((_variant_t)range);
    这样循环就继续了!

    • 已标记为答案 killfish 2009年11月6日 1:57
    2009年11月6日 1:57

全部回复

  • HI,

    通常这样的问题可以通过在Excel中手动操作然后录制VBA宏,通过查看VBA代码来解决,下面是Excel自动生成的代码,可以发现这是一种类似迭代的做法,以每次找到的当前单元格为起点往下继续找。

    Sub Macro1()
    '
    ' Macro1 Macro
    '

    '
        Cells.Find(What:="s", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
            xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
            , SearchFormat:=False).Activate
        Cells.FindNext(After:=ActiveCell).Activate
        Cells.FindNext(After:=ActiveCell).Activate
    End Sub


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    2009年11月4日 9:49
  • 首先非常感谢您的回复,我是用VC做工程,参考VB的代码,我现在无法解决问题,网上资料太多VB了,VC的少啊,还请大侠帮忙!感谢为盼。

    • 已编辑 killfish 2009年11月4日 23:19 写错字符了
    2009年11月4日 23:18
  • 首先非常感谢您的回复,我是用VC做工程,参考VB的代码,我现在无法解决问题,网上资料太多VB了,VC的少啊,还请大侠帮忙!感谢为盼。


    FindNext参数要指定 After,就是在当前Range之后查找,看你的问题好像是从当前Range开始查找,所以就找到自己了.

    你要还改不了,可以把Excel和源代码发给我,我帮你调试.
    2009年11月5日 6:23
  • vba 和C++里面用的对象模型是一样的,都是Excel 12.0 Object Library, 所以只要把vb的写法写成c++就可以了。

    关键是这句
      lpDisp=rgTotal.FindNext(covOptional);
    执行完了以后加上lpDisp.Actvate()
    把这个range设置成活动单元格然后再往下找应该就可以了

    Thanks.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    2009年11月5日 8:09
  • 板主,你好,我这样弄了,    range.AttachDispatch(app.GetActiveCell());还是不行啊,搭个环境帮我测试下吗
    lpDisp.Actvate()这样编译也通不过啊。

    2009年11月5日 11:27
  • 非常感谢各位的热心帮助,有位朋友帮我找到了,我把方法写在下面.
    头文件:
    #include "excel9.h"
    #include <COMUTIL.h>
    #pragma comment(lib, "comsupp.lib")

    然后:
    lpDisp=rgTotal.FindNext((_variant_t)range);
    这样循环就继续了!

    • 已标记为答案 killfish 2009年11月6日 1:57
    2009年11月6日 1:57