Virus ist ein lateinisches Wort, welches Ärzte verwenden, wenn sie sagen wollen: 'Ich weiß es auch nicht'. - Bob Hope
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.
Neuen Kommentar schreiben
Datenbank mit TAPI-Funktionen
Hier findet man eine Beispiel-Datenbank mit den minimalen Funktionen, die man braucht, um mit Access via TAPI zu telefonieren:
Kommentare (5)
michael
am 21.09.2016erst mal vielen Dank für ihre Musterdatenbank.
Es ist wirklich super wie das klappt. Leider ist mir noch nicht alles klar.
Ich versuche nun seit Tagen eine kleine Veränderung zu programmieren. Ich möchte, dass wenn das Gespräch beendet (Gespräch beendet oder der Anrufer legt auf) die Telefonnummer aus dem Feld "eingehender Anruf" gelöscht wird.
Ich habe dazu eingebaut Case CS_DISCONNECTED
und einen Haltepunkt an dieser Stelle gesetzt. Leider ohne Erfolg.
Haben Sie eine Tipp für mich?
Danke Michael
Anna
am 22.09.2016MW
am 13.05.2018Ich dachte nun (als Access-Anfänger), dass ich die heruntergeladene Datei in eine bestehende Access-DB importiere und dann die Telefonie überall dort einsetzen kann.
Es kommt aber immer ein Fehler beim Öffnen des Formulars TAPI_Eventhändler: Benutzerdedinierter Typ nicht definiert.
Was habe ich falsch gemacht?
Anna
am 14.05.2018HB
am 29.08.2018Laufzeitfehler 9:
Index außerhalb des gültigen Bereichs
und beim debuggen wird auf die Zeile
" TapiDevices(I) = oCollAddress.AddressName" verwiesen.
Was habe ich falsch gemacht?
Anna
am 30.08.2018Robert Dannenmüller
am 30.10.2018Hum... passt alles bis zur Öffnung des Formulares "TAPI_Treiber", aber bei der Auswahl des treibers ist kein Eintrag vorhanden (TAPI Library scheint "eingebunden" zu sein...
Können Sie mir bitte helfen?
Danke
Grüsse aus Frankreich
RD
Anna Emde
am 31.10.2018Haben Sie schon einmal getestet, ob ein TAPI-Treiber installiert ist, z.B. mit dial.exe? Falls TAPI-Treiber korrekt installiert ist, am besten mal die Funktion zum Auflisten der TAPI-Treiber in der Access-Datenbank Schritt für Schritt durchlaufen, dann kann man das Problem vielleicht erkennen.
Und die Antwort:
Hat geklappt. War kein TAPI Device installiert.
Thomas
am 05.11.2018Anna
am 06.11.2018* Im Modul "Telefonie" die Variable oCall auf Public stellen.
Public oCall As ITBasicCallControl
* In der Funktion Tele_Outbound die Variable oCall nicht erneut definieren.
* Folgende neue Sub:
Public Sub Tele_hangup()
oCall.Disconnect DC_NORMAL
End Sub
Ob das klappt oder nicht, hängt offensichtlich von der Telefonanlage bzw. dem TAPI-Treiber ab - bei mir selbst funktioniert es leider nicht.