Die Freiheit ist immer die Freiheit des Andersdenkenden. - Rosa Luxemburg
emde IT-LÖSUNGEN
> Tel. 08131 / 99 69 80-0
> Kontakt per E-Mail
Telefonieren mit Access und Windows TAPI
27. Mai 2015
Hat man eine Datenbank mit Kontaktdaten (Adressen und Telefonnummern), so liegt der Wunsch nahe, dass man per Klick direkt aus der Datenbank telefonieren kann sowie bei eingehenden Telefonanrufen in der Datenbank automatisch den entsprechenden Kontakt (Kunden) angezeigt bekommt.
Zur Realisierung dieser beiden essentiellen Funktionen braucht man nicht mehr als eine TAPI-fähige Telefonanlage und das Windows TAPI.
Die benötigten Funktionen befinden sich in der Microsoft TAPI 3.0 Type Library, die man über die Verweise einbinden muss.
Außerdem deklariert man folgende Objekte und Konstanten:
Public oTapi As TAPI Public oAddress As ITAddress Public Const CS_CONNECTED = 2 Public Const CS_OFFERING = 4
TAPI-Devices
Jeder Benutzer muss eines der auf seinem Rechner vorhandenen TAPI-Devices auswählen, dessen Name in den Einstellungen des Benutzers gespeichert wird.
Zur Auswahl werden beim Start der Datenbank die vorhandenen TAPI-Devices ermittelt und in ein globales Array TapiDevices gespeichert (siehe unten: Initialisierung beim Start der Datenbank).
Event handler für ankommende Anrufe
Es wird ein leeres Formular TAPI definiert, welches beim Start der Datenbank mit der Eigenschaft Hidden=True geöffnet wird und welches lediglich die Aufgabe hat, in seinem Modul das Objekt zu beherbergen, welches mittels der Eigenschaft WithEvents die TAPI-Ereignisse - hier: die eingehenden Anrufe - behandelt. Im Formularmodul wird also deklariert:
Private WithEvents oTapiWithEvents As TAPI
Initialisierung beim Start der Datenbank
Dieser Event handler muss nun beim Starten der Datenbank - bzw. beim Öffnen des Formulars TAPI - initialisiert werden.
Dazu muss zunächst festgestellt werden, welches TAPI-Device der aktuelle Benutzer verwendet. Zu diesem Zweck werden sämtliche TAPI-Devices auf dem aktuellen Rechner aufgelistet und mit dem Eintrag in den Einstellungen des Benutzers verglichen. Wird ein passendes Device gefunden, so wird dieses verwendet; außerdem merkt man sich dessen Index in einer Variablen AktDeviceID.
Gleichzeitig füllen wir so unser Array TapiDevices, mit dem wir neuen Benutzern ein entsprechendes Auswahlfeld füllen können.
Set oCollAddresses = oTapi.Addresses I = 0 For Each oCollAddress In oCollAddresses TapiDevices(I) = oCollAddress.AddressName If TapiDevices(I) = BenutzerDeviceName Then Set oAddress = oCollAddress AktDeviceID = I End If I = I + 1 Next Set oCollAddresses = Nothing
Wurde ein passendes Device gefunden, kann der Event handler nun initialisiert werden:
Dim CallbackInstance As Integer, MediaTypes As Integer Dim RegToken As Long Dim fOwner As Boolean, fMonitor As Boolean oTapi.EventFilter = TE_CALLSTATE Set oTapiWithEvents = oTapi fOwner = False fMonitor = True MediaTypes = TAPIMEDIATYPE_AUDIO CallbackInstance = 1 RegToken = oTapi.RegisterCallNotifications(oAddress, _ fMonitor, fOwner, MediaTypes, CallbackInstance)
Anruf per Klick
Je nach Telefonanlage muss einer in der Datenbank enthaltenen Nummer möglicherweise noch eine "0" vorangestellt werden. Außerdem müssen vermutlich die Formatierungszeichen entfernt werden, so dass die Nummer nur noch aus Ziffern besteht.
Mit folgendem Code wird die Nummer dann angewählt:
Dim oCall As ITBasicCallControl Set oCall = oAddress.CreateCall(Nummer, _ LINEADDRESSTYPE_PHONENUMBER, TAPIMEDIATYPE_AUDIO) oCall.Connect False ' False = asynchron
Steht kein TAPI-Provider zur Verfügung, erhält man beim Wählen folgende Fehlermeldung: "Die Methode Address für das Objekt ITCallInfo2 ist fehlgeschlagen."
Identifizierung eingehender Anrufe
Ankommende Anrufe werden vom Event handler bearbeitet. Dieser ist bei mir folgendermaßen definiert:
Private Sub oTapiWithEvents_Event( _ ByVal TapiEvent As TAPI3Lib.TAPI_EVENT, _ ByVal pEvent As Object) Dim oReceivedCallInfo As ITCallInfo Dim oCallState As ITCallStateEvent Dim TelNummer As Variant Const Err_CallInfoString = -2147467259 ' Die Methode 'CallInfoString' für das Objekt ' ITCallInfo2 ist fehlgeschlagen Const DiffSec = 60 Static LastTelNummer As Variant Static LastTime As Variant Static CallID As Long On Error GoTo Err_oTapiWithEvents_Event If IsEmpty(LastTelNummer) Then LastTelNummer = "" If IsEmpty(LastTime) Then LastTime = DateAdd("d", -1, Now) Select Case TapiEvent Case TE_CALLSTATE Set oCallState = pEvent Set oReceivedCallInfo = oCallState.Call TelNummer = _ oReceivedCallInfo.CallInfoString(CIS_CALLERIDNUMBER) Select Case oCallState.State Case CS_OFFERING ' Falls neuer Anruf -> neue CallID generieren ' Dieser Status kommt aber auch noch mal direkt ' vor dem CS_CONNECTED, deshalb brauchen wir ' einen Toleranzzeitraum von DiffSec, damit das ' nicht als neuer Anruf gewertet wird. If (TelNummer <> LastTelNummer) _ Or (DateDiff("s", LastTime, Now) > DiffSec) Then Randomize CallID = Int((999999 * Rnd) + 1) End If LastTelNummer = TelNummer LastTime = Now CCallIDOffering = CallID Tele_OnCallerID CallID, TelNummer Case CS_CONNECTED Tele_OnConnected CallID ' damit ggf. ein Anruf von derselben Nummer ' direkt danach wieder erkannt wird LastTime = DateAdd("d", -1, Now) End Select End Select Exit Sub Err_oTapiWithEvents_Event: If Err = Err_CallInfoString Then ' Info über Nummer des Anrufers liegt noch nicht vor ' - einfach ignorieren Err = 0 Else F E H L E R B E H A N D L U N G End If Exit Sub End Sub
Mit dieser etwas kompliziert wirkenden Konstruktion hat es folgende Bewandnis:
Die Ereignisse CS_OFFERING und CS_CONNECTED treten beim Eingehen bzw. beim Annehmen eines Anrufs innerhalb einiger Millisekunden mehrmals hintereinander auf.
Um einen Anruf trotzdem (möglichst) eindeutig zu identifizieren, erhalten Anrufe von derselben Telefonnummer innerhalb eines gewissen Toleranzzeitraums (hier: 60 Sekunden) dieselbe CallID.
Mit dieser CallID wird der Telefonanruf nun bearbeitet: Beim Eingehen des Anrufs wird versucht, den Anrufer in der Datenbank zu ermitteln und anzuzeigen. Außerdem werden die Anrufe in einer Tabelle gespeichert; dabei wird vermerkt, ob der Anruf angenommen wurde oder nicht. So kann z.B. ein Mitarbeiter nach einer Abwesenheit vom Arbeitsplatz sehen, welche Anrufe er verpasst hat.
Hier findet man eine Beispiel-Datenbank mit den minimalen Funktionen, die man braucht, um mit Access via TAPI zu telefonieren: » Download wintapi.zip.
Datenbank mit TAPI-Funktionen
Hier findet man eine Beispiel-Datenbank mit den minimalen Funktionen, die man braucht, um mit Access via TAPI zu telefonieren: