最近的項目中需要利用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)<br />{<br />int iElementCount = iColumnStop - iColumnStart + 1;<br />if(iElementCount <= 0)<br />return FALSE;</p><p>CString strStart,strEnd;<br />_variant_t start,stop;</p><p>strStart = GetItemName(iRow,iColumnStart);<br />start.vt = VT_BSTR;<br />start.bstrVal = strStart.AllocSysString();// 不需要進行_bstr_t轉換</p><p>strEnd = GetItemName(iRow,iColumnStop);<br />stop.vt = VT_BSTR;<br />stop.bstrVal = strEnd.AllocSysString();</p><p>// 建立安全陣列,從Excel中讀取內容<br />_variant_t varReturn;<br />varReturn.vt = VT_ARRAY | VT_VARIANT;</p><p>SAFEARRAYBOUND sab[2];// 必須為維<br />sab[0].lLbound = 1;<br />sab[0].cElements = iElementCount;<br />sab[1].lLbound = 1;<br />sab[1].cElements = iElementCount;<br />varReturn.parray = SafeArrayCreate(VT_VARIANT, 2, sab);</p><p>Range range;<br />range.AttachDispatch(m_Range.GetRange(start,stop));<br />if(range.m_lpDispatch == NULL)<br />return FALSE;</p><p>varReturn = range.GetValue2();<br />range.ReleaseDispatch();</p><p>strarray.RemoveAll();<br />// 從安全陣列中讀取資料<br />CString str;<br />if(iElementCount == 1)<br />{<br />CVariantCast(varReturn).GetValue(str);<br />strarray.Add(str);<br />}<br />else<br />{<br />_variant_t tmp;<br />for(int i=1;i<=iElementCount;++i)<br />{<br />long indices[] = {1,i};<br />SafeArrayGetElement(varReturn.parray, indices, (void *)&tmp);</p><p>CVariantCast(tmp).GetValue(str);<br />strarray.Add(str);<br />}<br />}</p><p>return TRUE;<br />}<br />
其中CVariantCast為一個自己實現的轉換類,使用的代碼如下:
inline void CVariantCast::GetValue(CString& strValue)<br />{<br />strValue.Empty();</p><p>if(m_variant.vt == VT_EMPTY || m_variant.vt == VT_NULL)<br />return;</p><p>if(m_variant.vt == VT_BOOL)<br />{<br />if(m_variant.boolVal)<br />strValue = _T("TRUE");<br />else<br />strValue = _T("FALSE");</p><p>return;<br />}</p><p>m_variant.ChangeType(VT_BSTR);<br />strValue = m_variant.bstrVal;<br />}