最近的项目中需要利用VC操作Excel进行自动化输出,期间碰到网上很多朋友遇到的一个问题,无法正常关闭Excel。经过琢磨,总结如下:
1、 原因:由于使用了Range的GetItem()函数获取Excel表中内容,所以程序在调用了_Application的Quit()函数后,Excel进程不能马上关闭,整个程序退出时,Excel将关闭。若注释了调用GetItem()的代码,将可以正常关闭。内部原因不知。
2、 解决办法,不使用GetItem()获取Excel中内容,而使用其他方法。如下代码介绍读取数据的一种方法:
- BOOL CAutomationExcel::GetValue(int iRow,int iColumnStart,int iColumnStop,CStringArray& strarray)
- {
- int iElementCount = iColumnStop - iColumnStart + 1;
- if(iElementCount <= 0)
- return FALSE;
- CString strStart,strEnd;
- _variant_t start,stop;
- strStart = GetItemName(iRow,iColumnStart);
- start.vt = VT_BSTR;
- start.bstrVal = strStart.AllocSysString(); // 不需要进行_bstr_t转换
- strEnd = GetItemName(iRow,iColumnStop);
- stop.vt = VT_BSTR;
- stop.bstrVal = strEnd.AllocSysString();
- // 创建安全数组,从Excel中读取内容
- _variant_t varReturn;
- varReturn.vt = VT_ARRAY | VT_VARIANT;
- SAFEARRAYBOUND sab[2]; // 必须为维
- sab[0].lLbound = 1;
- sab[0].cElements = iElementCount;
- sab[1].lLbound = 1;
- sab[1].cElements = iElementCount;
- varReturn.parray = SafeArrayCreate(VT_VARIANT, 2, sab);
- Range range;
- range.AttachDispatch(m_Range.GetRange(start,stop));
- if(range.m_lpDispatch == NULL)
- return FALSE;
- varReturn = range.GetValue2();
- range.ReleaseDispatch();
- strarray.RemoveAll();
- // 从安全数组中读取数据
- CString str;
- if(iElementCount == 1)
- {
- CVariantCast(varReturn).GetValue(str);
- strarray.Add(str);
- }
- else
- {
- _variant_t tmp;
- for(int i=1;i<=iElementCount;++i)
- {
- long indices[] = {1,i};
- SafeArrayGetElement(varReturn.parray, indices, (void *)&tmp);
- CVariantCast(tmp).GetValue(str);
- strarray.Add(str);
- }
- }
- return TRUE;
- }
其中CVariantCast为一个自己实现的转换类,使用的代码如下:
- inline void CVariantCast::GetValue(CString& strValue)
- {
- strValue.Empty();
- if(m_variant.vt == VT_EMPTY || m_variant.vt == VT_NULL)
- return;
- if(m_variant.vt == VT_BOOL)
- {
- if(m_variant.boolVal)
- strValue = _T("TRUE");
- else
- strValue = _T("FALSE");
- return;
- }
- m_variant.ChangeType(VT_BSTR);
- strValue = m_variant.bstrVal;
- }