24. 在其他應用程式中執行的ActiveX物件

在Microsoft對Microsoft Windows和Internet未來的規劃中,ActiveX佔了一個極重要的部分,整個ActiveX技術藍圖的核心部分就是Automation,Automation技術使得不同的應用程式可以共享物件。愈來愈多的應用程式將會開始提供Automation物件給外界使用,因此我們可以預見Visual Basic會因Automation物件的普及而更受歡迎。我們在 第五章"物件導向程式設計" 中介紹過,Visual Basic本身讓你能建立用來定義ActiveX物件的物件類別模組,產生能與其他應用程式共享的ActiveX物件。因為Visual Basic具備了這種Automation的能力,使得它成了Windows環境下發展軟體的最佳工具選擇。

本章要介紹一些Windows環境中常用的功能,這些功能由Microsoft Word和Microsoft Excel的Automation技術所提供,我們把這些功能整合到Visual Basic的應用程式中。

如何運用ActiveX執行拼字檢查?
 

所有Microsoft Office 97中的應用程式都提供ActiveX物件,你可以在Visual Basic應用程式中使用這些物件。現在讓我們來看看如何利用Automation技術從Visual Basic中使用Word與Excel的拼字檢查功能。

Microsoft Word的拼字檢查功能
 

以下這段程式將產生一個Word文件物件(Document Object),透過操縱這個物件的屬性及方法,Word將會對由Visual Basic應用程式傳來的字串進行拼字檢查,再送還給Visual Basic應用程式。我們在程式中加了許多註解,但其處理流程大致如下:產生一個Document物件,把Visual Basic應用程式中的文字放進Document物件中,然後啟動拼字檢查功能;經過拼字檢查後的文字再複製回Visual Basic應用程式中的文字方塊控制項,取代原來的文字。(本程式應配合Microsoft Word 97執行)。

Option Explicit

Dim mdocSpell As New Document
Dim mblnVisible As Boolean

Private Sub Form_Load()
    `Check whether application is visible;
    `used in Unload to determine whether this 
    `application started Word 
    mblnVisible = mdocSpell.Application.Visible
End Sub

`Check spelling of text box contents
Private Sub cmdSpell_Click()
    `Add text to a Word Range object
    mdocSpell.Range.Text = txtSpell
    `IMPORTANT: You must perform the following two steps
    `before using the CheckSpelling method!!
    `Be sure that Word is visible
    mdocSpell.Application.Visible = True
    `Activate Word
    AppActivate mdocSpell.Application.Caption
    `Check spelling
    mdocSpell.Range.CheckSpelling
    `Update text box with changes from Word
    txtSpell = mdocSpell.Range.Text
    `Trim off null character that Word adds
    txtSpell = Left(txtSpell, Len(txtSpell) - 1)
    `Activate this application
    AppActivate Caption
End Sub

`Clean up
Private Sub Form_Unload(Cancel As Integer)
    `Check whether this application started Word
    If mblnVisible Then
        `Close document
        mdocSpell.Close savechanges:=False
    Else
        `Shut down Word
        mdocSpell.Application.Quit savechanges:=False
    End If
End Sub

在這段程式中,有幾點值得提出來討論:第一,我們用程式碼使作用中的應用程式由Visual Basic轉為Word,再由Word轉為Visual Basic;第二,CheckSpelling方法會呼叫一個強制回應對話方塊──「拼字檢查」對話方塊,對話方塊完成工作後,使用者必須關掉這個對話方塊,Visual Basic應用程式才會繼續執行。在呼叫任何一個會叫用強制回應對話方塊的方法之前,請務必使Word顯示出來,否則使用者將不能轉換到Word環境中,應用程式也會毫無反應。

如果想測試這個範例,請建立一個標準執行檔專案,把表單取名為frmSpell,然後在表單中加入一個指令按鈕cmdSpell和一個文字方塊txtSpell。另外,很重要的一點,請務必把Microsoft Word 8.0 Object Library設定為引用項目。最後,加入前面的程式,程式就可以執行了。

圖24-1所顯示的是拼字檢查前帶有錯字的字串,圖24-2顯示的是正在進行拼字檢查的對話方塊,圖24-3則是拼字檢查完畢後正確的本文。


 

 圖24-1 拼字檢查前帶有錯字的本文


 

 圖24-2 「拼字檢查」對話方塊


 

 圖24-3 拼字檢查後正確的本文

Word的拼字檢查功能亦可由全域的GetSpellingSuggestions方法呼叫,我們可以用這個方法單獨檢查一個字。當使用者選了某個字並按下F7鍵之後,以下這段程式會列出建議的字。

Const KEY_F7 = 118 

`Check spelling of a single word
Private Sub txtSpell_KeyDown(KeyCode As Integer, Shift As Integer)
    Dim Corrections
    If KeyCode = KEY_F7 Then
        If txtSpell.SelLength = 0 Then
            `Select the word
            SendKeys "+^{Right}"
        End If
        `Check spelling of selection
        Set Corrections = GetSpellingSuggestions(txtSpell.SelText)
        `If misspelled, display suggestions
        If Corrections.Count Then
            frmCorrections.Display Corrections
        End If
    End If
End Sub

`Called by frmCorrections to replace text
Friend Sub Replace(Word As String)
    txtSpell.SelText = Word
End Sub

上面這段程式在第二張表單frmCorrections中列出拼字建議,這張表單中包含了一個下拉式清單方塊lstCorrections和兩個指令按鈕,cmdReplace及cmdCancel,這兩個指令按鈕讓使用者決定是否要取代原來選定的字。以下是frmCorrections中的程式內容:

`Called by frmSpell to display suggestions from Word
Friend Sub Display(Corrections)
    Dim Word
    For Each Word In Corrections
        lstCorrections.AddItem Word
    Next Word
    `Select first suggestion
    lstCorrections.Selected(0) = True
    `Display the form
    Show vbModal
End Sub

`Replace word with selection
Private Sub cmdReplace_Click()
    frmSpell.Replace lstCorrections.List(lstCorrections.ListIndex)
    Unload Me
End Sub

`Cancel correction
Private Sub cmdCancel_Click()
    Unload Me
End Sub

圖24-4顯示在錯字vehement被選取而且鍵被按下之後,GetSpellingSuggestions方法執行的情形。

你也許注意到了GetSpellingSuggestions方法執行的速度比CheckSpelling方法的速度還快,而且如果Word正在執行狀態中,這兩個方法的速度會更快。當你在設計一個使用ActiveX物件的應用程式時,執行速度會是一個設計上重要的考量因素。大部分的物件需要整個相關的應用程式處於執行狀態,少部分的物件則能夠獨立執行,只需要載入原始應用程式的幾個模組而已。


 

 圖24-4 使用Microsoft Word的GetSpellingSuggestions方法

Microsoft Excel的拼字檢查功能
 

在程式中透過Automation使用Excel的拼字檢查功能十分類似使用Word的拼字檢查功能。本例中程式執行後的結果和前例的結果相同。圖24-5和圖24-6顯示應用程式執行的結果。(本程式應配合Microsoft Excel 97使用)。

在本範例中,程式碼產生了一個Excel的試算表(Sheet)物件,將Visual Basic應用程式中的文字載入到試算表物件的一個儲存格中,然後啟動Excel的拼字檢查功能。拼字檢查完成後,試算表儲存格中的文字會再被複製回Visual Basic應用程式的文字方塊裡。

Option Explicit

Dim objXL As Object

Private Sub cmdSpell_Click()
    `Use Automation to create an Excel object
    Set objXL = CreateObject("Excel.Sheet")
    `Get programmable reference (apparently a bug in Excel)
    Set objXL = objXL.Application.ActiveWorkbook.ActiveSheet
    `Copy from text box to sheet
    objXL.Range("A1").Value = txtSpell.Text
    `Check spelling
    objXL.CheckSpelling
    `Copy back to text box
    txtSpell.Text = objXL.Range("A1").Value
    `Remove object from memory
    Set objXL = Nothing
    `Be sure that this application is active
    AppActivate Caption
End Sub


 

 圖24-5 Excel拼字檢查功能執行前的文字


 

 圖24-6 執行中的Excel拼字檢查功能

若要執行本例,請建立一個標準執行檔專案,在表單中加入指令按鈕cmdSpell和文字方塊txtSpell,最後加上以上的程式。

我們在程式的最後一行使用了AppActivate函式,如果不使用這個函式而且Excel已經在執行狀態下,那麼當拼字檢查完成後,Excel仍然會在作用中,使用者將看不到你的應用程式。因此,為了防止這個問題,我們必須用Visual Basic的AppActivate函式使應用程式回復為作用中的程式。

另外也請注意這行程式碼:

Set objXL = objXL.Application.ActiveWorkbook.ActiveSheet

在正常情況下,我們可以不需要這行程式碼,但是因為Excel 97裡有一個很明顯的程式錯誤,所以我們必須使用這行程式碼。

早期連結與晚期連結
 

在使用ActiveX物件時,你可以選擇早期連結(Early Binding)或晚期連結(Late Binding)。早期連結讓你可以使用特定的物件資料型別作為ActiveX物件的型別,如Document;另外,早期連結也使得「瀏覽物件」能夠引用ActiveX物件程式庫,並且也使得Visual Basic的自動完成指令(command-completion)功能得以作用。早期連結會把ActiveX物件的物件類別識別代碼(Class ID)寫到應用程式的可執行檔中,這樣,應用程式在存取物件時會較為快速。我們在Word拼字檢查的範例中所用的連結方式即是採早期連結的方式,其連結的動作是透過Visual Basic的「設定引用項目」對話方塊,把Word物件程式庫連結到應用程式中。

晚期連結(Late Binding)必須使用通用的Object資料型別作為ActiveX物件變數的資料型別,然後在執行階段產生一個ActiveX物件,將此物件指定給物件變數。晚期連結不會把ActiveX物件類別識別代碼寫到應用程式的可執行檔中,因此應用程式在存取物件時要花稍長的時間。我們的Excel拼字檢查範例就是使用晚期連結,應用程式以CreateObject方法來建立與Excel物件程式庫的連結。

物件識別代碼是否被寫在可執行檔中是一個程式設計上很重要的考慮因素。因為每當新版本的應用程式(如Word和Excel)問世時,它們的物件識別代碼就會改變,因此,使用早期連結的應用程式就必須重新編譯,而使用晚期連結的應用程式則沒有這層顧慮。

如何運用ActiveX計算檔案的字數?
 

讓我們再看一個有關Word中Automation的範例。我們要用這個例子計算字串中的字數。在下面的程式中,我們透過Document物件來使用Word;另一個物件變數dlg用來存取Word中「文件屬性」對話方塊的設定值。

Private Sub cmdWords_Click()
    Dim dlg As Word.Dialog
    `Copy text into Word document
    mdocSpell.Range = txtSpell.Text
    `Create an object to hold dialog box settings
    Set dlg = mdocSpell.Application.Dialogs _
        (wdDialogDocumentStatistics)
    `Count words and characters
    dlg.Execute
    `Display results in a Label control
    Caption = Str(dlg.Words) & " words, " _
        & Str(dlg.Characters) & " characters"
End Sub

在本例中,我們將「文件屬性」對話方塊中的字數與字元數擷取出來,這個對話方塊還有其他的屬性可供讀取,請參閱線上手冊有關Dialogs物件集合的資訊。

圖24-7所顯示的是文字方塊中本文的字數與字元數。


 

 圖24-7 利用Word的計算字數功能來計算字數與字元數

本例中的程式必須併入前面介紹的Word拼字檢查功能專案中,並且在啟始表單中增加一個指令按鈕cmdWord。執行時打入一段文字,然後按下Count Words按鈕即可看見執行的結果。

如何在Visual Basic中運用Excel的進階數學函式?
 

Microsoft Excel中有許多數學函式是不提供給Visual Basic使用的。以下這個範例運用Automation技術產生一個Excel的物件,然後透過這個試算表物件執行Excel的數學函式,對一個由Visual Basic應用程式傳給試算表物件的值加以計算。

在本例中,我們用試算表中的兩個儲存格存放由Visual Basic應用程式傳來的值,用另外兩個儲存取格存放計算的結果。Excel的ATAN2函式在程式中被用來計算平面座標上正x軸與某線段的夾角(在第一和第二象限);這個線段的一端是原點,另一端則是由輸入的兩個值所定義。Visual Basic的Atn函式以三角形兩邊的比例來傳回一個在 - π /2與π /2之間的弧度值,而Excel的ATAN2函式則用點的座標值來計算傳回在π與 - π之間的弧度值,因此,ATAN2可以正確地計算我們所要的結果。

以下的程式碼會產生一個Excel的試算表物件,將線段端點的座標值存入試算表物件的儲存格,用ATAN2函式計算夾角弧度,然後將計算的結果傳回Visual Basic的應用程式:

Option Explicit

Private Sub cmdAngle_Click()
    Dim objXL As Object
    `Use Automation to create an Excel object
    Set objXL = CreateObject("Excel.Sheet")
    `This solves the Excel bug mentioned earlier
    Set objXL = objXL.Application.ActiveWorkbook.ActiveSheet
    `Set known values in cells
    objXL.Range("A1").Value = txtX.Text
    objXL.Range("A2").Value = txtY.Text
    `Calculate third cell
    objXL.Range("A3").Formula = "=ATAN2(A1,A2)"
    objXL.Range("A4").Formula = "=A3*180/PI()"
    `Display results in Label controls
    lblRadians.Caption = objXL.Range("A3").Value
    lblDegrees.Caption = objXL.Range("A4").Value
    `Remove object from memory
    Set objXL = Nothing
End Sub

請建立一個標準執行檔專案,在表單上加入兩個文字方塊txtX和txtY,兩個標籤lblRadians和lblDegrees,以及一個指令按鈕cmdAngle。圖24-8顯示的是程式讀入了xy座標值後計算的結果。程式計算的結果有兩個,一個是弧度,另一個是角度。


 

 圖24-8 從Visual Basic中呼叫的Excel數學函式

這種使用Excel試算表物件的技巧可以應用在不同的資料量、不同的計算類型、和不同複雜程度的各種專案。你會發現在某些情況下使用Excel物件會比完全用Visual Basic的程式還要方便而有效率。