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.
Start et nytt ActiveX DLL-prosjekt i Visual Basic.
Klikk Referanser på Prosjekt-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.
Klikk Project1-egenskaper på Prosjekt-menyen. Endre prosjektnavnet til ExcelRTD, og klikk deretter OK.
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
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
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
Klikk Lag ExcelRTD.dll på Fil-menyen for å bygge komponenten.
Bruke RTD-serveren i Excel
Start en ny arbeidsbok i Microsoft Excel.
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.
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.
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.
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:
- Avslutt Microsoft Excel, og bytt til prosjektet i Visual Basic.
- Trykk F5 for å starte komponenten. Hvis dialogboksen Prosjektegenskaper vises, klikker du OK for å velge standardalternativet Vent på at komponenter skal opprettes.
- 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.