Slik oppretter du en RealTimeData-server for Excel

Sammendrag

Microsoft Excel har en ny regnearkfunksjon, RTD, som lar deg kalle opp en automatiseringsserver for komponentobjektmodell (COM) med det formål å hente data i sanntid. Denne artikkelen beskriver hvordan du bruker Visual Basic til å opprette en RealTimeData-server for bruk med Excels RTD-funksjon.

Mer informasjon

Regnearkfunksjonen RTD har følgende syntaks:

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

Det første argumentet, ProgID, representerer Programmatisk identifikator (ProgID) for RealTimeData-serveren. Server-argumentet angir navnet på maskinen som RealTimeData-serveren kjøres på. dette argumentet kan være en nullstreng eller utelates hvis RealTimeData-serveren skal kjøre lokalt. De gjenværende argumentene representerer ganske enkelt parametere som skal sendes til RealTimeData-serveren. hver unike kombinasjon av disse parameterne representerer ett «emne», som har en tilknyttet emne-ID. Parametere skiller mellom store og små bokstaver. Følgende illustrerer for eksempel kall til RTD-serveren som resulterer i tre separate emne-ID-er:

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

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

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

For at en COM Automation Server skal være en RealTimeData Server for bruk med Excels RTD-funksjon, må den implementere IRTDServer-grensesnittet. Serveren må implementere alle metodene for IRTDServer:

  • ServerStart: Kalt når Excel ber om det første RTD-emnet for serveren. ServerStart skal returnere en 1 ved vellykket, og en negativ verdi eller 0 ved feil. Den første parameteren for ServerStart-metoden er et tilbakeringingsobjekt som RealTimeData-serveren bruker til å varsle Excel når den skal samle oppdateringer fra RealTimeData-serveren.

  • ServerTerminate: Kalt når Excel ikke lenger krever RTD-emner fra RealTimeData-serveren.

  • ConnectData: Kalles når Excel ber om et nytt RTD-emne fra RealTimeData-serveren.

  • DisconnectData: Kalles når Excel ikke lenger krever et bestemt emne.

  • HeartBeat: Kalt av Excel hvis et gitt intervall har gått siden forrige gang Excel ble varslet om oppdateringer fra RealTimeData-serveren.

  • RefreshData: Kalles når Excel ber om en oppdatering av emner. RefreshData kalles etter at serveren varsler Excel om at oppdateringer finnes, og det returnerer et antall emner som skal oppdateres sammen med emne-ID-en og verdien for hvert emne.

Opprette en Eksempelserver for RealTimeData

Følgende eksempel demonstrerer hvordan du oppretter og bruker en RealTimeData-server med Microsoft Excel 2002. Denne serveren gir ganske enkelt en teller som oppdateres hvert 10. sekund i et regneark. Serveren godtar opptil to emnestrenger. Den første emnestrengen kan være AAA, BBB og CCC. alle andre emnestrenger anses som ugyldige, og serveren returnerer #VALUE! til RTD-funksjonen. Den andre strengen er en numerisk verdi som representerer hvordan returverdien skal økes. Hvis den andre strengen utelates, settes intervallerverdien som standard til 1. Hvis den andre strengen ikke er numerisk, returnerer serveren #NUM! til RTD-funksjonen.

  1. Start et nytt ActiveX DLL-prosjekt i Visual Basic.

  2. Klikk ReferanserProsjekt-menyen, velg objektbiblioteket for din versjon av Excel, og klikk deretter OK. Velg for eksempel ett av følgende:

    • Velg Microsoft Excel 12.0-objektbibliotek for Microsoft Office Excel 2007.
    • Velg Microsoft Excel 11.0-objektbibliotek for Microsoft Office Excel 2003.
    • For Microsoft Excel 2002 velger du Microsoft Excel 10.0-objektbibliotek.
  3. Klikk Project1-egenskaper på Prosjekt-menyen. Endre prosjektnavnet til ExcelRTD, og klikk deretter OK.

  4. Endre Navn-egenskapen for klassemodulen Class1 til RTDFunctions. Legg til følgende kode 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. Klikk Legg til klassemodul på Prosjekt-menyen. Endre navneegenskapen for klassemodulen til Emne, og endre Instancing-egenskapen til Privat. Legg til følgende kode i emneklassemodulen:

    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. Velg Legg til modul på Prosjekt-menyen. Legg til følgende kode i den nye 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. Klikk Lag ExcelRTD.dll på Fil-menyen for å bygge komponenten.

Bruke RTD-serveren i Excel

  1. Start en ny arbeidsbok i Microsoft Excel.

  2. Skriv inn følgende formel i celle A1, og trykk deretter ENTER:

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

    Den opprinnelige returverdien er AAA: 0. Etter fem sekunder oppdateres verdien til AAA: 10, og etter 10 sekunder oppdateres verdien til AAA:15 og så videre.

  3. Skriv inn følgende formel i celle A2, og trykk ENTER:

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

    Den opprinnelige returverdien er BBB: 0. Hvert femte sekund øker celleverdien med 3.

  4. Skriv inn følgende formel i celle A3, og trykk ENTER:

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

    Den opprinnelige returverdien samsvarer med innholdet i celle A1 fordi dette er det samme emnet som brukes i A1.

  5. Skriv inn følgende formel i celle A4, og trykk ENTER: =RTD("ExcelRTD.RTDFunctions",,"AAA", 10)

    Den opprinnelige returverdien er AAA: 0. Hvert femte sekund øker celleverdien slik de andre cellene gjør. Vær oppmerksom på at returverdien ikke samsvarer med innholdet i celle A1 eller A3 fordi kombinasjonen av parametere som sendes til serveren, er forskjellig.

I denne illustrasjonen ble RTD-serveren kompilert, og Excel brukte kjøretidsversjonen av komponenten. For feilsøkingsformål kan RTD-servere kjøres fra Visual Basic IDE.

Slik kjører du i feilsøkingsmodus:

  1. Avslutt Microsoft Excel, og bytt til prosjektet i Visual Basic.
  2. Trykk F5 for å starte komponenten. Hvis dialogboksen Prosjektegenskaper vises, klikker du OK for å velge standardalternativet Vent på at komponenter skal opprettes.
  3. Kontroller at Øyeblikk-vinduet i Visual Basic vises. Når du skriver inn formler i cellene og når cellene oppdateres, kan du undersøke innholdet i det umiddelbare vinduet i Visual Basic for å se hvilke handlinger som utløser de ulike hendelsene.

Merk

Angående DisconnectData-hendelsen

Selv om Excel er abonnent på RTD-serveren, utløses DisconnectData-hendelsen når den ikke lenger trenger et emne (for eksempel når du sletter eller fjerner en RTD-formel i en celle). Excel kaller imidlertid ikke DisconnectData for hvert emne for RTD-serveren når arbeidsboken lukkes eller Excel avsluttes. I stedet kaller Excel bare ServerTerminate. Når du oppretter en RTD-server, bør du kode for nødvendig opprydding av emner eller andre objekter når ServerTerminate-hendelsen utløses.

(c) Microsoft Corporation 2001, med enerett. Bidrag fra Lori B. Turner, Microsoft Corporation.