Så här skapar du en RealTimeData-server för Excel

Sammanfattning

Microsoft Excel tillhandahåller en ny kalkylbladsfunktion, RTD, som gör att du kan anropa en COM-automationsserver (Component Object Model) i syfte att hämta data i realtid. Den här artikeln beskriver hur du använder Visual Basic för att skapa en RealTimeData-server för användning med Excels RTD-funktion.

Mer information

Funktionen RTD-kalkylblad har följande syntax:

=RTD(ProgID,Server,String1,[String2],...)

Det första argumentet, ProgID, representerar ProgID (Programmatic Identifier) för RealTimeData-servern. Argumentet Server anger namnet på den dator där RealTimeData-servern körs. det här argumentet kan vara en null-sträng eller utelämnas om RealTimeData-servern ska köras lokalt. De återstående argumenten representerar helt enkelt parametrar som ska skickas till RealTimeData-servern. varje unik kombination av dessa parametrar representerar ett "ämne" som har ett associerat "ämnes-ID". Parametrar är skiftlägeskänsliga. Följande illustrerar till exempel anrop till RTD-servern som skulle resultera i tre separata ämnes-ID:

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

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

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

För att en COM Automation-server ska vara en RealTimeData-server för användning med Excels RTD-funktion måste den implementera IRTDServer-gränssnittet. Servern måste implementera alla metoder för IRTDServer:

  • ServerStart: Anropas när Excel begär det första RTD-ämnet för servern. ServerStart bör returnera en 1 vid lyckat resultat och ett negativt värde eller 0 vid fel. Den första parametern för metoden ServerStart är ett motringningsobjekt som RealTimeData-servern använder för att meddela Excel när den ska samla in uppdateringar från RealTimeData-servern.

  • ServerTerminate: Anropas när Excel inte längre kräver RTD-ämnen från RealTimeData-servern.

  • ConnectData: Anropas när Excel begär ett nytt RTD-ämne från RealTimeData-servern.

  • DisconnectData: Anropas när Excel inte längre kräver ett specifikt ämne.

  • HeartBeat: Anropas av Excel om ett visst intervall har förflutit sedan den senaste gången Excel informerades om uppdateringar från RealTimeData-servern.

  • RefreshData: Anropas när Excel begär en uppdatering av ämnen. RefreshData anropas när servern meddelar Excel att uppdateringar finns och returnerar ett antal ämnen som ska uppdateras tillsammans med ämnes-ID och värde för varje ämne.

Skapa en RealTimeData-exempelserver

Följande exempel visar hur du skapar och använder en RealTimeData-server med Microsoft Excel 2002. Den här servern tillhandahåller helt enkelt en räknare som uppdateras var tionde sekund i ett kalkylblad. Servern accepterar upp till två ämnessträngar. Den första ämnessträngen kan vara AAA, BBB och CCC. andra ämnessträngar anses vara ogiltiga och servern returnerar #VALUE! till RTD-funktionen. Den andra strängen är ett numeriskt värde som representerar hur returvärdet ska ökas. Om den andra strängen utelämnas är inkrementsvärdet standardvärdet 1. Om den andra strängen inte är numerisk returnerar servern #NUM! till RTD-funktionen.

  1. Starta ett nytt ActiveX DLL-projekt i Visual Basic.

  2. projektmenyn klickar du på Referenser, väljer objektbiblioteket för din version av Excel och klickar sedan på OK. Välj till exempel något av följande:

    • För Microsoft Office Excel 2007 väljer du Microsoft Excel 12.0-objektbibliotek.
    • För Microsoft Office Excel 2003 väljer du Microsoft Excel 11.0-objektbibliotek.
    • För Microsoft Excel 2002 väljer du Microsoft Excel 10.0-objektbibliotek.
  3. På projektmenyn klickar du på Project1-egenskaper. Ändra projektnamnet till ExcelRTD och klicka sedan på OK.

  4. Ändra egenskapen Namn för klassmodulen Class1 till RTDFunctions. Lägg till följande kod i 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
    
    
  5. Klicka på Lägg till klassmodul på Projekt-menyn. Ändra klassmodulens namnegenskap till Ämne och ändra egenskapen Instancing till Privat. Lägg till följande kod i klassmodulen Ämne:

    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
    
  6. På projektmenyn väljer du Lägg till modul. Lägg till följande kod i den nya modulen:

    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
    
  7. På Arkiv-menyn klickar du på Skapa ExcelRTD.dll för att skapa komponenten.

Använda RTD-servern i Excel

  1. Starta en ny arbetsbok i Microsoft Excel.

  2. I cell A1 anger du följande formel och trycker sedan på RETUR:

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

    Det första returvärdet är "AAA: 0". Efter fem sekunder uppdateras värdet till "AAA: 10" och efter 10 sekunder uppdateras värdet till "AAA:15" och så vidare.

  3. I cell A2 anger du följande formel och trycker på RETUR:

    =RTD("ExcelRTD.RTDFunctions",,"BBB", 3)

    Det första returvärdet är "BBB: 0". Var femte sekund ökar cellvärdet med 3.

  4. I cell A3 anger du följande formel och trycker på RETUR:

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

    Det första returvärdet matchar innehållet i cell A1 eftersom det är samma "ämne" som används i A1.

  5. I cell A4 anger du följande formel och trycker på Retur: =RTD("ExcelRTD.RTDFunctions",,"AAA", 10)

    Det första returvärdet är "AAA: 0." Var femte sekund ökar cellvärdet på samma sätt som de andra cellerna. Observera att returvärdet inte matchar innehållet i cell A1 eller A3 eftersom kombinationen av parametrar som skickas till servern är annorlunda.

För den här bilden kompilerades RTD-servern och Excel använde körningsversionen av komponenten. I felsökningssyfte kan RTD-servrar köras från Visual Basic IDE.

Så här kör du i felsökningsläge:

  1. Avsluta Microsoft Excel och växla till projektet i Visual Basic.
  2. Tryck på F5 för att starta komponenten. Om dialogrutan Projektegenskaper visas klickar du på OK för att välja standardalternativet Vänta tills komponenter har skapats.
  3. Kontrollera att fönstret Omedelbart i Visual Basic visas. När du anger formler i cellerna och när cellerna uppdateras undersöker du innehållet i fönstret Omedelbart i Visual Basic för att se vilka åtgärder som utlöser de olika händelserna.

Obs!

Angående händelsen DisconnectData

Excel är prenumerant på rtd-servern, men utlöser händelsen DisconnectData när den inte längre behöver ett ämne (till exempel när du tar bort eller tar bort en RTD-formel i en cell). Excel anropar dock inte DisconnectData för varje ämne för RTD-servern när arbetsboken stängs eller Excel avslutas. I stället anropar Excel endast ServerTerminate. När du skapar en RTD-server bör du koda för all nödvändig rensning av ämnen eller andra objekt när händelsen ServerTerminate utlöses.

(c) Microsoft Corporation 2001, Med ensamrätt. Bidrag från Lori B. Turner, Microsoft Corporation.