Rechnungsstellung mit QR Codes in Access

In einem meiner letzten Artikel zum Thema Rechnungsstellung habe ich erwähnt, dass manche Kundenüberweisungen aufgrund von Zahlendrehern in Rechnungsnummern nicht automatisiert zuordenbar waren. Dazu habe ich mir überlegt, wie ich die Zuordnungsquote erhöhen kann.

QR Code auf der Rechnung – Warum?

Eines Tages las ich einen Artikel über QR Codes (in diesem Zusammenhang oft als EPC QR Code oder als GiroCode bezeichnet), die vor allem im Paymentbereich in der Schweiz sehr verbreitet sind und eine Menge Vorteile bieten. Da kam mir die Idee, die QR Code Technologie für die Weiterentwicklung meines eigenen Rechnungsprogramm einzusetzen und die Rechnungen automatisch mit QR Codes auszustatten. Beim Einscannen des GiroCodes aus einer BankingApp heraus werden alle darin enthaltenen Daten dekodiert und direkt ins Überweisungsformular übernommen, sodass dieses nur noch zu kontrollieren und freizugeben ist. Davon würden beide Seiten profitieren – meine Kunden könnten sich das Abtippen oder Kopieren von Überweisungsdaten sparen und ich hätte dann keine Zuordnungsprobleme bei Überweisungen.

Hier stand ich vor der Überlegung, ob ich nicht einfach einen auf dem Markt frei erhältlichen QR Code Generator in meinem Rechnungsprogramm einbinde. Webbasierte Generatoren schieden allerdings gleich aus. Hauptsächlich, weil damit logischerweise kein Offlinebetrieb möglich ist. Zum anderen, weil ich nicht unbedingt Zahlungsinformationen durch das halbe Internet durchjagen wollte. Also drängte sich der Einsatz eines offline QR Code Generators nahezu auf. Da mich die Herausforderung gereizt hat und ich die Funktionsweise von QR Codes verstehen wollte, trieb mich der Forschungsdrang dazu, eigenen QR Code Generator zu programmieren.

Informationsbeschaffung

Bei der Recherche zum Thema QR Codes wurde mir schnell klar, dass viele Webseiten es relativ oberflächlich behandeln (ich kann es ihnen nicht verübeln 🙂 ) und nur einen groben Überblick über die Struktur, Aufbau und Funktionsweise geben, ohne jedoch stark in die Tiefe zu gehen. Es war also absehbar, dass ich für die komplexeren Teilgebiete, wie zum Beispiel Fehlerkorrektur oder Maskierung von QR Codes ganz andere Informationstiefe benötige. Dazu bin ich erst im englischsprachigen Raum fündig geworden (QR Code-Tutorial).

Auswahl der Technologie – VBA oder C#

Obwohl ich meinen QR Code Generator eigentlich nur für den Einsatz in meiner Microsoft Access-Rechnungsdatenbank (also in der VBA-Welt) vorgesehen habe, entschied ich mich, diesen nicht als ein VBA-Modul oder Add-In, sondern als eine C#-Klassenbibliothek unter Visual Studio zu entwickeln. Eine allgemeine Klassenbibliothek hätte den Charme, dass sich diese in eine Konsolen- oder auch in eine GUI-Anwendung integrieren ließe. Die geplante Verwendung aus der VBA-Welt heraus wäre durch die COM-Technologie ebenfalls abgedeckt.

Programmierung

Grundstruktur

Am Anfang des Projektes habe ich relativ schnell die ersten Erfolge erzielt und die statische Grundstruktur aufgebaut. So war die erste Version des QR Code Generators in der Lage, anhand des übergebenen Textes und des gewählten Korrekturlevels die benötigte Matrixgröße zu errechnen und die ganzen Pattern

  • Finderpattern
  • Alignmentpattern
  • Timingpattern

in der Matrix abzubilden und in Bildform zu visualisieren. Mathematisch und programmiertechnisch war dies relativ einfach zu bewerkstelligen.

Die QR Code-Spezifikation (ISO 18004) gibt viele Parameter vor, die je nach gewähltem Fehlerkorrekturlevel und QR Code-Größe mit unterschiedlichen Ausprägungen zu verwenden sind. Für die Verwaltung dieser Parameter habe ich mich für XML entschieden. Die Parameterverwaltung direkt in der Klassenstruktur würde zwar mit zwei Dateien weniger (xml und xsd) auskommen, wäre aber für mich persönlich deutlich unübersichtlicher. Da ich es nicht im Rahmen eines Kundenauftrages mit konkreten Vorgaben, sondern für mich entwickele, gilt hier – „mein Generator, meine Regeln“ 🙂

Um ein Gefühl für die Vielfalt der Parameterausprägungen zu bekommen, zeige ich hier einen kleinen Auszug aus dieser Konfigurationsdatei. Darin sieht man allgemeine Parameter für QR Codes in der Version 11 und spezielle Parameter für den Fehlerkorrekturlevel L in der Version 11. Insgesamt sieht die Spezifikation 40 Versionen und 4 Fehlerkorrekturlevel vor – am Ende bin ich da bei stolzen 3.000 Zeilen allein an Parameterdaten hinausgelaufen.

<qr-code version="11" number-of-remainder-bits="0">
	<alligment-pattern>
		<position>6</position>
		<position>30</position>
		<position>54</position>
	</alligment-pattern>
	<error-correction>
		<level-L>
			<capacity-in-characters>
				<numeric>772</numeric>
				<alphanumeric>468</alphanumeric>
				<byte>321</byte>
			</capacity-in-characters>
			<codeblock-information number-of-error-correction-codewords-per-block="20">
				<group index="1">
					<block number-per-group="4">
						<data-codeword number-per-block="81" />
					</block>
				</group>
			</codeblock-information>
		</level-L>
		...
	</error-correction>
</qr-code>

Für den Zugriff auf diese Parameterdatei habe ich eine separate Klasse implementiert, die auf dem Singleton-Entwurfsmuster basiert – so wird die Konfigurationsdatei physisch tatsächlich nur einmalig von der Festplatte gelesen. Das macht vor allem dann Sinn, wenn der Generator für eine Batchverarbeitung eingesetzt wird, wo mehrere Tausend QR Codes zu erzeugen sind. Diese Config-Klasse stellt dann über fachliche Methoden den lesenden Zugriff auf die einzelnen Parameter bereit.

Textkodierung

In Abhängigkeit davon, welche Daten der in QR Code zu überführende Text enthält, werden unterschiedliche Modi für die Kodierung der Daten herangezogen. Man verfolgt dabei das Ziel, den Text möglichst effizient (im Sinne von platzsparend) in eine Bitsequenz zu transformieren. In meiner Bibliothek habe ich folgende Modi realisiert.

  • Numeric
  • Alphanumeric
  • Byte

Jeder dieser Modi wandelt Texte auf unterschiedliche Art und Weise in eine Bitsequenz um. Der grundsätzliche Ablauf, bei dem die umgewandelte Bitsequenz mit Zusatzinformationen angereichert wird, ist jedoch in jedem Modus gleich. Von links werden an die Bitsequenz diese Daten angehängt:

  • Nummer des gewählten Kodierungsmodus (mode indicator)
  • Anzahl der im Text enthaltenen Zeichen (character count indicator)

Von rechts wird die Bitsequenz um diese Daten angereichert:

  • Bits, die das Ende der Nachricht einleiten (Terminatorbits)
  • Eventuell notwendige 0-Auffüllbits (Paddingbits), damit die Sequenz nach der Auffüllung aus kompletten Bytes besteht(also ohne Rest durch 8 teilbar ist)
  • Eventuell notwendige Auffüll-Bytes (Padding-Codewords), damit die Bitsequenz auf die erforderliche Ziellänge kommt

Diese Schritte der Anreicherung, die bei jedem Modus gleichermaßen zum Einsatz kommen, habe ich in der abstrakten Klasse MessageEncoderAbstract platziert.

Klassen für das Encoding des Textes

Von dieser Klasse erben konkrete Klassen, welche nur die Spezifika des jeweiligen Kodierungsmodus zu implementieren brauchen, nämlich die Art und Weise, wie der Text in die Bitsequenz überführt wird, sowie die Information, mit welcher Bitlänge die Anzahl der im Text enthaltenen Zeichen dargestellt werden soll.

Die tatsächliche Nutzung dieser Funktionalität ist innerhalb der Bibliothek sehr einfach. Dabei kommt die zentrale Rolle der statischen Klasse MessageEncoderFactory zu.

MessageEncoderAbstract MessageEncoder = MessageEncoderFactory.GetEncoder(message);
CodewordSet dataCodeWords = MessageEncoder.GetMessageCodewords(errorCorrectionLevel);

Beim Aufruf der GetEncoder-Methode, wird der übergebene Text analysiert. Anhand seiner Inhalte wird dabei der beste Modus ermittelt und ein Objekt der konkreten Kodierungsklasse (MessageNumericEncoder, bzw. MessageAlphanumericEncoder bzw. MessageByteEncoder) erzeugt und an den Aufrufer zurückgegeben.

Auf diesem Objekt wird dann die GetMessageCodewords Methode aufgerufen, die dann die tatsächliche Umwandlung des Textes in die Bitsequenz übernimmt und diese anschließend in Codeword-Auflistung transferiert, die dann in den nächsten Schritten für die Fehlerkorrekturerzeugung verwendet werden.

Fehlerkorrekturcodes

Das nächste Teilgebiet des Projektes forderte mich so richtig (mathematisch, programmiertechnisch und geistig) heraus. Es ging dabei um die Erzeugung von Fehlerkorrekturcodes. QR Codes können nämlich auch dann eingescannt und dekodiert werden, wenn ein gewisser Teil des Codes nicht lesbar ist. Beim höchsten Fehlerkorrekturlevel reichen gar 70% des QR Codes aus, ohne dass es dabei zu Dekodierungsproblemen kommt. Diese Fehlerkorrekturen werden, aus meiner Sicht als Nichtmathematiker, nach einem sehr komplizierten Verfahren namens Reed-Solomon (benannt nach zwei Überfliegern vom Massachusetts Institute of Technology) generiert.

Ohne die ausführlichen und für die Nichtdoktoren der Mathematik aufbereiteten Informationen aus dem Tutorial, hätte ich die Generierung der Fehlerkorrekturcodes definitiv nicht umsetzen können. Allerdings auch den wirklich ausführlich beschriebenen Ablauf in den Code zu gießen, war nicht ohne – wie oft hat man schon als Anwendungsentwickler, der eher im betriebswirtschaftlichen Umfeld unterwegs ist, eine Methode für die Polynomdivision zweier Gleichungen 68en Grades zu programmieren 🙂

Polynomdivisionen

Bei diesen Gleichungen handelt es sich um Generator- und Nachrichtenpolynomen. Das Generatorpolynom hängt ausschließlich von der Anzahl der zu berechnenden Fehlerkorrekturcodes ab. Da die ISO-18004 nur insgesamt 13 unterschiedliche Anzahlen je Block dafür vorsieht, wäre es denkbar, alle möglichen 13 Generatorpolynomen vorab zu berechnen und im Sourcecode oder in der Konfigurationsdatei vorzuhalten. Ich habe mich entschieden, die Erzeugung von Generatorpolynomen zur Laufzeit durch die Klasse PolynomialGenerator vorzunehmen. Um jedoch mehrfache Erzeugung von Generatorpolynomen (vor allem, wenn der QR Code Generator im Batchbetrieb läuft) zu vermeiden, habe ich diese Klasse mit einem statischen Member vom Typ Dictionary ausgestattet. In diesem fungieren die Fehlerkorrekturcodes-Anzahlen als Keys und die Generatorpolynome als Values. Jedes Mal, wenn der Konstruktor der Klasse aufgerufen wird, wird zuerst geprüft, ob für die übergebene Anzahl an Fehlerkorrekturcodes bereits ein Generatorpolynom errechnet worden ist. In diesem Fall wird dieses direkt aus dem Dictionary abgerufen, ohne dass es erneut berechnet werden muss.

Das Nachrichtenpolynom repräsentiert je nach ermittelter QR Code Version und vorgegebenem Fehlerkorrekturlevel, entweder die komplette Nachricht, bzw. nur einen Teil davon. Dies ist in der Spezifikation für jede Kombination der Version und des Fehlerkorrekturlevels vorgegeben und hat eine große Auswirkung auf das Aussehen und die Komplexität der Polynome.

Wollen wir beispielsweise den Text „Besonders geistreicher Spruch!“ in der höchsten Fehlerkorrekturstufe als QR Code generieren, ist dabei der Text, bzw. seine Bitsequenz auf 4 Nachrichtenpolynome mit je 9 Termen aufzuteilen und dafür jeweils 16 Fehlerkorrekturcodes auszurechen. Durch diese Aufteilung sehen die Nachrichtenpolynome nahezu süß und harmlos aus, wie es das unten stehende Beispiel schön zeigt:

65x8 + 228x7 + 38x6 + 87x5 + 54x4 + 246x3 + 230x2 + 70x + 87

Doch es geht auch anders. Wollen wir beispielsweise den Text „Besonders geistreicher Spruch, mit mehr Text, damit dieser in die Version 5 fällt!!!“ in der niedrigsten Fehlerkorrekturstufe als QR Code generieren, besagt die Spezifikation, den ganzen Text bzw. seine Bitsequenz nicht aufzuteilen, sondern als ein ganzes Nachrichtenpolynom zu verwenden und dafür insgesamt 26 Fehlerkorrekturcodes zu generieren. Dieser Vorgang bringt daher ein wahres Monstrum mit 108 Termen hervor:

69x107 + 68x106 + 38x105 + 87x104 + 54x103 + 246x102 + 230x101 + 70x100 + 87x99 + 39x98 + 50x97 + 6x96 + 118x95 + 86x94 + 151x93 + 55x92 + 71x91 + 38x90 + 86x89 + 150x88 + 54x87 + 134x86 + 87x85 + 34x84 + 5x83 + 55x82 + 7x81 + 39x80 + 86x79 + 54x78 + 130x77 + 194x76 + 6x75 + 214x74 + 151x73 + 66x72 + 6x71 + 214x70 + 86x69 + 135x68 + 34x67 + 5x66 + 70x65 + 87x64 + 135x63 + 66x62 + 194x61 + 6x60 + 70x59 + 22x58 + 214x57 + 151x56 + 66x55 + 6x54 + 70x53 + 150x52 + 87x51 + 54x50 + 87x49 + 34x48 + 6x47 + 150x46 + 226x45 + 6x44 + 70x43 + 150x42 + 82x41 + 5x40 + 102x39 + 87x38 + 39x37 + 54x36 + 150x35 + 246x34 + 226x33 + 3x32 + 82x31 + 6x30 + 110x29 + 70x28 + 198x27 + 199x26 + 66x25 + 18x24 + 18x23 + 16x22 + 236x21 + 17x20 + 236x19 + 17x18 + 236x17 + 17x16 + 236x15 + 17x14 + 236x13 + 17x12 + 236x11 + 17x10 + 236x9 + 17x8 + 236x7 + 17x6 + 236x5 + 17x4 + 236x3 + 17x2 + 236x + 17

Einem geübten Auge wird auffallen, dass in diesem Beispiel die letzten 22 Terme abwechselnd die Koeffizienten 17 und 236 haben. Es sind nämlich die im vorherigen Kapitel erwähnten Padding-Codewords. Da in der Version 5 mit dem Fehlerkorrekturlevel H in der Byte-Kodierung insgesamt 106 Zeichen Platz finden und unser Text mit 84 Zeichen deutlich unterhalb dieser maximalen Kapazität liegt, besagt die Spezifikation, den nicht genutzten Platz mit diesen Padding-Codewords, die jeweils 8 Bit lang sind, abwechselnd aufzufüllen.

Doch selbst dieses Monstrum ist noch nicht das Ende der Fahnenstange. Das toppt beispielsweise die Version 27 in der niedrigsten Fehlerkorrekturstufe, in der Nachrichtenpolynome mit insgesamt 123 Termen heranzuziehen sind.

Kehren wir jedoch nun zurück zum Wesentlichen.

Das Tutorial besagt, dass die Polynomdivision so oft durchzuführen ist, wie viele Terme das Nachrichtenpolynom hat. Klingt nach einem perfekten Einsatzszenario für eine For-Schleife, da die Anzahl der Durchläufe vor dem Beginn der Berechnung festzustehen scheint.

Bei jedem Schleifendurchlauf wird das Generatorpolynom mit dem ersten Term des Nachrichtenpolynoms bzw. mit dem des Ergebnispolynoms aus dem vorherigen Divisionsschritt multipliziert. Dadurch, dass laut der QR-Spezifikation sämtliche Generatorpolynomen (egal, welche Anzahl an Fehlerkorrekturen zu generieren ist) im ersten Term immer den Koeffizienten mit dem Wert ɑ0 haben, führt die im vorherigen Satz erwähnte Multiplikation des Generatorpolynoms mit dem ersten Terms des Nachrichtenpolynoms immer dazu, dass das Multiplikationsergebnis eben denselben ɑ Wert im ersten Term erhält, da beispielsweise ɑ0 * ɑ67 = ɑ67 ist.

Anschließend werden die Koeffizienten aus diesem Ergebnis und dem Nachrichtenpolynom bzw. dem Ergebnispolynom aus dem vorherigen Divisionsschritt aus der Alpha- in die Integer-Notation überführt und mit dem XOR-Operator verknüpft. Da beide Polynomen in ihren ersten Terms immer den selben Koeffizienten haben, bekommt der erste Term des Ergebnisses immer den Koeffizienten 0 und kann dadurch eliminiert werden. Am einfachsten ist diese XOR-Verknüpfung zu verstehen, wenn man die Integer-Notation gedanklich verlässt und sich die Koeffizienten in ihrer binärer Darstellung vorstellt. Der XOR-Operator besagt, dass zwei damit verknüpften Bits als Ergebnisbit immer dann 1 ergeben, wenn genau ein Bit den Wert 1 hat. Oder auch anders ausgedrückt, lautet das Ergebnisbit immer dann 0, wenn beide verknüpften Bits identisch sind.

Schauen wir uns mal an, was passiert, wenn man zwei identische Integer-Werte, beispielsweise 194 miteinander mit XOR verknüpft. Wie man sieht, ist deren binäre Darstellung logischerweise auch identisch, weswegen auch alle Bitpaare identisch sind. Daher ergibt die XOR-Verknüpfung von zwei identischen Integer-Werten immer den Wert 0.

194 -> 11000010
194 -> 11000010
       --------
       00000000 -> 0

Verknüpft man mit XOR hingegen einen 0 Integer-Wert mit einem beliebigen anderen größeren Integer-Wert, beispielsweise 254, wird das Ergebnis immer identisch mit dem größeren Wert sein, weil dabei alle Bits des größeren Wertes nicht verändert werden (aufgrund dessen, da immer ein Bit von jedem Paar den Wert 0 hat).

  0 -> 00000000
254 -> 11111110
       --------
       11111110 -> 254

In der Regel sind beide zu verknüpfenden Integer-Werte unterschiedlich, beispielsweise 243 und 187, sodass deren Verknüpfung dann tatsächlich einen komplett neuen Wert ergibt.

243 -> 11110011
187 -> 10111011
       --------
       01001000 -> 72

So funktioniert der Ablauf in rund 95-98% aller Fälle.

Im Laufe der Entwicklung bin ich auf die anderen 2-5% gestoßen, bei denen ein Divisionsschritt nicht nur den Koeffizienten des ersten Terms, sondern den des 2. oder gar des 3. Terms zu 0 werden ließ. In solchen Schritten konnten daher nicht nur der erste Term, sondern alle direkt darauf folgenden Terme eliminiert werden, die den Koeffizienten 0 hatten. Durch diese Besonderheit musste allerdings die Anzahl der noch auszuführenden Divisionen korrigiert werden.

Jeder, der programmiert hat, weiß, dass die Anpassung des Schleifenzählers in einer For-Schleife nicht wirklich die feine englische Art ist. Nach der Erkenntnis, dass die Anzahl der Divisionschritte vor dem Beginn der Division doch nicht zu 100% zuverlässig ermittelt werden kann, habe ich die For-Schleife durch eine While-Schleife ersetzt, um mich nicht mehr um die Anzahl der Durchläufe kümmern zu müssen. Diese Schleife läuft nämlich solange, solange der Exponent des ersten Terms vom Divisionsergebnis mindestens so hoch, wie die Anzahl der erforderlichen Fehlerkorrekturcodes ist.

while (leadTerm.ExponentOfX.Value >= this.numberOfErrorCorrectionwords)
{
	PolynomialEquitation generatorMultipliedByLeadTerm = generatorPolynomialWithFactor * leadTerm;

	messagePolynomial = messagePolynomial.XOR(generatorMultipliedByLeadTerm);
	messagePolynomial.RemoveLeadTermsWithZeroXCoefficient();

	leadTerm = messagePolynomial.LeadTerm;
}

Diese Besonderheit mit der Eliminierung von mehreren führenden Termen hat noch eine weitere Anpassung notwendig gemacht. Denn Polynomen, die in diesen Konstellationen am Ende erzeugt wurden, wiesen oft eine zu geringeiche Anzahl an Terms auf. Hier ist ein konkretes und aus meiner Sicht ein recht fieses Beispiel(hat mich einiges an Debugging-Aufwand gekostet):

Wir haben als Input eine Bitsequenz, die einen Teil des Textes repräsentiert. In dezimale Werte zur Verwendung als Koeffizienten des Nachrichtenpolynoms umgewandelt, sieht diese wie folgt aus:

117, 51, 20, 39, 21, 181, 245, 119, 117, 197, 162, 37

117x35 + 51x34 + 20x33 + 39x32 + 21x31 + 181x30 + 245x29 + 119x28 + 117x27 + 197x26 + 162x25 + 37x24

Da diese Sequenz zu einer Nachricht gehört, die in einem QR Code in der Version 14 und dem Fehlerkorrekturlevel H untergebracht wird, besagt die Spezifikation, dass pro Block 24 Fehlerkorrekturcodes benötigen werden und aus diesem Grund dieses Generatorpolynom zu verwenden ist (beide Polynomen wurden bereits auf die einheitliche Basis hinsichtlich ihres X-Exponenten gebracht).

ɑ0x35 + ɑ229x34 + ɑ121x33 + ɑ135x32 + ɑ48x31 + ɑ211x30 + ɑ117x29 + ɑ251x28 + ɑ126x27 + ɑ159x26 + ɑ180x25 + ɑ169x24 + ɑ152x23 + ɑ192x22 + ɑ226x21 + ɑ228x20 + ɑ218x19 + ɑ111x18 + ɑ0x17 + ɑ117x16 + ɑ232x15 + ɑ87x14 + ɑ96x13 + ɑ227x12 + ɑ21x11

Lassen wir die Division des Generator- und des Nachrichtenpolynoms komplett durchlaufen, erhalten wir dieses Ergebnis:

49x22 + 29x21 + 117x20 + 167x19 + 92x18 + 210x17 + 71x16 + 182x15 + 89x14 + 146x13 + 92x12 + 232x11 + 72x10 + 111x9 + 84x8 + 131x7 + 249x6 + 69x5 + 229x4 + 132x3 + 6x2 + 181x

Hmmm. Jetzt haben wir zwar ein Endpolynom, dessen Koeffizienten als Fehlerkorrekturcodes fungieren sollen. Allerdings hat dieses lediglich 22 Koeffizienten anstelle von erforderlichen 24 – hier kommen wir nicht um die Auffüllung mit 0-Werten herum.

Am Anfang habe ich mich schwer getan, da ich aus dem Tutorial nicht herauslesen konnte, ob die Auffüllung von links oder von rechts erfolgen musste. Nun, nach dem ich die Endpolynomen von Standarddivisionen aufmerksamer studiert habe, lag die Lösung eigentlich schon auf der Hand – es kann nämlich alle 3 Konstellationen geben (fehlende Termen von links, fehlende Termen von rechts, sowie auf beiden Seiten). Für die korrekte Auffüllung muss jedes zu kurz geratene Endpolynom lediglich mit dem „idealen“ Polynom verglichen werden, welches diese Voraussetzungen erfüllt:

  1. Das Polynom besteht aus insgesamt so vielen Terms, wie viele Fehlerkorrekturcodes benötigt werden.
  2. Der erste Terms des Polynoms weist den X-Exponenten auf, der um 1 kleiner ist als die Anzahl der Fehlerkorrekturcodes.
  3. Der letzte Terms des Polynoms weist den X-Exponenten von 0 auf.

Für die Prüfung und eventuell erforderliche Ergänzung des Endpolynoms, habe ich folgende kurze Methode entwickelt:

while (LastTerm.ExponentOfX.Value != 0)
{
	XCoefficient coefficientOfX = new XCoefficient(0);
	XExponent exponentOfX = new XExponent(LastTerm.ExponentOfX.Value - 1);

	this.equation.Add(new PolynomialTerm(coefficientOfX, exponentOfX));
}


while (LeadTerm.ExponentOfX.Value < numberOfErrorCorrectionwords - 1)
{
	XCoefficient coefficientOfX = new XCoefficient(0);
	XExponent exponentOfX = new XExponent(LeadTerm.ExponentOfX.Value + 1);

	this.equation.Insert(0, new PolynomialTerm(coefficientOfX, exponentOfX));
}

Diese prüft zuerst, ob der Exponent des letzten Term vom Polynom 0 ist. Wenn es nicht der Fall ist, werden ans Ende des Polynoms solange Terms mit dem Koeffizient von 0 und dem um 1 kleineren X-Exponenten angehängt, bis am Ende wirklich nur noch ein Koeffizient von 0 steht, der den X-Exponenten von 0 hat.

Nachdem dies erfolgt ist, wird der erste Term des Polynoms geprüft, ob die Anzahl der Fehlerkorrekturcodes minus 1 immer noch den X-Exponenten übersteigt. Ist es der Fall, werden an den Anfang des Polynoms solange Terms mit dem Koeffizient von 0 und dem um 1 größeren X-Exponenten angehängt, bis am Anfangs des Polynoms wirklich ein Term steht, der den X-Exponenten von Fehlerkorrekturcodes minus 1 hat.

So füllt diese Methode dieses zu kurze Polynom am Anfang und am Ende

49x22 + 29x21 + 117x20 + 167x19 + 92x18 + 210x17 + 71x16 + 182x15 + 89x14 + 146x13 + 92x12 + 232x11 + 72x10 + 111x9 + 84x8 + 131x7 + 249x6 + 69x5 + 229x4 + 132x3 + 6x2 + 181x

so auf, dass dieses seine Ziellänge erreicht:

0x23 + 49x22  + 29x21 + 117x20 + 167x19 + 92x18 + 210x17 + 71x16 + 182x15 + 89x14 + 146x13 + 92x12 + 232x11 + 72x10 + 111x9 + 84x8 + 131x7 + 249x6 + 69x5 + 229x4 + 132x3 + 6x2 + 181x + 0

Klassenhierarchie der Polynome

Verlieren wir ein paar Worte zur technischen Umsetzung und der Klassenhierarchie, die für die Arbeit mit Polynomen zum Einsatz kommt. Auf der obersten Ebene befindet sich die Klasse PolynomialEquitation. Objekte dieser Klasse repräsentieren konkrete Polynome, beispielsweise das Generatorpolynom oder das Nachrichtenpolynom.

Klasse PolynomialEquitation

Wie man dem Screenshot entnehmen kann, bietet diese Klasse grundlegende Methoden, um zum einen gewisse Rechenoperationen wie beispielsweise Multiplikation oder XOR durchzuführen und zum anderen um Polynomen durch das Hinzufügen von einzelnen Termen aufzubauen. Ebenfalls stellt diese Klasse zwei Methoden bereit, welche die Formatierung des Polynoms (entweder in der AlphaNotation bzw. in der IntegerNotation) übernehmen.

Die einzelnen Termen, aus denen sich Polynome zusammensetzen, werden durch Objekte der Klasse PolynomialTerm repräsentiert. Diese Klasse stellt zwei Konstruktoren bereit, mit denen sich entweder Termen in der AlphaNotation bzw. IntegerNotation erzeugen lassen

Auf der unterstehen (fachlichen) Ebene befinden sich die 3 Klassen, welche die einzelnen Bestandteile eines Polynomterms repräsentieren. Ein Term in der Alphanotation, beispielsweise ɑ229x34 besteht aus einem Objekt der Klasse AlphaExponent und einem Objekt der Klasse XExponent. Ein Term in der Integernotation wiederum besteht aus einem Objekt der Klasse XExponent und einem Objekt der Klasse XExponent, beispielsweise 69x5

Jede dieser Klassen stellt auch konkrete Implementierungen der ToString()-Methode, welche für eine html-gestützte Ausgabe sorgen.

Auf der untersten (technischen) Ebene befindet sich die abstrakte Klasse PolynomialTermPart, welche ein paar gemeinsam genutzte Methode für die 3 oben genannten Klassen zur Verfügung stellt.

Maskierung

Das letzte Teilgebiet mit der Darstellung der kodierten Daten in der Matrix und deren Maskierung für ein besseres maschinelles Einscannen war verglichen mit dem vorherigen Teil schon fast zu einfach. Das hat mich auch richtig motiviert, dass ich den komplizierten Teil schon hinter mir habe und kurz vor der Fertigstellung stehe. Tja, und dann kam das Testen:-)

Testen

Einem QR Code sieht man mit unbewaffnetem Auge in der Regel nicht an, ob es richtig aufgebaut ist. Für den Schnelltest nutzte ich dabei mein Handy – beim Einscannen hatte ich dann direkt die Rückmeldung, ob der QR Code richtig war oder zumindest eingescannt werden konnte. Wenn jedoch der erzeugte QR Code nicht lesbar war, dann ging die Suche nach dem Fehler erst richtig los.

Einen guten Dienst hat mir dabei diese Webseite https://www.nayuki.io/page/creating-a-qr-code-step-by-step geleistet. Im Gegensatz zu anderen webbasierten QR Code Generatoren, erlaubt der Betreiber hier einen Blick in den „Maschinenraum“. So ist es zum Beispiel möglich, sich die generierten Korrekturwörter oder die Penaltyscores der einzelnen Masken anzeigen zu lassen. Durch den Vergleich mit dem Output meiner Klasse konnte ich den Fehler zumindest ganz grob lokalisieren. Der Löwenanteil aller Fehler lag in der Klasse für die Erzeugung der Fehlerkorrekturcodes – mit Sicherheit habe ich für die Fehlersuche und deren Behebung fast genauso lang gebraucht wie für die Entwicklung . Aufgrund deren Komplexität auch nicht weiter verwunderlich – aus sprachlicher Sicht dennoch amüsant:-). Alle anderen Klassen waren da deutlich robuster und wiesen kaum Fehler auf.

Projektergebnis

Herausgekommen ist aus diesem Projekt, wie erwähnt, ein QR Code Generator in Form einer dll-Datei, eine Wrapperklasse für die Nutzung des Generators in der VBA-Welt (ebenfalls als eine dll-Datei) und eine Parameter-XML-Datei mit QR Code Spezifikationen inklusive einer XSD-Datei.

Klasse QRCodeGenerator

Alle C#-Klassen bis auf die Klasse QRCodeGenerator haben die Sichtbarkeit internal und treten somit gar nicht in Erscheinung, sondern verrichten ihren Dienst ausschließlich im Hintergrund. Die Klasse QRCodeGenerator ist public und fungiert somit als die Schnittstelle nach außen. Die Nutzung dieser Klasse in anderen Anwendungen (beispielsweise in einer GUI- oder einer Konsolenanwendung) ist wirklich sehr einfach, weil nahezu alle Parameter entweder von der Klasse selbst errechnet oder in der Parameterdatei „nachgeschlagen“ werden. Das geht natürlich etwas auf die Kosten der Flexibilität, sodass man beispielsweise keinen Einfluss auf die QR Code Größe hat – die Einfachheit in der Nutzung war mir persönlich aber am wichtigsten. Zumal im Fall der Fälle sich der Generator ohne Probleme erweitern lässt, um gewisse Parameter manuell vorgeben zu können.

Diese zentrale Klasse QRCodeGenerator bietet einen dreifach überlagerten Konstruktor, der jeweils unterschiedliche Eingabeparameter erwartet:

allgemeiner Konstruktor (für die .NET-Welt)

Der erste Konstruktor wird verwendet, wenn die Klasse in ein normales Visual Studio Projekt eingebunden ist und es um die Erzeugung eines QR Codes geht, den man mit einem bestimmten Fehlerkorrekturlevel erzeugen möchte.

public QRCodeGenerator(string message, QRErrorCorrectionLevel errorCorrectionLevel)
{
//
}

allgemeiner Konstruktor (für die VBA-Welt)

Der zweite Konstruktor ähnelt sehr dem ersten und ist für den Einsatz in der VBA-Welt gedacht, da VBA die im ersten Konstruktor eingesetzte Enumeration vom Typ QRErrorCorrectionLevel natürlich nicht kennt.

public QRCodeGenerator(string message, string errorCorrectionLevel)
{
//
}

fachlicher Konstruktor (für die .NET- und VBA-Welt)

Möchte man mit der Klasse einen Girocode für eine Rechnung generieren, dann kommt der dritte und letzte Konstruktor zum Einsatz. Dieser nimmt fachliche Bestandteile einer Rechnung als Eingabeparameter entgegen und kümmert sich im Hintergrund um den korrekten Aufbau des Girocode-Strings. Ein kurzer Ausflug zum Wikipedia-Artikel European Payment Council (EPC) verriet mir, welchen Aufbau der EPC-Text haben muss, damit alle darin hinterlegten Überweisungsinformationen von BankingApps korrekt eingelesen werden können. Der Artikel ist sehr übersichtlich und klar geschrieben, sodass ich den nicht zusammenzufassen brauche. Das einzige, was ich extra erwähnen würde, ist, dass im Betrag der dezimale Punkt(nicht Komma!) als Trennzeichen zu verwenden ist. Dies hab ich nämlich beim ersten Lesen übersehen.

Da der EPC-Standard die Korrekturstufe M voraussetzt, wird diese automatisch bei der Erzeugung mit dem 3. Konstruktor verwendet.

public QRCodeGenerator(string iban, string accountOwner, double amount, string invoiceReference, string bic = "")
{
//
}

Nachdem das Objekt mit einem der Konstruktoren erzeigt ist, kann mit einer der beiden SaveAs-Methoden der generierte QR Code auf die Festplatte gespeichert werden.

Klasse QRCodeGeneratorVBALibrary

Um den QR Code Generator auch unter Microsoft Access nutzen zu können, war es erforderlich, ihn von einer Wrapperklasse aufzurufen zu lassen, welche die COM-Schnittstelle implementiert. Diese enthält tatsächlich keinerlei Verarbeitungslogik, sondern macht den Generator „lediglich“ für die VBA-Welt aufrufbar. Dafür ist eine einmalige DLL-Registrierung auf dem Zielrechner erforderlich. Zu diesem Zweck gibt es vom .NET-Framework das entsprechende Tool RegAsm.exe.

Anbindung des QR Code Generators an die Rechnungsstellung

In meinen ersten Versionen des QR Code Generators wurden erzeugte QR Codes physisch auf der Festplatte unter einem festen Namen gespeichert und anschließend direkt vom Access-Rechnungsbericht eingebunden und dargestellt. Doch damit war ich nicht ganz zufrieden. Es war keine Lösung wie aus einem Guss, sondern ein Umweg, bei dem ich mich mit unschönen Nebeneffekten wie verzögertes Speichern befassen musste. Dabei war die Codezeile für die QR-Codeerzeugung schon abgearbeitet, der PC war unter Umständen jedoch noch mit dem physischen Speichervorgang des QR Codes beschäftigt, sodass die nächste Codezeile beim Einbinden des QR Codes ins Leere lief.

Zum Glück hat sich bei meiner Recherche herausgestellt, dass Access nicht nur die Möglichkeit bietet, Bilder von der Festplatte einzubinden, sondern kann auch Bilder darstellen, die in Form eines Bytearrays vorliegen.
Das war genau das, was ich gesucht habe. Aus diesem Grund habe ich neben SVG- und JPEG-Exportmethode auch eine weitere Methode realisiert, die das vorbereitete QR Code-Bildobjekt in einen Bytestrom umwandelt und diesen ausgibt. So konnte ich den Output, den diese Methode liefert, direkt dem Bildcontainer (seinem Attribut pictureData) im Access Bericht zuweisen.

    On Error Resume Next
    
    Set objQrGenerator = CreateObject("QRCodeGeneratorVBALibrary")
    If Err.Number = 0 Then
        Call objQrGenerator.CreateQRCodeGenerator(strQrCodeMessage, "M")
        If Err.Number = 0 Then
            bytQrCodeArray = objQrGenerator.getQRBytes()
        End If
    End If
    
    Err.Clear
    On Error GoTo 0

Diese Zuweisung bewirkt, dass auf der Rechnung der EPC GiroCode dargestellt wird, ohne dass dieser zuvor als Bild abgespeichert werden muss. Der komplette Prozess läuft ausschließlich auf dem lokalen Rechner ab und benötigt zu keinem Zeitpunkt eine Internetverbindung.

Fazit

Im Nachhinein betrachtet ist das ganze Projekt deutlich deutlich komplexer geworden als ich anfangs gedacht habe. Dennoch war es aus dem Blickwinkel Wissensaufbau enorm bereichernd und lehrreich, vor allem was Datenstrukturen, Designpattern und C#-Entwicklung im Allgemeinen angeht.

Sollten Sie ebenfalls Interesse an diesem Generator haben, sprechen Sie mich einfach an.

71 thoughts on “Rechnungsstellung mit QR Codes in Access

  1. Hallo Anton,
    Kompliment an den Autor Deiner Webseite und danke fürs teilen 🙂

    Ich bin auf diesen Content gestoßen, da Ich mich mit der Offlinerzeugung von QR-Codes via VBA beschäftigen möchte.

    Den Quellcode der QRCodegeneratorBatch.exe habe Ich nicht finden können, daher meine Frage, wie viel Zeit hat dieses Projekt in Anspruch genommen?

    1. Hallo Marco, vielen Dank für die Anerkennung, ich leite sie gerne an Tony aka Anton weiter 🙂
      Das Batchprogramm habe ich an 1-2 Abenden entwickelt – dort befindet sich allerdings auch keinerlei Geschäfts/Verarbeitungslogik. Es nimmt lediglich übergebene Parameter (eine Zeichenkette für einen einzelnen QR-Code oder CSV-Dateipfad für eine Sammelerzeugung) entgegen, prüft sie und leitet sie an den QR-CodeGenerator weiter und gibt sein Output in Form von QR-Bildern aus. Die Hauptarbeit war definitiv der QR-CodeGenerator – wenn man alles berücksichtigt, also Recherche der QR-Spezifikationen, Implementierung und das Testen, dann war ich mit Sicherheit 1,5-2 Monate damit beschäftigt. Natürlich nicht am Stück von morgens bis Abends, aber dennoch nahezu jeden Abend.
      Wenn du bei deinem Vorhaben Fragen hast, kannst dich gerne melden, können in einer Zoom-Session die Thematik besprechen.

      Viele Grüße
      Anton

  2. Hallo ,
    ich bin auf der Suche nach genau der oben beschriebenen Methode auf meine Rechnungen einen EPC-QR CODE zu drucken. Ich muss aber gestehen, dass ich bei weitem nicht so mit Access bewandert bin wie der Autor, deshalb stelle ich hier einfach mal die Frage ob es möglich ist diese Methode als Beispieldatenbank zu kaufen?
    Vielen Dank!

    1. Hallo Herr Reinhold, sehr gerne, lassen Sie uns hierzu telefonieren und prüfen, wie sich die QR-Generator-Bibliothek in Ihre Datenbank integrieren lässt.
      Viele Grüße
      Anton Ristau

  3. Hallo Tony,
    1. Frage
    kannst Du das „Tool“ in einer Beispiel-Access-Anwendung inkl. einer kurzen Erklärtung bereit stellen.
    Dann könnte ich dem EPC QR Code in meine Rechnung einbauen.
    2. Frage was würde es kosten

    Danke
    lg
    Peter

    1. Servus Peter, vielen Dank für deine Nachricht und dein Interesse. Meine QR-Bibliothek entstammt einem Hobbyprojekt bzw. Machbarkeitsstudie – daher kann ich sie dir unentgeltlich bereitstellen. Welche Version (32Bit / 64Bit) benötigst du? Ich kann dir gerne ein Anbindungsbeispiel + Beispiel für die Registrierung im Betriebssystem per Mail zukommen lassen.

      Wenn du darüber hinaus Unterstützung benötigst, kann ich dich gerne im Rahmen einer Beauftragung begleiten

      Viele Grüße
      Tony

  4. Hallo Tony
    Das interessiert mich auch sehr. In meiner App nutze ich eine API um den Swiss-QR-Code zu erstellen. Das hat natürlich einige Nachteile. Daher würde ich gerne deine Methode übernehmen. Kannst du mir auch deine Beispiel DB und die Erklärung per Mail senden?
    Viele Grüsse
    Friedemann

    1. Hallo Friedemann, ich kann dir gerne die QR-Code-Bibliothek zukommen lassen. Allerdings generiert sie nur ganz normale QR-Codes (nicht die spezifische Swiss-QR-Variante mit dem Schweizer Kreuz) und unterstützt lediglich die Zeichenkodierung ISO-8859-1 (kein UTF-8, welches so weit ich weiß bei Swiss QR zum Einsatz kommt).
      Für welche Rechnerarchitektur benötigst du die Bibliothek (32Bit oder 64Bit)?

      Viele Grüße
      Tony

  5. Hallo Tony,
    ich benutze Microsoft® Access® für Microsoft 365 MSO (Version 2302 Build 16.0.16130.20298) 32 Bit und würde die QR-Generator-Bibliothek gerne in eine von mir programmierten Mieternebenkostenabrechnung einbauen.

    Vielen Dank im voraus

    Thomas

    1. Hallo Thomas, kann ich gerne machen. Witzig, ich bin ebenfalls an der Entwicklung einer Datenbankanwendung zur Erstellung von Nebenkostenabrechnungen, bin allerdings noch relativ weit weg von der Fertigstellung:-)
      Ich nehme an, du benötigst die Bibliothek für einen 64Bit-Rechner?

      Viele Grüße
      Tony

  6. Hallo Tony,
    mit großem Interesse habe ich deinen Beitrag gelesen. Ich würde deinen QR Code auch gerne verwenden. Kannst du mir auch die Beispiel Datenbank und eine Anleitung dazu zukommen lassen?
    Danke schon mal vorweg.

    Gruß Florian

    1. Hallo Florian, vielen Dank für deinen Kommentar. Ja, das kann ich gerne machen.
      Ist es für deine private Anwendung gedacht oder für den kommerziellen Einsatz?
      Ich melde mich per Mail bei dir

      Viele Grüße
      Tony

  7. Hallo Florian, danke für Deinen tollen Artikel.
    Gerne hätte ich die Beispieldatenbank und die Anleitung dazu ebenfalls.
    Ich habe Access 365, 32 Bit auf einem 64 Bit Rechner laufen.
    Meine Rechnungsdatenbank ist schon sehr lange im Einsatz und hat schon viele Updates von Funktionen erhalten. Mehrere Firmen möglich, E-Mail-Rechnungen, Postleitzahldaten (Deutsch), Mehrwertsteuer oder nicht, Einzelpositionen/ Zeitabrechnung, uvm. Vielleicht können wir tauschen?
    LG Benno

    1. Hallo Benno, vielen Dank für deinen Kommentar und die Blumen:-) ich schicke dir die Bibliothek samt einer Beispieldatenbank gerne zu. Den Registrierungsprozess sowie die Anbindung in die VBA-Welt ist in der beiliegenden README-Datei relativ ausführlich beschrieben und mit Quellcodebeispielen unterlegt. Wenn du deine Rechnungsdatenbank selbst entwickelt hast und somit die ganzen relevanten Berichte und Codebehinds kennst, dann ist die Integration schnell gemacht.
      Sollten sich noch weitere Fragen ergeben, können wir gerne telefonieren. Ich bin derzeit relativ eingespannt, sodass es aktuell bei mir eher gegen 16-18 Uhr möglich ist. Ich melde mich per Mail bei dir

      Viele Grüße
      Tony

  8. Hallo Tony, auch hier wieder ein exzellenter Beitrag von dem ich sofort dachte, das wäre auch was für mein anstehendes Projekt das auch eine Rechnungsbearbeitung beinhalten wird. Ich bin also sehr daran interessiert, die Bibliothek samt Beispieldatenbank zu bekommen. Vielen Dank für die Mühe und lese gerne weiter die Beiträge.
    Viele Grüße
    Harald

    1. Hallo Harald, vielen Dank, das freut mich sehr! Ich kann dir die QR-Code-Bibliothek und die Access-Datei als Anbindungsbeispiel gerne bereitstellen. Mit welcher Access-Version (32Bit / 64Bit) entwickelst du, damit ich die richtige Version generieren kann?

      Viel Erfolg beim anstehenden Vorhaben – es wird bestimmt ein größeres Projekt, oder? Für meine eigene Rechnungsstellung, obwohl sie schon relativ lange im Einsatz ist, habe ich noch eine riesige, immer länger werdende Backet-List für Anforderungen, die ich noch umsetzen möchte:-)

      Viele Grüße
      Tony

      1. Hallo Tony, sorry, hatte vergessen zu erwähnen, dass ich nur noch mit 64Bit hantiere. In der Tat ist es auch immer so, dass neue Wünsche geäußert werden und diese dann meistens auch erfüllt werden.
        Die Rechnungslegung ist nur ein kleiner aber auch wichtiger Teil des Projekts, es handelt sich in erster Linie um eine Dokumentationssoftware, es werden aber auch Leistungen in Rechnung gestellt , irgendwie muss ja auch Geld reinkommen.
        Viele Grüße Harald

      1. Hallo Tony,
        Wunderbare Arbeit.

        Es würde mir sehr viel Arbeit ersparen wenn Du so nett wärst mir auch die Beispieldatenbank zur Verfügung zu stellen

        Grund: Sohnemann hat den Meister gemacht möchte nun in die Selbständigkeit.

        Möchte ihm mit einer Datenbank unterstützen.

        Eigentlich hantiere ich mit einem 64 Bit System. Weiß jedoch nicht ob es ggf auf einem 32 Bit System kaufen muss.

        Beide wäre super. Danke

        Nochmal erwähnt: Klasse Arbeit.

        Gruß. Mario Altmann

        1. Hallo Mario, vielen Dank für die Blumen! Die QR-Code-Bibliothek kann ich dir gerne für beide Plattformen (32Bit / 64Bit) bereitstellen.
          Die Beispieldatenbank, die ich zusammen mit der QRCode-Bibliothek verteile, ist nichts weiter als eine leere Access-Datei mit einem
          Formular und einem Bericht, auf dem ein QRCode generiert wird. Sie ist ausschließlich dazu da, die Verwendung und die Anbindung der QR-Code-Bibliothek besser nachvollziehen zu können, um diese in eigenen Accessdatenbanken einzubinden.
          Wenn es für deine Zwecke ausreicht, stelle ich es dir gerne bereit.

          Die Rechnungsdatenbank plane ich mittelfristig zu einem Produkt zu entwickeln. Aktuell kann ich sie also weder verkaufen noch weitergeben.

          Viele Grüße
          Tony

    1. Hallo Werner, ich habe dir die Bibliothek samt einer Access-Datei zugeschickt, mit der die Anbindung der Bibliothek nachvollzogen werden kann. Darüber hinaus ist da auch eine Readme beigefügt 🙂

      Viele Grüße
      Tony

  9. Hallo Tony,

    auch ich bin wegen einer kleinen Firma meiner Frau an deiner Beispiel-DB und der QR Code Bib interessiert (32 bit). Das würde mir sehr weiterhelfen.

    LG
    Guido

  10. Hallo Tony,
    habe großes Interesse an deiner Beispieldatenbank.
    Wär dir sehr dankbar für die Demodatenbank in 64 bit
    Viele Grüsse
    Thomas

  11. Moin Anton,
    Respekt vor deinem Ehrgeiz und Durchhaltevermögen. Ich wäre bestimmt bei der Polynomdivision ausgestiegen. Nun suche ich just eine Bibliothek für c# und bin auf diesen Beitrag gestoßen. Kann ich das bekommen? Ich möchte das zunächst nur für eigene Rechnungen nutzen.
    Danke.
    Viele Grüße Oliver

    1. Hallo Oliver, ich danke dir! Ja, in der Tat, die Umsetzung der Polynomdivision erforderte einige Klimmzüge, vor allem bei der Fehlersuche:-)
      Ich kanns es dir gerne bereitstellen, welche Version 32/64 benötigst du?

      Viele Grüße
      Tony

  12. Hallo Anton,
    bin beim recherchieren nach den Grundlagen zur EPC-QR-Code-Erstellung auf deinen Beitrag gestoßen. Mein Kompliment für deine Arbeit. Deine Entwicklungsschritte und besonders die Anwendungsbreite ist beeindruckend. Aus der Praxis für die Praxis!
    Erstelle selbst meine Rechnungen aus Access heraus. Darf ich dich bitten, mir die DLL und zugehörige Dateien (32 bit) zur Verfügung zu stellen.

    Vielen Dank für deine Arbeit!

    Gruß Manfred

    1. Hallo Manfred, vielen Dank für deinen Kommentar und Anerkennung, ich freue mich immer über Leser auf meinem Blog! Apropo Namensverwechslung – es ist keine. Tony ist einfach mein Nickname hier auf dem Blog.
      Wegen der DLL melde ich mich per Mail bei dir.

      Viele Grüße
      Tony aka Anton

  13. Hallo Tony,
    sorry für die Namensverwechslung in meinem vorigen Kommentar. Er ist doch das Persönlichste was wir haben. Bin wohl beim lesen sämtlicher Beiträge aus der Spur geraten.
    Gruß Manfred

  14. Hallo Tony!

    Nach langer Suche im Netz bin ich auf deinen Blog gekommen. Würde auch gerne meine Access-DB mit deiner QR-Code Lösung erweitern. Bitte höflichst um Zusendung der Demodatenbank für 32/64bit. Danke!

    Gruß aus der verschneiten Steiermark,
    LG Philipp

  15. Hallo Toni,
    mit großem Interesse habe ich hier die Informationen, Anmerkungen, etc, gelesen.
    Auch ich möchte gerne in Access für unterschiedliche Zwecke generierte QR-Codes in Berichten, eMails (aus Access heraus generiert), etc. verwenden und würde mich freuen, wenn du mir die 32- und 64-bit Varianten mit Beispiel-DB zusenden könntest.
    Ich sage schon mal danke im Voraus und wünsche schöne Weihnachtsfeiertage.

    Martin

    1. Hallo Martin, vielen Dank für deinen Kommentar. Es freut mich, dass dir der Beitrag gefallen hat. Ich lass dir die QR-Code-Bibliothek die Tage per Mail zukommen.

      Wünsche dir ebenfalls schöne Weihnachtszeit
      Viele Grüße
      Tony

  16. Hallo Tony,
    ich finde deine Lösung sehr interessant und würde mich freuen, wenn du mir deine Beispieldatenbank zukommen lassen könntest ( 32 und 64-bit, bin gerade am Umstellen). Ich möchte sie für private Rechnungen verwenden.
    Danke und Frohe Weihnachten!
    Bert

    1. Hallo Bert, vielen Dank für deinen Kommentar. Ich habe dir die Bibliothek gerade an deine Emailadresse geschickt.

      Wünsche dir ebenfalls frohe Weihnachten (nachträglich) und ein erfolgreiches Neues Jahr
      Viele Grüße
      Tony

  17. Hallo Tony,
    ich programmiere gerade ein Fakturierungsprogramm. Meine Lösung soll ab Access 2013, 32 und 64 bit, bis 365 laufen können.
    Über die Zusendung der Bibliothek (32- und 64-bit) mit Beispieldatenbank würde ich mich sehr freuen.
    Herzlichen Dank udn vioele Grüße!
    Jürgen

    1. Hallo Jürgen, vielen Dank für deinen Kommentar! Die Anbindung ab Access 2013 sollte kein Problem sein. Ich schicke dir die Bibliothek per Mail zu. Wünsche dir bei deinem Vorhaben viel Erfolg

      Viele Grüße
      Tony

  18. Kompliment an den ausführlichen und trotzdem sehr gut verständlichen Artikel. Ich bin im Zuge meiner Recherche nach genau so einer Lösung darüber gestolpert, weil ich etwas in der Art für Rechnungen für einen Verein suche. Ich wäre sehr an der Nutzung des QR Code Generators interessiert, speziell auch, wie ich es in Berichte einbinde, die in einer Art Serienbrief automatisiert verschickt werden.

    Vielen Dank!!
    Martin

    1. Hallo Martin, vielen Dank für die Blumen! Jepp, der Generator lässt sich sowohl für einzelne Generierungen in Berichten, als auch in Form von Massenverarbeitung einsetzen. Ich mach die Mail fertig und schick dir die Dll’s zu.

      Viele Grüße
      Tony

  19. Hallo Anton
    nicht nur das Du eine Akribische Arbeit hingelegt hast, sondern die Früchte Deiner Arbeit anderen zur Verfügung stellst. Verdienst allerhöste Anerkennung. Respekt. Wie meine Vorredner bin ich an einen Generator für MS-Access und einer Demo-Datenbank interessiert. Und würde mich über eine positive Rückmeldung freuen.
    Vielen Dank für Deine Mühen.
    Viele Grüße aus dem närrischen Rheinland Gerry

    1. Hallo Gerry, vielen Dank für deinen Kommentar und die Anerkennung, das freut mich!
      Ja, ich kann dir die Bibliothek dir gerne die Tage per Mail zukommen lassen. Ich melde mich bei dir.

      Viele Grüße
      Tony

  20. Hallo Anton
    Ich habe mir grossen Interesse deinen Bericht gelesen, grosses Kompliment.
    Ich bin am Aufbau einer Vereinsdatenbank und mochte gerne die Rechnunsstellung intergireren. Könntest du mir diee Bibliothek (32/64 Bit zustellen.
    Besten Dank im Voraus
    Viele Grüsse
    Beat

  21. Hallo Tony,

    danke für die tolle Erklärung – du nimmst damit einen wesentlichen Teil meiner geplanten Arbeit vorweg, weil genau das hatte ich vor.
    Würd mich auch für deine DemoDB interessieren.

    Liebe Grüße aus Wien,
    Christian

  22. Hallo,
    also Respekt! Das ist wirklich ein toller Artikel. Könnte ich mir das Beispiel für ACCESS auch mal anschauen.
    Würde mich über die Libery sehr freuen.
    Viele Grüße und ein schönes Wochenende
    Jörn

  23. Hallo Anton
    Hut ab! So weit bin ich bei weitem nicht.
    Könntest du mir das Beispiel mailen. DANKE
    Und vielleicht gibts ja irgendwo ein Spendenkonto
    LG
    Gerald

    1. Hallo Gerald, danke dir! Ja, das kann ich gerne machen – die Mail kommt morgen. Und ein Spendenkonto lässt sich ebenfalls auftreiben 🙂

      Viele Grüße
      Tony

  24. Hallo Tony,
    dein Projekt hast du vor fast genau 3 Jahren hier gepostet und ich bin begeistert, dass sich während der ganzen Zeit immer wieder Leute gemeldet haben, die den QR Code Generator benötigen können.
    Auch ich könnte deinen Code Generator prima ihn die Mitgliederverwaltung unserer Feuerwehr einbauen und würde mich freuen, wenn du ihn mir mit einer Beispiel-DB zukommen lassen könntest.
    Liebe Grüße aus Österreich und Gut Wehr,
    Ingemar

    1. Hallo Ingemar, ja, das stimmt, im Laufe der Jahre kamen insgesamt recht viele Anfragen von Interessenten, die die DLL auch in ihren Datenbanken einsetzen wollten, vermutlich aufgrund der Offlinefähigkeit.
      Die Feuerwehr war allerdings bisher nicht dabei 🙂

      Ich lasse dir die DLL und ein Anbindungsbeispiel per Mail zukommen

      Viele Grüße und viel Erfolg beim Einsatz!
      Tony

  25. Hallo Tony.

    Mache mich gerade dran in meine Rechnungsdatenbank (wir sind eine 2 Personen Firma, die Weiterbildungen für Pflegepersonen anbietet). einen QR Code für die Online-Überweisung zu integrieren.
    Ich habe das Rechnungspogramm für den Eigengebrauch selbst programmiert und erstellt.

    Jetzt habe ich mal kurz gegoogelt, wie ich´s angehe und da bin ich auf dich gestossen.
    Auch mir würde der Code Generator prima Dieste leisten und mir eine Menge Arbeit sparen, wenn ich das nicht selbst realisieren muss.

    Ich würde mich freuen, wenn du mir deine Beispiel-DB zukommen lassen könntest. Ich arbeite mit 32bit Access in Win 64 bit.
    Danke für deine Engagement!

    Beste Grüße aus Österreich
    Hannes

    1. Hallo Hannes, vielen Dank für deinen ausführlichen Kommentar! Ich kann dir gerne helfen und die DLL bereitstellen. Ich schicke es dir per Mail zu.

      Es würde mich interessieren, warum du deine Rechnungsdatenbank selbst programmiert hast – steckte dahinter die Lust am Entwickeln oder bestimmte fachliche Überlegungen, die in der aktuellen Rechnungssoftwarelandschaft nicht zu finden waren?

      Viele Grüße
      Tony

  26. Hallo Tony,

    Erstmal danke für die Zusendung per eMail. Das ist sehr nettt von dir!!

    Ich habe früher beruflich auch im KFZ/Landtechnik Bereich Warenwirtschaftssysteme entwickelt und sehr viel mit MS Access realisiert.

    Bin dann allerdings von der Software-Entwicklung und IT in den letzten 10-15 Jahren mehr und mehr weg gekommen, aber als es bei der Realisierung einer Rechnungs- Kurs- und Teilnehmerverwaltung für die eigene Firma kommen sollte, lag es natürlich nahe das Ganze selbst in die Hand zu nehmen.

    Einerseits war es natürlich auch Spieltrieb und die Freude daran sich alles nach den eigenen Anorderungen und Vorstellung umsetzen zu können, andererseits waren es auch sehr individuelle Lösungen die gefragt waren, die es so am Markt nicht wirklich bzw. nur mit großen finanziellen Aufwendung gegeben hätte.

    Aber ich brauche dir eh nichts erzhählen, wie du weisst wird sowas nie „fertig“ und man zimmert immer etwas daran herum.

    Beste Grüße
    Hannes

    1. Hallo Hannes, hehe, klar, welcher Softwareentwickler kennt es nicht:) Mal ist es Fluch, mal ist es Segen.
      Meine Backetliste mit den weiteren Features zum Rechnungsprogramm ist recht lang, aber nachdem alle Grundfunktionalitäten stehen (Rechnungen schreiben, verschicken, ablegen und mit Zahlungsinformationen abgleichen), widme ich mich anderen Projekten:)

      Viele Grüße
      Tony

  27. Hallo Anton,
    Wir sind eine kleine Wassergenossenschaft und ich mache mit MS Access die Abrechnungen. Ich würde gerne einen QR Code in die Rechnungen einbauen und bin sehr interessiert an deiner Beispiel DB (64 bit).
    Meine VBA-Kenntnisse reichen da nicht aus.
    Gruß Josef

    1. Hallo Josef, vielen Dank für dein Interesse. Ich schick dir die Bibliothek, die Readme und eine Access-Datenbank mit einem Anbindungsbeispiel per Mail zu. Anhand dieser lässt sich die Anbindung gut nachvollziehen.

      Viele Grüße
      Anton

  28. Hallo Anton,
    ich habe eine kleine Tischlerei und würde gerne einen QR-Code in mein VBS Projekt und in meine Access Anwendung zu Testzwecken einbauen. Ich bin sehr interessiert an einer Beispiel DB auf 64Bit-Version.
    Viele Grüße
    Martin

  29. Hallo Anton,
    ich bin gerade dabei, eine Rechnungsdatenbank auf XRechnung zu modernisieren. Darum würde ich auch gerne den QR-Code zusätzlich integrieren. Könntest du mir ebenfalls die Bibliothek sowie der Erklärung bzw. eine Beispieldatenbank zukommen lassen? Das wäre super. Meine Rechnungsdatenbank soll auf 32 und 64 Bit Versionen laufen. Vielen Dank

    1. Hallo Marcus, hehe, ich bin ebenfalls dabei, mein Rechnungstool XRechnungsfähig zu machen. Ja, kann ich gerne machen, melde mich die Tage per Mail

      Viele Grüße
      Anton

  30. Hallo Tony,
    ich finde deine Lösung sehr spannend und würde mich freuen, wenn du mir deine Beispieldatenbank für 64-Bit zukommen lassen könntest.
    Ich würde sie gerne für private Rechnungen verwenden.
    Vielen lieben Dank und Grüße aus München
    Ediz

  31. Hallo Anton!

    Wie schon die User vor mir, möchte ich Dir zu deiner Arbeit gratulieren.
    Ich beschäftige mich selber gerade mit dem Thema EPC QR Code für Rechnungen und bin bei meiner Recherche auf deinen Artikel gestossen. Ich habe mich als „Hobby-Access-Entwickler“ bis dato noch nicht getraut das Thema anzugehen. (die Komplexität dieses Thema ist in deinem Artikel sehr gut beschrieben)
    Wie Josef entwickle ich gerade für unsere Wassergenossenschaft ein Abrechnungstool für den Wasserverbrauch unserer Mitglieder.

    Kannst Du mir deinen QR Code Generator und vielleicht eine Beispieldatenbank für 64bit zur Verfügung stellen? Damit wäre mir sehr geholfen 😉

    Vielen Dank und schöne Grüße aus dem Salzkammergut in Österreich!

    1. Hallo Stefan, vielen Dank für deine Anerkennung und deinen Kommentar. Gerne kann ich dir den DLL-Generator mit dem Anbindungsbeispielen bereitstellen (kommt gleich per Mail). Es ist echt interessant, dass es recht viele Österreicher sind, die diesen Beitrag kommentieren 🙂

      Viele Grüße
      Anton

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert