Wie uns warum wir Rechnungen aus Outlook direkt in lexoffice hochladen wollen

Als wir vor einiger Zeit zu lexoffice wechselten, war einer der Gründe, die einfach zu nutzende API. Als kleiner Betrieb wollen wir so viel wie möglich automatisieren. Wir haben daher bereits einen Abgleich mit unserer Ticketlösung, die nicht nur die Stammdaten überträgt, sondern auch eine Abrechnung der Tickets vornehmen kann. Das spart ernorm viel Zeit. Auch aus unserem Online-Shop erfolgt eine automatische Übertragung an lexoffice. Nur das Hochladen der eingehenden Rechnungen hatten wir bis vor Kurzem noch manuell durchgeführt. Zwar geht das schon simpel, benötigte jedoch bisher mehr Zeit als uns lieb war. 

Aus diesem Grund haben wir uns überlegt, wie wir einfach und kostengünstig den Prozess optimieren können. Da wir in Outlook schon andere eigene VBA-Markos nutzen, dachten wir uns, wir bemühen mal ChatGPT, uns ein Outlook-Makro zum Hochladen von Anhängen zu erstellen. Es ist erstaunlich wie gut ChatGPT unsere Anforderung verstanden hat und uns zumindest ein gutes Grundgerüst für ein Makro erstellt hat. Nachdem wir unsere Anpassung für die Nutzung der lexoffice API vorgenommen hatten, wollte einfach partour kein Upload funktionieren. Wir haben diverse Versuche zur Findung der Problems unternommen. Hier konnte ChatGPT uns leider dann auch keine Hilfe mehr leisten und wir haben intensiv nach Lösungen online recharchiert. Nur ein Stack Overflow Beitrag hat uns dann zu der Lösung gebracht, da einfach der Aufbau des Payload etwas anderes aussehen musste, als die Lösung von ChatGPT und die sonst gängigen Hilfestellungen aus dem Netz offerierten.

Bisher haben wir zudem nach dem Uplaod von Rechnungen in Outlook diese mit einem "Erledigt"-Häkchen versehen, damit wir wissen, welche Rechnungen bereits hochgeladen wurden. Auch das haben wir dann noch zusätzlich in unserem VBA -Makro hinzugefügt. Damit wir zudem schnell und einfach auf das Makro zugreifen können, haben wir ein eigenes Symbol in die Schnellstartleiste von Outlook hinzugefügt, das dann wiederum über eine kurze Tastenkombination erreicht werden kann.

Am Ende haben wir nun mit geringem Aufwand eine Lösung geschaffen, die unseren Aufwand zum Hochladen unserer eingehenden Rechnungen erheblich vereinfacht hat. Den Aufwand zum Erstellen des VBA-Makros haben wir damit in kurzer Zeit wieder drin und es macht auf diesem Weg einfach auch mehr Spaß. Damit alle profitieren können, stellen wir nachfolgend einmal  den Code des Makros zur Verfügung. Die entsprechende Stellen, an den der individuelle API-Schlüssel eingetragen werden muss, ist entsprechend hervorgehoben.

 

Der magische Code


Sub Lexoffice_Rechnung_hochladen()
Dim oXMLHTTP As Object
Dim sURL As String
Dim sAPIKey As String
Dim sTempPath As String
Dim oForm As Object
Dim oAttach As Attachment
Dim strRequest As String
Dim strBoundary As String
Dim d As String
    
Set oXMLHTTP = CreateObject("WinHttp.WinHttprequest.5.1")
sURL = "https://api.lexoffice.io/v1/files"
sAPIKey = "" ' Hier Ihren API Key eintragen
sTempPath = "C:\Temp\lexofficetemp\" 'Hier einen temporären Pfad angeben

Set oAttach = ActiveExplorer.Selection.Item(1).Attachments(1)

strBoundary = "---------------------------" & Format(Now, "dd-mmm-yyyy-hh-mm-ss")

oAttach.SaveAsFile sTempPath & oAttach.fileName

Dim File, FILESIZE
Set ado = CreateObject("ADODB.Stream")
ado.Type = 1                                      'binary
ado.Open
ado.LoadFromFile sTempPath & oAttach.fileName
ado.Position = 0
FILESIZE = ado.Size
File = ado.Read
ado.Close

Set ado = CreateObject("ADODB.Stream")
d = "--" + strBoundary + vbCrLf
d = d + "Content-Disposition: form-data; name=""type""" + vbCrLf + vbCrLf
d = d + "voucher" + vbCrLf
d = d + "--" + strBoundary + vbCrLf
d = d + "Content-Disposition: form-data; name=""file"";"
d = d + " filename=""" + oAttach.fileName + """" + vbCrLf
d = d + "Content-Type: application/pdf" + vbCrLf + vbCrLf
ado.Type = 1                                      'binary
ado.Open
ado.Write ToBytes(d)
ado.Write File
ado.Write ToBytes(vbCrLf + "--" + strBoundary + "--" + vbCrLf)
ado.Position = 0


Set oForm = CreateObject("WinHttp.WinHttpRequest.5.1")
oForm.Open "POST", sURL, False
oForm.setRequestHeader "Authorization", "Bearer " & sAPIKey
oForm.setRequestHeader "Accept", "application/json"
oForm.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & strBoundary
oForm.Send ado.Read

If oForm.Status = 202 Then
    ActiveExplorer.Selection.Item(1).MarkAsTask (olMarkComplete)
    ActiveExplorer.Selection.Item(1).Save
Else
    MsgBox "Fehler beim Senden des Anhangs an die API." & oForm.Status & vbCrLf & oForm.responseText
End If

Kill sTempPath & oAttach.fileName

Set oXMLHTTP = Nothing
Set oAttach = Nothing
End Sub

Function ToBytes(str As String) As Variant
Dim ado As Object
Set ado = CreateObject("ADODB.Stream")
ado.Open
ado.Type = 2                                      ' text
ado.Charset = "_autodetect"
ado.WriteText str
ado.Position = 0
ado.Type = 1
ToBytes = ado.Read
ado.Close
End Function

Hinweise in eigener Sache

Wir können zu dem Code und wie man Makros in Outlook einbindet, keinen kostenlosen Support anbieten.  Sie können stattdessen Ihre Anfrage an Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein. stellen, die wir dann kostenpflichtig bearbeiten.

 

Links zum Thema

Der wichtige Stack Overflow-Artikel mit dem entscheidendem Hinweis -  https://stackoverflow.com/questions/64626636/vba-pdf-file-upload-using-http-post
VBA-Code-Signierung um nur signierte Makros zuzulassen - https://support.microsoft.com/de-de/office/digitales-signieren-ihres-vba-makroprojekts-956e9cc8-bbf6-4365-8bfa-98505ecd1c01
Eigenes Signatur-Zertifikat ausstellen -  https://support.microsoft.com/de-de/office/durch-hinzuf%C3%BCgen-einer-digitalen-signatur-vertrauen-ausdr%C3%BCcken-5f4ebff3-360d-4b61-b2f8-ce0dfb53adf6
Outlook-Shortcut für Makros hinzufügen - https://ekiwi-blog.de/7864/outlook-shortcut-fuer-makro-festlegen/
VBA Debug Print zum Debuggen nutzen - https://www.wallstreetmojo.com/vba-debug-print/


Wir benutzen Cookies

Wir nutzen Cookies auf unserer Website. Einige von ihnen sind essenziell für den Betrieb der Seite, während andere uns helfen, diese Website und die Nutzererfahrung zu verbessern (Tracking Cookies). Sie können selbst entscheiden, ob Sie die Cookies zulassen möchten. Bitte beachten Sie, dass bei einer Ablehnung womöglich nicht mehr alle Funktionalitäten der Seite zur Verfügung stehen.