摘要
本文解答有關從 Visual C++自動化到 Microsoft Office 的常見問題。
其他相關資訊
目錄
-
什麼是自動化?
-
我是自動化的新進者,哪裡可以找到能深入瞭解的好資源?
-
我可以使用自動化的不同方式嗎?
-
什麼是 COM?
-
如何?附加到 Office 應用程式的執行實例嗎?
-
如何?通過選擇性參數?
-
如何?發現 Office 應用程式公開的事件?
-
我的自動化程式碼太慢。 如何加快工作速度?
-
這些像是 -2147352573 或 0x80030002 等大型錯誤值代表什麼意思?
-
什麼是型別程式庫?
-
我的自動化程式碼可搭配 Microsoft Excel 95 使用,但在 Microsoft Excel 97 中失敗。 為什麼?
-
為什麼我的程式完成之後,我自動化的應用程式會留在記憶體中?
-
我知道身為 Microsoft Office 應用程式使用者我該怎麼做,但該如何使用自動化以程式設計方式執行這項作業?
-
我可以將內嵌的 Microsoft Office 應用程式自動化嗎?
-
如何?存取 Microsoft Office 檔中的檔摘要資訊嗎?
問題與解答
-
什麼是自動化?
自動化 (舊稱 OLE Automation) 是一種技術,可讓您善用現有程式的功能,並將其整合到您自己的應用程式中。 例如,您可以在應用程式中使用 Microsoft Word 拼字及文法檢查功能,而您的使用者無法看到 Microsoft Word。 您甚至可以使用所有 Microsoft Excel 圖表、列印和資料分析工具。 這項技術可以大幅簡化並加快您的開發。
-
我是自動化的新進者,哪裡可以找到能深入瞭解的好資源? 第 24 章:David Porglinski 的「內部 Visual C++」 (ISBN:1-57231-565-2) 提供一般概觀以及一些絕佳的範例。 此外,Microsoft 知識庫是很好的資訊來源。
如果您偏好以範例學習,請參閱 Microsoft 知識庫中的下列文章:
179706 如何使用 MFC 自動化 Excel &建立/格式化新活頁簿
-
我可以使用自動化的不同方式嗎?
您可以使用三種基本方式:MFC、#import 和 C/C++:
-
使用 MFC,使用 Visual C++ ClassWizard 從 Microsoft Office 類型文件庫產生「包裝類別」。 這些課程以及其他 MFC 課程,例如 COleViont、COleSafeArray、COleException,可簡化自動化的工作。 通常建議您採用此方法,而大部分的 Microsoft 知識庫範例都是使用 MFC。
-
#import,一項隨 Visual C++ 5.0 一起提供的新指令,會從指定的類型文件庫建立 VC++ 「智慧指標」。 它非常強大,但通常不建議使用,因為使用 Microsoft Office 應用程式時通常會發生參照計數問題。
-
C/C++ 自動化變得更加困難,但有時需要避免 MFC 的負荷過重或#import的問題。 基本上,您使用的是 CoCreateInstance () 等 API,以及 IDispatch 和 IUnknown 等 COM 介面。
請務必注意,與純 C 比較,來自 C++ 的 Automation 之間有一些微差異,因為 COM 是以 C++ 類別為設計。
-
-
什麼是 COM?
Automation 是以元件物件模型 (COM) 為基礎。 COM 是以介面為基礎的標準軟體架構,設計來將程式碼分成獨立的物件。 將它視為物件導向設計 (OOP) 範例的擴充功能,但適用于個別的應用程式。 每個物件都會公開一組介面,而所有對物件的通訊,例如初始化、通知和資料傳輸,都會透過這些介面進行。
COM 也是由) 作業系統一起安裝的動態連結文件庫 (DLL 所提供的一組服務。 自動化使用其中許多服務。 其中一個範例是「增益集」服務,此服務會將用戶端應用程式的呼叫封裝到伺服器應用程式介面的成員函數,並透過引數將這些呼叫傳遞至伺服器應用程式。 這會讓伺服器介面顯示在用戶端的記憶體空間中,而當用戶端是在其本身的處理空間中執行的.exe時,就不是這種情況。 「傳送」也可讓伺服器的方法傳回跨程式範圍的傳回值,並安全地交到用戶端通話的手中。 還有其他許多自動化不可或缺的服務是由各種 COM 文件庫所提供。 相關資訊的來源包括:「Inside Ole - Second Edition」 by Kraig Brockschmidt, ISBN 1-55615-843-2, 「Inside COM」 by DaleDaleDaleon - ISBN 1-57231-349-8, and 「Automation Programr's Reference,」 ISBN 1-57231-584-9. -
如何?附加到 Office 應用程式的執行實例嗎?
使用 GetActiveObject () API。 自動化伺服器會透過 RegisterActiveObject () API 在 [執行物件資料表]) 的 ROT (中自行註冊。 自動化用戶端可以在執行中的實例中取得程式碼,例如:
// Translate server ProgID into a CLSID. ClsidFromProgID // gets this information from the registry. CLSID clsid; CLSIDFromProgID(L"Excel.Application", &clsid); // Get an interface to the running instance, if any.. IUnknown *pUnk; HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk); ASSERT(!FAILED(hr)); // Get IDispatch interface for Automation... IDispatch *pDisp; hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp); ASSERT(!FAILED(hr)); // Release the no-longer-needed IUnknown... pUnk->Release();
注意:如果您想要附加的 Office 應用程式有多個實例,您只能附加到使用 GetActiveObject () API 啟動的第一個實例。
事實上,您可以為每個個別實例反覆運算 ROT,但如果有另一個實例已經在 ROT 中,Office 應用程式就不會自行註冊,因為本身的名稱永遠都是相同的 () 無法辨別。 這表示除了第一個實例以外,您無法附加至任何實例。 不過,由於 Office App 也會在 ROT 中註冊檔,因此您可以透過反覆運算 ROT 尋找特定檔、附加至特定檔,然後從中取得應用程式物件,成功附加至其他實例。
您不需要針對 PowerPoint 執行此動作,因為它是單一實例應用程式;您只能執行其中一個實例。 -
如何?通過選擇性參數?
有些方法有「選擇性」參數。 在 Visual Basic 中,撥打方法時,您可以隨意省略。 不過,當您使用 Visual C++ 撥號時,必須通過一個特殊的 VARIANT,其 .vt 功能變數會VT_ERROR,而 .scode 功能變數會DISP_E_PARAMNOTFOUND。 那是:
// VARIANT used in place of optional-parameters. VARIANT varOpt; varOpt.vt = VT_ERROR; varOpt.scode = DISP_E_PARAMNOTFOUND;
這正是 Visual Basic 在幕後執行的動作。
-
如何?發現 Office 應用程式公開的事件嗎?
基本上,您要實作事件介面來 (「接收器」) ,並設定與應用程式 (「來源」) 的諮詢連線。
一般說來,若要設定建議連線,您會取得伺服器的 IConnectionPointContainer,並使用事件介面的 IID 呼叫 FindConnectionPoint () 。 這可讓您使用 IConnectionPoint 介面,剩餘的就是使用事件介面實例呼叫 [建議] () 。 發生這些事件時,伺服器會透過這個介面回撥。 -
我的自動化程式碼太慢。 如何加快工作速度?
自動化速度問題的一個常見原因是重複讀取和撰寫資料。 這是 Excel 自動化用戶端的一般情況。 不過,大部分的人並不知道此資料通常可以使用 SAFEARRAY 一次撰寫或讀取所有資料。 如需詳細資訊和資訊範例,請參閱下列 Microsoft 知識庫文章:179706 HOWTO:使用 MFC 自動化 Excel 和建立/格式化新活頁簿
此外,請務必指出,使用剪貼簿有時可以改善效能。 例如,您可以將資料複製到剪貼簿,然後使用自動化來告知伺服器貼上。 反之亦然;請要求伺服器複製到剪貼簿,然後貼到應用程式中。 -
這些大型錯誤值,例如 -2147352573 或0x80030002代表什麼?
這些值稱為 HRESULTs,定義于值。 數位太大,因為第一個位代表是否為錯誤結果。 您可以使用 Visual C++ 隨附的ErrLook.Exe公用程式,將這些數位轉換成有意義的描述。
如果您想要以程式設計方式取得錯誤的描述,您可以使用 FormatMessage () API。注意:如果您使用的是 Visual C++ 6.0,且在偵錯監看視窗中有包含此值的變數,請在不使用引號) 的情況下附加 「,hr」 (,讓 Visual C++ 為您翻譯!
-
什麼是型別程式庫?
類型文件庫類似于 C/C++ 頁首檔案。 它包含伺服器正在發佈的介面、方法和屬性。 您可以使用 Visual C++隨附的 OLE/COM 物件檢視器 (Oleview.exe) 來檢視類型文件庫。 以下是 Microsoft Office 95、97 和 2000 的類型文件庫檔案名清單:
Office 應用程式|輸入文件庫
------------------------+----------------
Word 95 及之前的|wb70en32.tlb
Excel 95 及之前的 |xl5en32.olb
Powerpoint 95 及之前的 |Powerpoint.tlb
Access 95 及之前的|msaccess.tlb
文件夾 95 |binder.tlb
Schedule+ |sp7en32.olb
Project |pj4en32.olb
團隊管理員|mstmgr1.olb
Word 97 |msword8.olb
Excel 97 |excel8.olb
Powerpoint 97 |msppt8.olb
Access 97 |msacc8.olb
文件夾 97 |msbdr8.olb
Graph 97 |graph8.olb
Outlook 97 |msoutl8.olb
Outlook 98 |msoutl85.olb
Word 2000 |msword9.olb
Excel 2000 |excel9.olb
Powerpoint 2000 |msppt9.olb
Access 2000 |msacc9.olb
Outlook 2000 |msoutl9.olb
Word 2002 |msword.olb
Excel 2002 |
excel.exe PowerPoint 2002 |msppt.olb
Access 2002 |msacc.olb
Outlook 2002 |msoutl.olb
-
我的自動化程式碼可搭配 Excel 95 使用,但在 Excel 97 中失敗。 發生了什麼事情?
Excel 的物件模型在版本 95 到 97 之間做了重大變更。 Excel 95 會在單一 IDispatch 實作中實作其所有方法和屬性。 這表示您通常可以從物件 Y 呼叫物件 X 所用的方法。這不是很好的設計,因此在 Office 97 中,每個物件都有各自的 Idispatch 實作。 這表示,如果您從個別的物件 Y 要求物件 X 提供方法或屬性,您會收到錯誤0x80020003-2147352573「找不到成員」。 若要避免此錯誤,您必須確認您撥打電話的基礎 IDispatch 介面是語義上正確的介面。
-
程式完成後,我自動化的應用程式會留在記憶體中。 發生了什麼事情?
這很可能是因為您忘記釋出取得的介面,而需要追蹤。 以下是一些一般建議,以及要尋找的專案:
-
如果您使用的是 #import,很可能是您遇到其中一個與它關聯的參照計數錯誤。 錯誤通常可以解決,但通常建議您使用其他自動化方法之一。 #import不適用於 Office 應用程式,因為其類型文件庫和使用方式相當複雜。 此外,這類參照計數問題也難以追蹤,因為許多介面層級 COM 呼叫都是使用#import時的幕後運作。
-
檢查您是否撥打任何方法,例如 Open 或 New,傳回 IDispatch * (LPDISPATCH) ,並忽略傳回值。 如果您是,則表示您正在將此傳回的介面送出,並且需要變更程式碼,以便在不再需要時放開。
-
逐漸批註程式碼的區段,直到問題消失為止,然後謹慎地再次新增,以追蹤問題的起始位置。
-
請注意,如果使用者「觸碰」應用程式,某些應用程式將會維持在執行狀態。 如果在您自動化時發生此情況,則應用程式之後可能會繼續執行。 Office 應用程式的 Application 物件上有一個「UserControl」屬性,您可以讀取/寫入以變更此行為。
-
此外,如果使用者介面發生足夠的「動作」,部分應用程式會決定繼續執行。 如果您打算讓應用程式結束,請在 Application 物件上呼叫其 Quit () 方法。 當 「結束」被叫用時,無論其參照計數為何,Word 都會關機。 這是未預期的 COM 行為。 不過,Excel 會正確隱藏本身,但會持續執行,直到所有未完成的介面都發佈為止。 一般說來,您應該釋出所有未完成的參照,如果您打算結束應用程式,請只撥打 Quit () 。
-
-
我知道身為 Office 應用程式使用者我該怎麼做,但該如何透過自動化以程式設計方式執行這項作業?
您感興趣的是您需要使用的物件、方法和屬性。 瞭解如何根據您想要做為使用者的方式流覽 Word、Excel 和 Powerpoint 物件模型的最佳方式,就是使用宏錄製器。 只要從 [工具] 功能表中選擇 [宏]\[錄製新宏],執行您感興趣的工作,然後選擇 [宏\'停止錄製]。 錄製完成後,從 [工具] 功能表中選擇 [Macro\Macros],選取您錄製的宏,然後按一下 [編輯]。 這會帶您前往產生的 VBA 程式碼,以完成您錄製的工作。 請記住,在大多數情況下,記錄的宏並不是最佳的程式碼,但對於快速範例來說,這個方法非常實用。 -
我可以將內嵌的 Office 應用程式自動化嗎?
絕對。 訣竅在於取得 IDispatch 指標:這是在 Visual C++ Technical Note 39 (TN039) 中提供。
-
如何?存取 Office 檔中的檔摘要資訊嗎?
檔摘要資訊可透過自動化存取,或直接透過 IPropertyStorage 存取。