根据微软的技术文章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
/******************************************************************************
* 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
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
不知道跟这个有没有关系
IDispatch* Temp;
Temp = V_app.get_ActiveCell();
V_range.AttachDispatch(Temp);
单步检查Temp的值,返回的不是NULL
为什么你要用一个表达式生成的临时的值作为参数?