Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 2/2004.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Access-FAQ: Rund um Access

Karl Donaubauer, Wien

In der Access-FAQ von Karl Donaubauer (www.donkarl.com) finden Sie die meistgestellten Fragen und Antworten zum Thema Microsoft Access. In dieser Beitragsreihe stellt Karl Donaubauer die wichtigsten Einträge im Detail vor und zeigt Ihnen entsprechende Lösungen anhand praxisnaher Beispiele. Im dritten Teil lernen Sie die Lösungen zu den meistgenannten Problemen der Teilnehmer der deutschsprachigen Access-Newsgroups bei der Behandlung von Zahlen und Zeiten kennen.

Kaufmännisch Runden

Obwohl Access-Anwendungen sicher überwiegend zum Organisieren von Zahlen und besonders Geldwerten eingesetzt werden, ist Access - ganz im Gegensatz zu Excel - erstaunlich schlecht mit den dafür nötigen Rundungsfunktionen ausgerüstet. Genau gesagt gibt es nur eine einzige eingebaute Rundungsfunktion und die ist leider für die Praxis untauglich.

Die häufigste Rundungsproblematik ist das korrekte kaufmännische Runden, also gleich bleibender Wert der zu rundenden Stelle, wenn eine Zahl zwischen 0 und 4 folgt, und Aufrundung der zu rundenden Stelle, wenn eine Zahl zwischen 5 und 9 folgt. In der Praxis geht es meistens darum, einen Geldbetrag auf zwei Kommastellen genau kaufmännisch zu runden.

Die meisten Fehler passieren, weil dafür ungeeignete Zahlentypen, Funktionen oder Ad-hoc-Formeln verwendet werden. Die tiefere Ursache sind meist Ungenauigkeiten durch die interne Fließkommabehandlung von Dezimalzahlen. Zahlen vom Typ Währung, den man für Geldwerte immer verwenden sollte, sind gegen diese Ungenauigkeiten etwas resistenter als zum Beispiel solche vom Typ Double. Access gibt allerdings bei Berechnungen in Abfragen, Formularen, Berichten - auch bei Zahlen vom Typ Währung - wiederum Double-Werte zurück.

Deshalb sollte eine zuverlässige Rundungsfunktion mit Double-Werten umgehen können.

Hinweis

Auf der Begleit-CD finden Sie eine Beispiel-Datenbank für Access 97 (FAQ97.mdb) und Access 2000 und höher (FAQ00.mdb) mit den Quellcodes und Beispielen aus diesem Artikel. (

Int() und Fix()

Bei einfacher Verwendung dieser beiden Funktionen nach dem Muster

Int(Zahl * 100 + 0,5)/100

stimmen zwar viele Ergebnisse, aber nicht alle. Beispiele:

Int(5,025 * 100 + 0,5)/100

ergibt das erwartete Ergebnis 5,03.

Int(1,025 * 100 + 0,5)/100

ergibt bei Double-Werten 1,02 und bei Währungswerten korrekt 1,03.

Bei einer negativen Währungszahl scheitert die Berechnung wieder:

Int(-1,025 * 100 + 0,5)/100

ergibt nicht korrekt -1,02.

CLng() und CInt()

Diese beiden Funktionen runden nicht kaufmännisch, sondern bei einer fünf hinter der Stelle, auf die gerundet werden soll, auf die nächste gerade Zahl.

CLng(0.5) ergibt beispielsweise 0, während CLng(1.5) als Ergebnis den Wert 2 ausgibt. Darauf wird zwar in der Online-Hilfe zu diesen Funktionen hingewiesen, wird aber oft übersehen.

Round()

Diese ab Access 2000 in VBA eingebaute (einzige) Rundungsfunktion rundet nach dem gleichen Prinzip wie CDbl und CInt, also bei einer fünf hinter der Stelle, auf die gerundet werden soll, auf die nächste gerade Zahl.

Zum Beispiel ergibt Round(1,085; 2) korrekterweise den Wert 1,08, weil 8 die nächste gerade Zahl ist.

Microsoft bezeichnet diese Art der Rundung als "Banker's Rounding". Leider ist sie für alle mir bekannten Anwendungen unbrauchbar und der Grund für ihren Einbau seit jeher rätselhaft.

Hinzu kommt, dass Round() fehlerhaft arbeitet, wenn man voraussetzt, dass es mit Double-Werten zurechtkommen sollte:

So ergibt zum Beispiel Round(1,035;2) den Wert 1,03 statt des korrekten Wertes 1,04.

Resumée: Finger weg von dieser Funktion!

Weitere Informationen zu Round() und zur Rundung nach Microsoft-Vorstellungen finden Sie in den Knowledgebase-Artikeln 225330 und 196652.

Format

Die Funktion Format() ist differenzierter zu sehen. In Access 97 hat sie ähnliche Probleme mit Fließkommawerten wie Int() und Fix(), wenn man sie etwa in dieser Weise einsetzt:

Format(Zahl;"#,##")

Interessant ist, dass diese Probleme offenbar ab Access 2000 behoben wurden. In den neueren Access-Versionen sind mir bisher noch keine Fehler bei der kaufmännischen Rundung mit der Format-Funktion begegnet.

Die Formulierung ist deshalb so vorsichtig, weil Format() weder als Rundungsfunktion definiert ist, noch die Änderungen nach Access 97 dokumentiert sind.

Microsoft hat Access also nie eine definierte und funktionierende Methode zur kaufmännischen Rundung spendiert. Deshalb kursieren unzählige Varianten von benutzerdefinierten Funktionen. Viele davon runden falsch, weil sie sich auf die oben angeführten unzureichenden Methoden stützen.

Wenn Sie bereits eine benutzerdefinierte Funktion zum kaufmännischen Runden verwenden, dann testen Sie diese mit den hier verwendeten und oft problematischen Zahlen (insbesondere 1.025, -1.025). Sollten sie diese Tests nicht bestehen, bietet Quellcode 1 eine Rundungsfunktion, die seit Jahren vielfach erprobt ist.

Wenn Sie diese Funktion in einem Standardmodul speichern, kann sie in der ganzen Datenbank zur kaufmännischen Rundung verwendet werden. Dem Argument varNr wird die zu rundende Zahl übergeben, dem Argument varPl die Anzahl der Dezimalstellen. Dieses zweite Argument ist optional und bereits mit dem Standardwert 2 versehen. Wird beim Aufruf der Funktion das Argument nicht übergeben, rundet die Funktion automatisch auf zwei Dezimalstellen. Der folgende Aufruf ergibt daher den kaufmännisch gerundeten Wert 1.03:

fctRound(1.025)

Function fctRound(Optional varNr, Optional varPl As Integer = 2) As Double

    If IsMissing(varNr) Or Not IsNumeric(varNr) Then Exit Function

    fctRound = Fix("" & varNr * (10 ^ varPl) + Sgn(varNr) * 0.5) / (10 ^ varPl)

End Function

Quellcode 1

Public Function fctExcelRound(argNumer, Optional argPlaces = 2)

    fctExcelRound = Excel.Application.Round(argNumer, argPlaces)

End Function

Quellcode 2

Abb. 1: Rundungsvarianten in der Beispiel-mdb

Andere Beispiele für Aufruf und Ergebnis:

fctRound(1.25, 1) ergibt 1.3,

fctRound(1250, -2) ergibt 1300.

Abb. 1 zeigt gut und schlecht funktionierende Rundungsvarianten im Formular frmKaufRunden der Beispieldatenbank.

Access bietet indirekt noch eine andere Möglichkeit zur kaufmännischen Rundung, indem man Excel als Rundungstool einsetzt. Das Vorgehen ist recht einfach. Öffnen Sie ein beliebiges VBA-Modul, wählen Sie den Menüpunkt Extras ( Verweise, setzen Sie einen Verweis auf die Excel-Objektbibliothek. In Office XP heißt die Bibliothek zum Beispiel Microsoft Excel 10.0 Object Library (s. Abb. 2).

Ab sofort stehen in der Datenbank sämtliche Rundungsfunktionen von Excel zur Verfügung. Excel besitzt für die kaufmännische Rundung die Tabellenfunktion Round().

Diese ist nicht identisch mit der oben erwähnten, gleichnamigen VBA-Funktion, sondern rundet zuverlässig kaufmännisch.

Am besten kapselt man die Excel-Tabellenfunktion mit einer eigenen Funktion in einem Standardmodul (Quellcode 2).

Aufruf und Handhabung erfolgen analog zu der oben angeführten benutzerdefinierten Funktion. Als Beispiel ein Steuerelementinhalt:

=fctExcelRound(1,025;2)

Voraussetzung für die Nutzung der Excel-Bibliothek ist natürlich, dass Excel auf dem Zielsystem vorhanden ist.

Zahl in Worten

Abb. 2: Verweis auf die Objektbibliothek von Excel

Für das Drucken von Zahlscheinen, Schecks und so weiter ist es notwendig, den Geldbetrag als geschriebenes Wort anzugeben. Beispiel: 4321 wird zu viertausenddreihunderteinundzwanzig. Quellcode 3 und Quellcode 4 enthalten zwei Funktionen, die zusammen diese Arbeit erledigen. Kopieren Sie den Code in ein Standardmodul. Der Aufruf ist schlicht:

FctZahl_In_Worten(4321)

Daten und Uhrzeiten in Access

Für den richtigen Umgang mit Datum und Uhrzeit in Access muss man wissen, wie Access diese Art von Daten intern handhabt.

Der Felddatentyp Datum/Uhrzeit funktioniert im Bereich 1.1.100 bis 31.12.9999. In einem Feld dieses Typs befinden sich immer Datum und Uhrzeit, auch wenn durch die Formatierung des Feldes nur einer dieser Teile zu sehen sein sollte. Intern speichert Access Datum/Uhrzeit als Kommazahl. Das Datum steht vor dem Komma, die Uhrzeit nach dem Komma. Der Zeitpunkt 0, ab dem gezählt wird, ist in Access der 30.12.1899 00:00 (in Excel ist es der 1.1.1900). Der Tag 1 ist der 31.12.1899, Tag 2 der 1.1.1900 und so weiter. Ältere Datumswerte werden als negative Zahl gespeichert (-1 bedeutet zum Beispiel 29.12.1899 00:00).

Die Uhrzeit wird in Form des Bruchteils eines Tages nach dem Komma gespeichert. 0,5 ist daher der 30.12.1899 12:00. Mithilfe der Umwandlungsfunktionen CDbl() und CDate kann man von Datum auf Zahl und von Zahl auf Datum umrechnen. Ein Beispiel aus dem Testfenster des VBA-Editors:

? CDbl(#1/1/2004 18:00#)

37987,75

Die Zahl vor dem Komma zeigt, dass der 1.1.2004 der 37987. Tag seit dem 30.12.1899 ist. Die Zahl nach dem Komma zeigt, dass 18:00 Uhr drei Viertel beziehungsweise 75% eines Tages sind. Das funktioniert auch umgekehrt:

?CDate(37987.75)

01.01.2004 18:00:00

Diese Art der Speicherung ermöglicht für positive Zahlen, also den Bereich seit dem 30.12.1899, das arithmetische Rechnen mit Datum und Uhrzeit.

Man kann zum Beispiel mit dem Ausdruck Datum() + 1,5 eineinhalb Tage zum aktuellen Systemdatum addieren. Natürlich kann man für solche Berechnungen auch Datumsfunktionen wie DateAdd und DateDiff verwenden.

Im negativen Zahlenbereich vor dem 30.12.1899 ist hingegen keine simple Arithmetik möglich -1,5 bedeutet nicht eineinhalb Tage vor dem 30.12.1899, sondern 29.12.1899 12:00:00. Historiker, die mit der Schlachtdauer von Waterloo Berechnungen anstellen, sollten daher unbedingt die Datumsfunktionen wie DateAdd und DateDiff verwenden.

Public Function fctZahlInWorten(Zahl As Double)

    Dim Z As String, W As String

    Dim R As Integer, i As Integer

    Z = Int(Zahl)

    If Z = 0 Then fctZahlInWorten = "null": Exit Function

    For i = 6 To 0 Step -3

      If Len(Z) > i Then

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

© 2003-2015 André Minhorst Alle Rechte vorbehalten.