ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 16.10.2001

Diese Seite wurde zuletzt aktualisiert am 16.10.2001
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Brüche lesen

Zurück...


Anzeige

(-hg) mailto:hg_fractiontonum@aboutvb.de

Zur Umsetzung der Eingabe einer Zahl als Bruchschreibweise (zum Beispiel "3 1/8") in einen Dezimalbruch (3,125) ist zum einen der ganzzahlige Anteil der Eingabe und zum anderen der gebrochene Anteil zu isolieren und auszuwerten. Die Ergebnisse beider Teile ergeben addiert den gesuchten Dezimalwert.

Als Text eingegebene Bruchzahlen werden in Dezimalzahlen umgesetzt

Als Text eingegebene Bruchzahlen werden in Dezimalzahlen umgesetzt

Die Funktion FractionToNumDbl (bzw. FractionToNumSng und FractionToNumCur für Single- und Currency-Rückgabewerte) sind bezüglich der genauen Formatierung des zu übergebenden Ausdrucks relativ tolerant. Leerzeichen, vor allem vor und nach dem Teiler-Zeichen werden ignoriert. Bis auf eine Ausnahme: nachdem eventuell vorhandene Leerzeichen um das Teiler-Zeichen herum entfernt worden sind, wird der ganzzahlige Anteil vor dem ersten noch verbleibenden Leerzeichen erwartet. Ist dieser nicht vorhanden, wird der Ausdruck als Bruch ohne ganzzahligen Anteil interpretiert.

Schauen wir uns die Funktion FractionToNumDbl einmal näher an.

Public Const ftnErrInvalidParam = 30001

Public Function FractionToNumDbl(ByVal Value As String, _
 Optional ByVal NormalFraction As Boolean = True) As Double

  Dim nNumParts() As String
  Dim nFracParts() As String
  Dim nSgn As Long
  Dim nNum As Long
  Dim nNumerator As Long
  Dim nDenominator As Long
  Dim nFraction As Double

Zunächst putzen wir überflüssige Leerzeichen weg - vom Anfang und vom Ende und um das Teiler-Zeichen herum (in Visual Basic 5 gibt es die Replace-Funktion noch nicht - dieses Putzen wird daher in der VB5-Version des Moduls zu diesem Artikel in der gesonderten Hilfsfunktion zReplaceX erledigt, die Sie am Ende dieses Artikels finden).

  Value = Trim$(Value)
  Do While InStr(Value, " /")
    Value = Replace(Value, " /", "/")
  Loop
  Do While InStr(Value, "/ ")
    Value = Replace(Value, "/ ", "/")
  Loop
  On Error Resume Next

Dann teilen wir den Ausdruck am ersten noch innerhalb vorkommenden Leerzeichen in zwei Teile (die Split-Funktion gibt es auch erst ab VB 6 - für VB 5 finden Sie eine speziell für diesen Zweck angepasste Variante ebenfalls am Ende dieses Artikels).

  nNumParts = Split(Trim$(Value), " ")
  Select Case UBound(nNumParts)
    Case 0

Besteht das zurückgegebene Array nur aus einem Element, war gar kein Leerzeichen mehr enthalten. Der Ausdruck bestand somit vermutlich entweder nur aus einem ganzzahligen Anteil oder aus einem Bruch. Daher versuchen wir nun, den Ausdruck anhand des Teiler-Zeichens zu zerlegen.

      nFracParts = Split(nNumParts(0), "/")
      Select Case UBound(nFracParts)
        Case 0

Wenn auch diese Teilung nur ein Element liefert, haben wir es wohl mit einem ganzzahligen Ausdruck zu tun. Diesen wandeln wir mittels der Hilfsfunktion zCLngX in einen Long-Wert um. Das Innere dieser Funktion werden Sie später noch zu Gesicht bekommen - Sie werden dann erkennen, dass die VB-Funktion CLng nicht genügt hätte.

          FractionToNumDbl = zCLngX(nFracParts(0))

Konnte der Ausdruck nicht in einen Long-Wert umgewandelt werden, wird ein Fehler ausgelöst.

          If Err.Number Then
            Err.Raise Err.Number
          End If
        Case 1

Konnte der Ausdruck erfolgreich in zwei Teile zerlegt werden, wandeln wir beide Teile in Long-Werte um und führen die Bruch-Division aus. Das Vorzeichen des Dezimalbruchs ergibt sich automatisch aus den Vorzeichen von Zähler und Nenner des Bruchs.

          FractionToNumDbl = _
           zCLngX(nFracParts(0)) / zCLngX(nFracParts(1))

Sollte einer der beiden Teile nicht erfolgreich in einen Long-Wert umgewandelt werden können, oder ergab die Umwandlung des zweiten den Wert 0, wird auch hier wieder ein Fehler ausgelöst.

          If Err.Number Then
            Err.Raise Err.Number
          End If
        Case Else

Ergab die Teilung mehr als 2 Teile oder auch gar kein Teil, wird ein Fehler ausgelöst.

          Err.Raise ftnErrInvalidParam
      End Select
    Case 1

Ergab erste Teilung zwei Teile, haben wir es mit einem ganzzahligen Anteil und einem Bruch-Anteil zu tun. Letzeren teilen wir auch hier wieder am Teiler-Zeichen.

      nFracParts = Split(nNumParts(1), "/")
      Select Case UBound(nFracParts)

Hier ist es nun zwingend, dass der Bruch-Anteil aus zwei Elementen bestehen muss. Hinzu kommt, dass Vorzeichen beim Bruch-Anteil eines zusammengesetzten Ausdrucks keinen Sinn haben. Bei einem negativen Vorzeichen von Zähler (engl. "Numerator") und/oder Nenner (engl. "Denominator") wird daher wieder ein Laufzeitfehler ausgelöst.

        Case 1
          nNumerator = zCLngX(nFracParts(0))
          If Sgn(nNumerator) = -1 Then
            Err.Raise ftnErrInvalidParam
          Else
            nDenominator = zCLngX(nFracParts(1))
            If Sgn(nDenominator) = -1 Then
              Err.Raise ftnErrInvalidParam
            Else

Das Vorzeichen des ganzzahligen Anteils bestimmt das Vorzeichen des Dezimalbruchs. Es wird zunächst ermittelt und festgehalten.

              nNum = zCLngX(nNumParts(0))
              nSgn = Sgn(nNum)
              nFraction = nNumerator / nDenominator
              If Err.Number Then
                Err.Raise Err.Number
              ElseIf NormalFraction Then

Konnte die Bruch-Division erfolgreich ausgeführt werden (kein Überlauf oder keine Division durch 0), prüfen wir, ob das Ergebnis größer oder gleich 1 ist. Da dies bei einem zusammengesetzen Ausdruck ebenfalls keinen Sinn hätte, lösen wir auch hier wieder einen Laufzeitfehler aus.

                If nFraction >= 1 Then
                  Err.Raise Err.Number
                End If
              End If

Nun addieren wir den Absolutwert des ganzzahligen Ausdrucks und das zwangsläufig mit positivem Vorzeichen gegebene Ergebnis der Bruchdivision und multiplizieren die Summe mit dem zuvor ermittelten Vorzeichenwert des ganzzahligen Anteils. Das Ergebnis bildet den Rückgabewert der Funktion.

              FractionToNumDbl = (Abs(nNum) + nFraction) * nSgn
            End If
          End If
        Case Else

Hier wird ein Laufzeitfehler ausgelöst, wenn die Teilung des Bruch-Anteils mehr als zwei Teile ergeben sollte.

          Err.Raise ftnErrInvalidParam
      End Select
    Case Else

Falls die Teilung des Gesamtausdrucks anhand des Leerzeichens mehr als 2 Teile ergeben haben sollte, wird auch für diesen Fall ein Laufzeitfehler ausgelöst.

      Err.Raise ftnErrInvalidParam
  End Select
End Function

Die Aufgabe der Hilfsfunktion zCLngX ist, den übergebenen Ausdruck nur dann in einen Long-Wert zu konvertieren, wenn dieser auch eindeutig einem solchen entspricht. Die VB-Funktion CLng alleine würde auch eine Dezimalzahl gerundet konvertieren. Diese Hilfestellung können wir jedoch nicht brauchen - wir müssen feststellen können, ob der Ausdruck eindeutig schon einem Long-Wert entspricht. Dazu isolieren wir ein gegebenenfalls vorhandenes Vorzeichen und prüfen mittels eines kleinen Formatierungstricks, ob der Ausdruck unverändert bleibt. Nur wenn dies der Fall ist (anderenfalls wird ein Laufzeitfehler ausgelöst, der in der übergeordneten Funktion ausgewertet wird), haben wir einen brauchbaren Ausdruck übergeben. Erst dieser wird ganz banal mittels CLng endgültig in einen Long-Wert konvertiert und mit dem zuvor ermittelten Vorzeichenwert multipliziert.

Private Function zCLngX(ByVal Value As String) As Long
  Dim nSgn As Long
  
  Value = Trim$(Value)
  If Left$(Value, 1) = "-" Then
    Value = Mid$(Value, 2)
    nSgn = -1
  Else
    nSgn = 1
  End If
  Select Case True
    Case CLng(Value) = 0
      zCLngX = 0
    Case Value = Format$(Value, "#")
      zCLngX = CLng(Value) * nSgn
    Case Else
      Err.Raise ftnErrInvalidParam
  End Select
End Function

Die folgende Funktion zReplaceX für Visual Basic 5 beseitigt überflüssige Leerzeichen aus einem Zahl/Bruch-Ausdruck.

Private Sub zReplaceX(Value As String)
  Dim nPos As Long
  
  Value = Trim$(Value)
  Do
    nPos = InStr(Value, " /")
    If nPos Then
      Value = Left$(Value, nPos - 1) & Mid$(Value, nPos + 1)
    Else
      Exit Do
    End If
  Loop
  Do
    nPos = InStr(Value, "/ ")
    If nPos Then
      Value = Left$(Value, nPos) & Mid$(Value, nPos + 2)
    Else
      Exit Do
    End If
  Loop
End Sub

Der folgende für VB 5 benötigte Ersatz der ebenfalls erst seit VB 6 verfügbaren Split-Funktion ist kein vollwertiger Ersatz, sondern enthält nur eine speziell auf die hier benötigten Bedürfnisse angepasste Version. Sie gibt nur im Erfolgsfall ein Array mit einem oder mit zwei Element(en) zurück, anderenfalls ein Array mit 2 Elementen (was als Fehler gewertet wird).

Private Function zSplit(Str As String, Separator As String) _
 As Variant

  Dim nPos As Long
  Dim nParts() As String
  
  nPos = InStr(Str, Separator)
  If nPos Then
    If InStr(Mid$(Str, nPos + 1), Separator) Then
      ReDim nParts(0 To 2)
    Else
      ReDim nParts(0 To 1)
      nParts(0) = Left$(Str, nPos - 1)
      nParts(1) = Mid$(Str, nPos + 1)
    End If
  Else
    ReDim nParts(0)
    nParts(0) = Str
  End If
  zSplit = nParts
End Function

Beispiel-Projekte und Modul(e) modFractionToNum(5) (fractiontonum.zip - ca. 7,4 KB)


Artikel
Zum Download-Bereich dieses Artikel
Mail an den Autor dieses Artikels

KnowHow
Zur KnowHow-Übersicht

KnowHow-Themen
Themen - Allgemeines
Themen - Entwicklungsumgebung (VB-IDE)
Themen - Forms
Themen - Steuerelemente (Controls)
Themen - Grafik
Themen - Dateien
Themen - UserControls
Themen - Einsteiger-Tipps
Themen - Wussten Sie...?

Übersicht nach Titeln in alphabetischer Reihenfolge
Übersicht nach Erscheinungsdatum

Schnellsuche




Zum Seitenanfang

Copyright © 1999 - 2017 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Download Internet Explorer