QR Codes mit VBA und Google Chart API erstellen

Im Internet gibt es zahlreiche Webseiten, mit denen man QR-Codes erzeugen kann. Man tippt einfach die zu verschlüsselnde Zeichenkette ein und erhalt eine entsprechende Grafik mit dem QR-Code. Was ist jedoch, wenn man dies nicht per Hand, sondern maschinell erledigen möchte? Hierfür könnte die Google Chart API eine mögliche Lösung sein.

In diesem Tutorial stelle ich ein kleines, von mir entwickeltes, Programm vor und erkläre ausführlich, wie dieses funktioniert. Es ist in der Lage, Texte aus einem Array mit Hilfe der Google Chart API automatisch in QR Codes zu überführen. Mit einer kleinen Anpassung kann auch eine Exceltabelle als Quelle für die umzuwandelnden Texte angebunden werden, sodass die Textpflege noch einfacher wird.

Was ist Google Chart API?

Die Google Chart API ist ein Webdienst von Google, welcher aus übergebenen Daten Diagramme im png-Format erzeugen kann. Dieser Dienst ist nicht neu, er dürfte vor rund 15 Jahren online gegangen und sollte eigentlich vor 3 Jahren abgeschaltet worden sein. Zum Zeitpunkt der Artikelveröffentlichung funktioniert diese aber noch tadellos. Dieser Artikel befasst sich allerdings nur mit der QR Code Generierung.

Erläuterungen zum Quellcode

Schauen wir uns das Programm Zeile für Zeile an und versuchen deren Funktionsweise nachzuvollziehen.

Variablendeklaration

    Dim objWebRequest           As Object
    Dim byteBildArray()         As Byte
    Dim strURL                  As String
    Dim strBildPfad             As String
    Dim strInhalteArray(1 To 3) As String
    Dim bytZaehler              As Byte

    strInhalteArray(1) = "MeinErsterTest"
    strInhalteArray(2) = "VBA"
    strInhalteArray(3) = "Programmierung"

In diesem Block findet die Deklaration benötigter Variablen und die Belegung des Arrays mit umzuwandelnden Beispieltexten statt. Mittlerweile verwende ich ganz gerne die sogenannte ungarische Variablennotation. Diese zeichnet sich dadurch aus, dass sich der Datentyp der jeweiligen Variablen am Variablennamen erkennen lässt.

  • str für String
  • byt für Byte
  • lng für Long
  • obj für Objekt

So (zumindest geht es mir so) vermeide ich größtenteils Flüchtigkeitsfehler, die durch eine falsche Variablenzuweisung entstehen.

WinHttpRequest

Set objWebRequest = CreateObject("WinHttp.WinHttpRequest.5.1")

Damit unser Programm überhaupt mit der API kommunizieren kann, benötigen wir das WinHttpRequest-Objekt, welches hier in der Zeile erzeugt wird.

API-Adresse und die Parameterliste

strURL = "http://chart.apis.google.com/chart?chs=500x500&cht=qr&chld=L&chl="

Was die API genau zu tun hat, „erfährt“ sie durch die übermittelten Parameter. An dieser Stelle setzen wir diese Parameter zu einer Zeichenkette zusammen. Der erste Teil des Strings http://chart.apis.google.com/chart ist die Adresse, unter der die API erreichbar ist. Das darauf folgende Fragezeichen kündigt die Parameterliste an. Diese ist an den Key-Value-Pairs erkennbar chs=500×500&cht=qr&chld=L&chl=. Links des Gleichheitszeichens steht der Attributsname und rechts seine Ausprägung. Die Key-Value-Pairs werden durch das &-Zeichen voneinander getrennt. Die Entwickler dieser API waren bei der Namensgebung richtig sparsam – mir erschließt sich die Attributsbedeutung nur, wenn ich sie zusammen mit Ausprägungen vor Augen habe.

  • chs – hier wird die Größe des QR-Code-Bildes in Pixel angegeben
  • cht – da hinterlegt man, um welchen Grafiktyp es sich handelt, unserenfalls ist es immer qr
  • chld – hier wird der Fehlerkorrekturlevel des QR-Codes hinterlegt, in unserem Fall ist es L(ow). Es gibt noch Ausprägungen M(edium), Q(artil), H(igh), die noch höheren Fehlerkorrekturlevel ermöglichen
  • chl – an der Stelle wird der zu umzuwandelnde Text angegeben

Schleifenverarbeitung

For bytZaehler = LBound(strInhalteArray) To UBound(strInhalteArray)
…
Next bytZaehler

Damit das Programm alle Texte des Arrays umwandeln kann, wird hier eine For-Schleife eingesetzt, die das komplette Array vom ersten bis zum letzten Element durchläuft. Da die Anzahl der Arrayelemente variieren kann, ermittele ich den Start- und Endindex jeweils mit LBound bzw. UBound-Funktion.

Request an die API absetzen

objWebRequest.Open "POST", strURL & strInhalteArray(bytZaehler), False
objWebRequest.send

Um mit der API kommunizieren zu können, müssen wir zuerst die Verbindung vorbereiten. Dafür wird der Methode open der zuvor gebildete String mit der API-Adresse und den Parametern übergeben. Zu diesem festen String geben wir auch den zu verschlüsselnden Text aus dem Array mit. Bei jedem Schleifendurchlauf wird dann der jeweils nächste Text an die Methode übergeben. Der letzte Parameter false teilt der API mit, dass sie synchron aufgerufen wird. Das bedeutet, dass der Aufrufer der API so lange „wartet“, bis sie das Ergebnis zurück geliefert hat. Lässt sich die Antwort der API jedoch auf sich warten, bricht die Verarbeitung aufgrund eines Timeouts ab. In der nächsten Zeile wird der eben vorbereitete Request an die API übermittelt.

Response erhalten und verarbeiten

        strBildPfad = ActiveWorkbook.Path & "/bild_" & bytZaehler & ".png"
                
        byteBildArray = objWebRequest.responseBody
        Call byteArrayAlsDateiSpeichern(strBildPfad, byteBildArray)
        
    Next bytZaehler

End Sub

Private Sub byteArrayAlsDateiSpeichern(strDateiKomplettPfad As String, byteArray() As Byte)

    Open strDateiKomplettPfad For Binary As #1
        Put #1, , byteArray()
    Close #1
    
End Sub

In diesem letzten Abschnitt kümmert sich das Programm darum, einen Bildnamen inklusive Pfad zu generieren. Dafür verwenden wir den Index des jeweiligen Textes aus dem Array, um die Eindeutigkeit des Bildnamens sicherzustellen.

Nun ist endlich die Zeit da, das Ergebnis der API abzuholen. Dieses wird durch die Eigenschaft responseBody bereitgestellt. Anschließend wird der Response in ein ByteArray überführt und an die Funktion für die Speicherung als PNG-Bild weitergereicht.

Quellcode des kompletten Programms

Um das Programm laufen lassen zu können, habe ich hier dieses als Quellcode aufgeführt.

 Public Sub qrCodeErzeugen()
   
    Dim objWebRequest           As Object
    Dim byteBildArray()         As Byte
    Dim strURL                  As String
    Dim strBildPfad             As String
    Dim strInhalteArray(1 To 3) As String
    Dim bytZaehler              As Byte

    strInhalteArray(1) = "MeinErsterTest"
    strInhalteArray(2) = "VBA"
    strInhalteArray(3) = "Programmierung"

    Set objWebRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
    strURL = "http://chart.apis.google.com/chart?chs=500x500&cht=qr&chld=L&chl="

    For bytZaehler = LBound(strInhalteArray) To UBound(strInhalteArray)
    
        objWebRequest.Open "POST", strURL & strInhalteArray(bytZaehler), False
        objWebRequest.send
        
        strBildPfad = ActiveWorkbook.Path & "/bild_" & bytZaehler & ".png"
                
        byteBildArray = objWebRequest.responseBody
        Call byteArrayAlsDateiSpeichern(strBildPfad, byteBildArray)
        
    Next bytZaehler

End Sub


Private Sub byteArrayAlsDateiSpeichern(strDateiKomplettPfad As String, byteArray() As Byte)

    Open strDateiKomplettPfad For Binary As #1
        Put #1, , byteArray()
    Close #1
    
End Sub

Notwendige Anpassungen für den produktiven Einsatz

Der hier vorgestellte Quellcode ist voll funktionsfähig und eignet sich gut dazu, die Abläufe nachvollziehen zu können. Um den Quellcode nicht mit Details zu überfrachten, die nichts mit QR-Code-Erstellung zu tun haben, habe ich auf jegliche Fehlerbehandlung verzichtet.

Das bedeutet, dass es für einen echten Produktionsbetrieb noch einiges an Prüfungen zu hinterlegen wäre. Denn bereits eine Kleinigkeit (fehlende Internetverbindung) reicht aus, um den Code mit einem hässlichen Abbruch auf die Nase fallen zu lassen.

Sinnvolle Prüfungen wären zum Beispiel:

  • ob die Erzeugung des Requestobjektes funktioniert hat.
  • ob sich der Response mit dem Statuscode 200 zurückgemeldet hat.
  • ob bei der Speicherung des Bilder Probleme gegeben hat

Fazit

Bei sensiblen Daten, wie Überweisungs-, Personen- oder Rechnungsdaten, sollte man sich ganz genau überlegen, ob man diese durch die halbe Welt schicken möchte. Eine bessere und datenschutzkonforme Variante wäre es, die QR-Codeerzeugung mit einem offline Generator durchzuführen, welches die Generierung lokal durchführt, sodass die Daten den Rechner nicht verlassen. Für Schulungszwecke oder für den „Hausgebrauch“, beispielsweise zur Verschlüsselung von unkritischen Daten wie Artikelnummern ist diese API aber definitiv zu empfehlen und erspart einem eine Installation eines QR Code Generators.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.