根据微软的技术文章Article ID: 309301 - HOW TO: Handle Events for Excel by Using Visual C++ .NET,在VC工程中自动生成了用于接收处理excel事件的代码:
/******************************************************************************
*   Invoke -- Takes a dispid and uses it to call another of this class's 
*   methods. Returns S_OK if the call was successful.
******************************************************************************/ 
STDMETHODIMP CAppEventListener::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
                                  WORD wFlags, DISPPARAMS* pDispParams,
                                  VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
                                  UINT* puArgErr)
{
   switch(dispIdMember){
   case 0x00622:
      if(pDispParams->cArgs !=2)
         return E_INVALIDARG;
      else
      {
         if(pDispParams->rgvarg[1].vt & VT_BYREF)
         {
            HandleBeforeWorkbookClose( // Call the function.
               *(pDispParams->rgvarg[1].ppdispVal),
               pDispParams->rgvarg[0].pboolVal);
         }
         else
         {
            HandleBeforeWorkbookClose(  // Call the function.
               (pDispParams->rgvarg[1].pdispVal),
               pDispParams->rgvarg[0].pboolVal);
         }
      }   case 0x0061c:
      {
         if(pDispParams->rgvarg[1].vt & VT_BYREF)
         {
            HandleSheetChange( // Call the function.
               *(pDispParams->rgvarg[1].ppdispVal),
               *(pDispParams->rgvarg[0].ppdispVal));
         }
         else
         {
               HandleSheetChange(  // Call the function.
               pDispParams->rgvarg[1].pdispVal,
               pDispParams->rgvarg[0].pdispVal);
         }
      }
      break;
   }
   return S_OK;
}……
/******************************************************************************
*  HandleSheetChange -- This method processes the SheetChange event for the 
*  application attached to this event handler.
******************************************************************************/ 
STDMETHODIMP CAppEventListener::HandleSheetChange( IDispatch* xlSheet, 
                                                  IDispatch* xlRange)
{
   OutputDebugString("HandleSheetChange\n");

   COleVariant
      covTrue((short)TRUE),
      covFalse((short)FALSE),
      covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); CApplication V_app;
CWorkbook V_book;
CWorksheet V_sheet;
CRange0 V_range;
long V_Row    = 0;
long V_Column = 0;

V_sheet.AttachDispatch(xlSheet);
V_app=V_sheet.get_Application();
V_range.AttachDispatch(V_app.get_ActiveCell());
V_book=V_app.get_ActiveWorkbook(); V_Column=V_range1.get_Column();
V_Row=V_range1.get_Row();  V_range.put_Value2(COleVariant("测试成功!"));

   HRESULT hr = S_OK;
   return hr;
}请教:
1)红色部分为我加的代码,虽然能运行,但总是出问题,不知道为什么:
 执行V_range.put_Value2(COleVariant("测试成功!"));这句代码时总是提示内存访问冲突!
2)HandleSheetChange( IDispatch* xlSheet, IDispatch* xlRange)为什么要带两个参数?应该怎么样分别使用?
   在上面的代码里面,我只用了IDispatch* xlSheet

解决方案 »

  1.   

    http://support.microsoft.com/kb/309301/zh-cn
      

  2.   

    查看下V_range.AttachDispatch(V_app.get_ActiveCell()); 这句是否成功。怀疑V_app.get_ActiveCell()返回为NULL。
      

  3.   


    4楼真是高人!我也怀疑这一句可能有问题!希望继续指点,先谢谢了!
       1)不过刚才单步执行发现返回值应该不是0,因为我检查后面这两句执行的结果,行和列都是对的,就是点击的那个单元格:
       V_Column=V_range1.get_Column();
       V_Row=V_range1.get_Row();    2)我把V_range.put_Value2(COleVariant("测试成功!")); 一句注销掉,
          可以单步执行到return hr;
          但当我点击run让程序继续运行时,就会发现在VC的输出窗口出现如下提示:
         “test3.exe 中的 0x77122f7e 处最可能的异常: 0xC0000005: 读取位置 0xfeeefef6 时发生访问冲突 。”
        也就是问题不是出在这个函数体里面???
       3)当我恢复V_range.put_Value2(COleVariant("测试成功!")); 这一句
          不设断点一运行就会出现出现大量的
         “test3.exe 中的 0x77122f7e 处最可能的异常: 0xC0000005: 读取位置 0xfeeefef6 时发生访问冲突 。”
          可能是因为这一句修改了单元个内容使得重新进入该函数,变成了一个循环。
       4)当我单步运行,发现每次运行到V_range.put_Value2(COleVariant("测试成功!")); 这一句
          执行完毕后,V_range里面的m_lpDispatch就会变成了0x00000000
          不知道跟这个有没有关系
      

  4.   

    先判断下V_app.get_ActiveCell();返回值是否为NULL?
      

  5.   

    我把代码改成:
    IDispatch* Temp;
    Temp = V_app.get_ActiveCell();
    V_range.AttachDispatch(Temp);
    单步检查Temp的值,返回的不是NULL
      

  6.   

    0xfeeefef6说明变量在被销毁了之后才使用……
    为什么你要用一个表达式生成的临时的值作为参数?
      

  7.   

    0xfeeefef6说明变量在被销毁了之后才使用