Währungen runden

Im Finanzsektor wird alles sehr genau genommen. Wird über kleinere Rundungsfehler an anderer Stelle gern einmal hinweggesehen, so sind hier Inkonsistenzen in der Regel absolut inakzeptabel. Einzelne Cent-Beträge können sich über Millionen von Datensätzen zu größeren Summen aufaddieren. Wohin Sie genau schauen müssen, um solche Umstände zu vermeiden, untersuchen die folgenden Ausführungen.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1605_Runden.accdb

Geldbeträge im Tabellenentwurf

Für Zahlen mit Nachkommastellen kommen unter Access im Prinzip vier Datentypen infrage: Single, Double, Currency und Decimal, also Fließkommazahl einfacher und doppelter Genauigkeit, sowie Währungs- und Dezimaltyp.

Single scheidet wegen der geringen Genauigkeit aus. Hier werden zur Speicherung nur vier Bytes verwendet, während der Double-Typ acht Bytes benötigt. Wie groß der Unterschied letztlich ist, können Sie mit einem kleinen Test im VBA-Direktfenster ermitteln. Lassen Sie sich die Ergebnisse dieser beiden Zeilen ausgeben:

  CSng (Now)
 CDbl (Now)

Die Funktion Now gibt das aktuelle Datum samt Uhrzeit aus, wobei diesem Date-Typ tatsächlich ein Double-Wert unterliegt. CSng wandelt den Wert in einen Single-Typ um, CDbl in einen Double-Typ. Sie erhalten nun etwa

42516,4 (Single)
42516,4020486111 (Double)

Wären dies Geldbeträge, so betrüge die Differenz bereits circa 0,2 Cent!

Die große Zahl an Nachkommastellen lässt Double als für Währungen geeignet erscheinen. Doch immerhin muss es einen Grund geben, warum der Typ Currency zusätzlich zur Verfügung steht. Einerseits führt sein Einsatz dazu, dass in Tabellen auch gleich automatisch das Währungszeichen erscheint. Zudem ist die Zahl der Nachkommastellen gleich zwei. Andererseits speichert Currency aber Zahlen auch nach einem anderen System. Liegt dem Double-Typ mathematisch ein Exponentialsystem zugrunde, hantiert Currency mit einer festen Zahl von ganzzahligen Stellen, nämlich 19. Die Umwandlung in einen Fließkommatyp geschieht hier rein optisch durch Setzen des Kommas an die viertletzte Stelle, also über Division der Ganzzahl durch 10.000. Ergo stehen grundsätzlich vier Nachkommastellen zur Verfügung, während bei Double und Single die Zahl der Nachkommastellen variabel ist und von der Größe des Betrags abhängt.

Decimal schließlich ähnelt im Ergebnis Currency, weil der angezeigt Wert sich durch Division mit einer Zehnerpotenz ergibt. Die Genauigkeit ist sogar noch höher, als bei Currency. Doch auch hier gilt das gleiche, wie bei Double und Single: Die Anzahl der Nachkommastellen ist variabel. Außerdem kann VBA mit diesem Datentyp schlecht umgehen. Eine Variable vom Typ Decimal lässt sich erst gar nicht deklarieren! Der Typ scheidet damit für Währungsrechnungen weitgehend aus.

Für eine empirische Studie wurde die Tabelle tblBetraege in der Beispieldatenbank angelegt, deren Entwurf sich aus Bild 1 ergibt. Sie simuliert eine Bestelltabelle, wo es zu jeder Position die Anzahl gibt, den eigentlichen Betrag und die Umsatzsteuer (Ust, Prozentzahl, Double). Der Betrag ist für unseren Versuch über drei Varianten abgebildet. BetragDbl ist ein Feld vom Typ Double, BetragCur ist ein Currency-Typ und BetragDez von Typ Decimal. Zur Kontrolle wurden noch drei Berechnete Felder eingefügt. SummeDbl ist dabei folgender Ausdruck hinterlegt:

Entwurf der Tabelle tblBetraege mit ihren drei Währungsfeldern, sowie darauf bezogenen berechneten Feldern

Bild 1: Entwurf der Tabelle tblBetraege mit ihren drei Währungsfeldern, sowie darauf bezogenen berechneten Feldern

[Anzahl] * [BetragDbl] * (1 + [Ust])

Ohne eine Abfrage bemühen zu müssen, wird damit die Positionssumme gleich im Datenblatt angezeigt. In produktiven Datenbanken sollten Sie von diesen Berechneten Feldern aber eher absehen, weil die Anzeige direkter Tabelleninhalte dort zu vermeiden ist. SummeCur und SummeDez berechnen nach der identischen Formel, beziehen sich aber jeweils auf die Felder BetragCur und BetragDez.

Um die Tabelle mit Daten zu füllen, gibt es die Prozedur GeneriereBetraege in der Datenbank. Sie legt 10.000 Datensätze an und schreibt nach Zufallsprinzip Zahlen in die drei Felder Anzahl, Betrag… und Ust. Beim Betrag wird über String-Verarbeitung darauf geachtet, dass nur exakt zwei Nachkommastellen generiert werden:

Dim dBetrag As Double
Dim sBetrag As String
dBetrag = 100 * Rnd
sBetrag = CStr(Val(dBetrag * 100) / 100)
rs!BetragDbl.Value = sBetrag

Die genaue Gestaltung der Routine interessiert hier weniger, als ihr Ergebnis, welches in Bild 2 dargestellt ist. Im Datenblatt wurde hier zusätzlich die Aggregatzeile eingeblendet. An die Aggregatzeile kommen Sie über diese Schritte:

Das ist die Datenblattansicht der Tabelle tblBetraege, unten mit der hinzugefügten Aggregatzeile für die Summen

Bild 2: Das ist die Datenblattansicht der Tabelle tblBetraege, unten mit der hinzugefügten Aggregatzeile für die Summen

  • öffnen Sie die Tabelle in der Datenblattansicht
  • Aktivieren Sie im Ribbon die Schaltfläche Start | Datensätze | Summen. Die Aggregatzeile erscheint unten in der Ansicht.
  • Gehen Sie in die Aggregatzelle einer Datenspalte und wählen Sie aus dem nun erscheinenden Kombinationsfeld die gewünschte Aggregatfunktion aus – hier jeweils Summe. Je nach Datentyp des Felds ist allerdings nur ein Teil der Aggregatfunktionen verfügbar.

Die Summen der drei Betragsspalten sind alle identisch. Das gilt auch für die Summen der berechneten Spalten, wobei hier SummeDbl drei Nachkommastellen zeigt, obwohl für die Formatierung des Felds dezidiert nur zwei Stellen im Entwurf festgelegt wurden. Aber die Formatierung der Aggregatzeile selbst lässt sich nun mal nicht beeinflussen.

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar