如何為 Excel 建立 RealTimeData 伺服器

文章翻譯 文章翻譯
文章編號: 285339 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

結論

Microsoft Excel 提供新的工作表函數 RTD,可讓您呼叫「元件物件模型」(Component Object Model,COM) 自動化伺服器,以便即時擷取資料。本文將告訴您,如何使用 Visual Basic 建立可與 Excel 的 RTD 函數搭配使用的 RealTimeData 伺服器。

其他相關資訊

RTD 工作表函數具有下列語法:
=RTD(ProgID,Server,String1,[String2],...)
第一個引數 ProgID,表示 RealTimeData 伺服器的「程式設計識別碼」(Programmatic Identifier,ProgID)。Server 引數表示 RealTimeData 伺服器執行所在的電腦名稱;如果 RealTimeData 伺服器會在本機執行,那麼這個引數可以是 Null 字串或省略。其餘的引數僅表示要傳送至 RealTimeData 伺服器的參數;這些參數的每個唯一組合都代表一個「主題」,而該主題具有關聯的「主題編號」。參數必須區分大小寫。例如,下列說明對 RTD 伺服器的呼叫,這些呼叫可能產生三個不同的主題編號:
=RTD("ExcelRTD.RTDFunctions",,"AAA", "10")

=RTD("ExcelRTD.RTDFunctions",,"AAA", "5")

=RTD("ExcelRTD.RTDFunctions",,"aaa", "5")
為了讓 COM Automation 伺服器成為 RealTimeData 伺服器以搭配使用 Excel 的 RTD 函數,必須實作 IRTDServer 介面。伺服器必須實作 IRTDServer 的所有方法:

ServerStart
當 Excel 要求伺服器的第一個 RTD 主題時呼叫。ServerStart 應該會傳回 1 表示成功,並傳回負值或 0 表示失敗。ServerStart 方法的第一個參數是回呼物件,RealTimeData 伺服器會使用此回呼物件通知 Excel 何時應該從 RealTimeData 伺服器收集更新。
ServerTerminate
當 Excel 不再需要來自 RealTimeDatao 伺服器的 RTD 主題時呼叫。
ConnectData
每當 Excel 要求來自 RealTimeDatao 伺服器的新 RTD 主題時呼叫。
DisconnectData
每當 Excel 不再需要特定主題時呼叫。
HeartBeat
自上次通知 Excel 從 RealTimeData 伺服器取得更新以來,如果超過指定的間隔時間,就會由 Excel 呼叫。
RefreshData
當 Excel 在主題上要求重新整理時呼叫。RefreshData 是在伺服器通知 Excel 有更新之後呼叫的,並且它會傳回主題的計數,以更新每個主題的主題編號和值。

建立範例 RealTimeData 伺服器

下列範例將告訴您,如何利用 Microsoft Excel 2002 建立和使用 RealTimeData 伺服器。此伺服器只會在工作表上提供每 10 秒更新一次的計數器。伺服器最多可接受兩個主題字串。第一個主題字串可以是 AAA、BBB 和 CCC,而任何其他主題字串會被視為無效,並且伺服器會傳回 #VALUE! 至 RTD 函數。第二個字串是數值,表示傳回值該如何遞增。如果省略第二個字串,遞增值會預設為 1;如果第二個字串不是數值,則伺服器會傳回 #NUM! 至 RTD 函數。
  1. 在 Visual Basic 中開啟新的 ActiveX DLL 專案。
  2. [專案] 功能表上,按一下 [參考],選取 Excel 的物件程式庫,然後按一下 [確定]
    在 Microsoft Excel 2002 中:[Microsoft Excel 10.0 物件程式庫]
  3. 在 Microsoft Office Excel 2003 中:[Microsoft Excel 11.0 物件程式庫]
  4. [專案] 功能表上,按一下 [Project1 屬性]。將 [專案名稱] 變更為 ExcelRTD,然後按一下 [確定]
  5. Class1 類別模組的 Name 屬性變更為 RTDFunctions。將下列程式碼加入至 RTDFunctions
    Option Explicit
    
    Implements IRtdServer  'Interface allows Excel to contact this RealTimeData server
    
    Private m_colTopics As Collection
        
    Private Function IRtdServer_ConnectData(ByVal TopicID As Long, Strings() As Variant, GetNewValues As Boolean) As Variant
        '** ConnectData is called whenever a new RTD topic is requested
        
        'Create a new topic class with the given TopicId and string and add it to the
        'm_colTopics collection
        Dim oTopic As New Topic
        m_colTopics.Add oTopic, CStr(TopicID)
        oTopic.TopicID = TopicID
        oTopic.TopicString = Strings(0)
        If UBound(Strings) >= 1 Then oTopic.SetIncrement Strings(1)
        
        'For this example, the initial value for a new topic is always 0
        IRtdServer_ConnectData = oTopic.TopicValue
        
        Debug.Print "ConnectData", TopicID
    End Function
    
    Private Sub IRtdServer_DisconnectData(ByVal TopicID As Long)
       '** DisconnectData is called whenever a specific topic is not longer needed
       
       'Remove the topic from the collection
       m_colTopics.Remove CStr(TopicID)
       
       Debug.Print "DisconnectData", TopicID
    End Sub
    
    Private Function IRtdServer_Heartbeat() As Long
        '** Called by Excel if the heartbeat interval has elapsed since the last time
        '   Excel was called with UpdateNotify.
        Debug.Print "HeartBeat"
    End Function
    
    Private Function IRtdServer_RefreshData(TopicCount As Long) As Variant()
        '** Called when Excel is requesting a refresh on topics. RefreshData will be called
        '   after an UpdateNotify has been issued by the server. This event should:
        '   - supply a value for TopicCount (number of topics to update)
        '   - return a two dimensional variant array containing the topic ids and the
        '     new values of each.
       
        Dim oTopic As Topic, n As Integer
        ReDim aUpdates(0 To 1, 0 To m_colTopics.Count - 1) As Variant
        For Each oTopic In m_colTopics
            oTopic.Update
            aUpdates(0, n) = oTopic.TopicID
            aUpdates(1, n) = oTopic.TopicValue
            n = n + 1
        Next
        TopicCount = m_colTopics.Count
        IRtdServer_RefreshData = aUpdates
       
       Debug.Print "RefreshData", TopicCount & " topics updated"
    End Function
    
    Private Function IRtdServer_ServerStart(ByVal CallbackObject As Excel.IRTDUpdateEvent) As Long
        '** ServerStart is called when the first RTD topic is requested
        
        Set oCallBack = CallbackObject
        Set m_colTopics = New Collection
        g_TimerID = SetTimer(0, 0, TIMER_INTERVAL, AddressOf TimerCallback)
        If g_TimerID > 0 Then IRtdServer_ServerStart = 1       'Any value <1 indicates failure.
        
        Debug.Print "ServerStart"
    End Function
    
    Private Sub IRtdServer_ServerTerminate()
        '** ServerTerminate is called when no more topics are needed by Excel.
        
        KillTimer 0, g_TimerID
    
        '** Cleanup any remaining topics. This is done here since 
        '   IRtdServer_DisconnectData is only called if a topic is disconnected 
        '   while the book is open. Items left in the collection when we terminate
        '   are those topics left running when the workbook was closed.
    
        Dim oTopic As Topic
        For Each oTopic In m_colTopics
            m_colTopics.Remove CStr(oTopic.TopicID)
            Set oTopic = Nothing
        Next
    
        Debug.Print "ServerTerminate"
      
    End Sub
    
    					
  6. [專案] 功能表上,按一下 [加入類別模組]。將類別模組 Name 屬性變更為 Topic,並將 Instancing 屬性變更為 Private。將下列程式碼加入至 Topic 類別模組:
    Option Explicit
    
    Private m_TopicID As Long
    Private m_TopicString As String
    Private m_Value As Variant
    Private m_IncrementVal As Long
    
    Private Sub Class_Initialize()
        m_Value = 0
        m_IncrementVal = 1
    End Sub
    
    Friend Property Let TopicID(ID As Long)
        m_TopicID = ID
    End Property
    
    Friend Property Get TopicID() As Long
        TopicID = m_TopicID
    End Property
    
    Friend Property Let TopicString(s As String)
        s = UCase(s)
        If s = "AAA" Or s = "BBB" Or s = "CCC" Then
            m_TopicString = s
        Else
            m_Value = CVErr(xlErrValue) 'Return #VALUE if not one of the listed topics
        End If
    End Property
    
    Friend Sub Update()
        On Error Resume Next 'the next operation will fail if m_Value is an error (like #NUM or #VALUE)
        m_Value = m_Value + m_IncrementVal
    End Sub
    
    Friend Sub SetIncrement(v As Variant)
        On Error Resume Next
        m_IncrementVal = CLng(v)
        If Err <> 0 Then
            m_Value = CVErr(xlErrNum) 'Return #NUM if Increment value is not numeric
        End If
    End Sub
    
    Friend Property Get TopicValue() As Variant
        If Not (IsError(m_Value)) Then
            TopicValue = m_TopicString & ": " & m_Value
        Else
            TopicValue = m_Value
        End If
    End Property
    					
  7. [專案] 功能表上,選取 [加入模組]。將下列程式碼加入至新的模組:
    Public Declare Function SetTimer Lib "user32" (ByVal hWnd As Long, _
    ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    
    Public Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long
    
    Public Const TIMER_INTERVAL = 5000
    Public oCallBack As Excel.IRTDUpdateEvent
    Public g_TimerID As Long
    
    Public Sub TimerCallback(ByVal hWnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
        oCallBack.UpdateNotify
    End Sub
    					
  8. [檔案] 功能表上,按一下 [建立 ExcelRTD.dll] 以建置元件。

在 Excel 中使用 RTD 伺服器

  1. 在 Microsoft Excel 中開啟新的活頁簿。
  2. 在儲存格 A1 中,輸入下列公式,然後按下 ENTER 鍵:
    =RTD("ExcelRTD.RTDFunctions",,"AAA", 5)
    初始傳回值為 AAA:0". 經過五秒後,值會更新為 AAA:10,再過 10 秒後,值會更新為 AAA:15,以此類推。

  3. 在儲存格 A2 中,輸入下列公式並按下 ENTER:
    =RTD("ExcelRTD.RTDFunctions",,"BBB", 3)
    初始傳回值為 BBB:0". 每隔五秒儲存格值會增加 3。

  4. 在儲存格 A3 中,輸入下列公式並按下 ENTER:
    =RTD("ExcelRTD.RTDFunctions",,"AAA", 5)
    初始傳回值會符合儲存格 A1 的內容,因為這是在 A1 中使用的相同主題。

  5. 在儲存格 A4 中,輸入下列公式並按下 ENTER:
    =RTD("ExcelRTD.RTDFunctions",,"AAA", 10)
    初始傳回值為 AAA:0." 每隔五秒儲存格值會隨著其他儲存格一起增加。請注意,由於傳遞至伺服器的參數組合不相同,所以傳回值不會符合儲存格 A1 或 A3 的內容。
在這個示範中,RTD 伺服器已編譯,並且 Excel 使用執行階段版本的元件。為了進行偵錯之用,您可以從 Visual Basic IDE 執行 RTD 伺服器。

如果要以偵錯模式執行:
  1. 結束 Microsoft Excel 並切換至 Visual Basic 中的專案。
  2. 按下 F5 以啟動元件。如果出現 [專案屬性] 對話方塊,請按一下 [確定] 以選取 [等待元件建立完成] 預設選項。
  3. 請確認 Visual Basic 中的 [即時運算] 視窗已出現。當您在儲存格輸入公式,並且儲存格已更新時,請檢視 Visual Basic [即時運算] 視窗的內容,以查看哪些動作觸發不同事件。
關於 DisconnectData 事件的注意事項

雖然 Excel 是您的 RTD 伺服器的訂閱者,但是當 Excel 不再需要主題時,仍會觸發 DisconnectData 事件 (例如,當您刪除或清除儲存格中的 RTD 公式時)。然而,當活頁簿關閉或 Excel 結束時,Excel 不會針對 RTD 伺服器的每個主題呼叫 DisconnectData,而是只會呼叫 ServerTerminate。當您建立 RTD 伺服器時,您應該在 ServerTerminate 事件觸發時,針對任何必要清除的主題或其他物件編碼。

(c) Microsoft Corporation 2001, All Rights Reserved.本文內容由 Lori B. Turner, Microsoft Corporation 提供。

?考

如需詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:
284883 RTD Server does not send update notifications to multiple Excel instances

屬性

文章編號: 285339 - 上次校閱: 2006年2月16日 - 版次: 4.1
這篇文章中的資訊適用於:
  • Microsoft Office Excel 2003
  • Microsoft Excel 2002 Standard Edition
  • Microsoft Visual Basic 6.0 Professional Edition
關鍵字:?
kbhowto kbautomation KB285339
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com