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
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/