Ich habe eine alte Funktion von mir (_FormatNumber) völlig überarbeitet und erweitert zur Nutzung mit Windows Language ID.
Was wichtig ist, steht im Skriptkopf ausführlich beschrieben.
EDIT 12.04.2022
Ich habe noch etwas erweitert. Ziel ist ja, ohne mit dem zweifelsohne mächtigen StringFormat, das leider eine nicht intuitiv zu erschließende Syntax hat (und dennoch nicht alle kann, was man sich wünscht), eine Formatierungsfunktion zu besitzen, die mit einfachen und verständlichen Formatierungsmasken zum gewünschten Ergebnis führt. Intern nutze ich zwar intensiv StringFormat aber für alle Funktionen geht das nicht. Z.B. kann in meiner Funktion statt Vor-Null auch jedes beliebige Zeichen zum Auffüllen verwendet werden (außer bei Hex-Zahlen, dort gibt es kein Auffüllen), das bietet StringFormat nicht. Zudem ist StringFormat bei Hex-Zahlen auf 32bit limitiert, da wird erbarmungslos auf Länge 8 eingekürzt.
Jetzt kann formatiert werden als: Integer / Float / Exponentialdarstellung / Hexadezimaldarstellung.
Zusätzlich kann mit anghängten Leerzeichen formatiert werden, das ermöglicht eine spaltengenaue Ausgabe unterschiedlicher Formate.
Bsp.
Bsp.
$a = 12, $b = 1.25, $c = 2480, $d = 0.75
$a1 = 125, $b1 = 7.89, $c1 = 3278, $d1 = 0.12
; Ausgabe soll untereinander an der Einerstelle ausgerichtet erfolgen, Füllzeichen soll ' ' sein.
; UND
; alle Ausgaben sollen gleich lang sein um die nächste Spalte sauber anzuhängen
; Die längste Zahl hat 4 Stellen VK, für NK brauche ich 2.
; Für die anzuhängenden Spaces bei den Ganzzahlen ist die Länge: NK+1 (Dezimaltrenner)
; So lässt sich übersichtlich in Tabbellenform ausgeben:
ConsoleWrite(_NumberFormat($a, 'N4s3', ' ') & ' | ' & _NumberFormat($a1, 'N4s3', ' ') & ' | ' & @CRLF)
ConsoleWrite(_NumberFormat($b, 'N4.2', ' ') & ' | ' & _NumberFormat($b1, 'N4.2', ' ') & ' | ' & @CRLF)
ConsoleWrite(_NumberFormat($c, 'N4s3', ' ') & ' | ' & _NumberFormat($c1, 'N4s3', ' ') & ' | ' & @CRLF)
ConsoleWrite(_NumberFormat($d, 'N4.2', ' ') & ' | ' & _NumberFormat($d1, 'N4.2', ' ') & ' | ' & @CRLF)
#cs
Ausgabe:
12 | 125 |
1,25 | 7,89 |
2480 | 3278 |
0,75 | 0,12 |
#ce
Alles anzeigen
Für die Angabe der Maske ergeben sich daraus folgende Möglichkeiten:
Eine Unterscheidung von Klein-/Großschreibung findet nur für Hex-Zahlen statt. Dort wird damit geregelt, ob Klein- oder Großbuchstaben in der Hex-Zahl Verwendung finden. Alle anderen Buchstaben können beliebig groß oder klein übergeben werden.
MASKE allgemein:
[Buchstabe] [opt. Zahl] [opt. Dezimalpunkt & Zahl] [opt. Folgespaces]
N3 | Zahl mit Mindestlänge 3, bei Bedarf wird mit (beliebigem) Füllzeichen aufgefüllt, Standard: '0' |
N3.2 | Zahl mit min. 3 VK-Stellen und max. 2 NK-Stellen (wenn zu kurz wird mit '0' gefüllt, bei zu lang wird gerundet |
N3s3 | Wie N3 und zusätzlich 3 Leerzeichen angehängt. Dadurch sind 'N3s3' und 'N3.2' exakt gleich lang |
N.2 | VK-Stellen, wie übergeben. NK-Stellen gefüllt/gerundet |
E | Exponentialschreibweise [-]1,234567E[+-]012 |
E3 | Die Längenangabe bezieht sich auf die VK-Stellen. Da ein Vorzeichen möglich ist, ist die kleinste Länge: 2. Als Standard wird mit Leerzeichen befüllt. |
H | Hexadezimalzahl in Schreibweise '123ABF', Länge 8 / 16 (wird an den Zahlenbereich angepasst) |
h | Hexadezimalzahl in Schreibweise '123abf', Länge 8 / 16 (wird an den Zahlenbereich angepasst) |
Hx / hx | wie vorab aber Ausgabe mit Präfix '0x' |
H8 / hx4 | '123ABCEF' / '0x12ab' - Zahlenangabe zum Definieren der Länge. Wenn kürzer als die Zahl, wird diese von links abgeschnitten |
Hx4S4 | '0x12AB ' - Anhängen von Leerzeichen |
;-- TIME_STAMP 2022-04-12 15:14:01 v 0.2
#cs
• Formatierung von Zahlenwerten mit/ohne Angabe Language Code. Ohne Angabe wird UserDefaultLanguage verwendet.
• Angelehnt an Formatierungsmasken, wie sie z.B. in Report Generatoren verwendet werden.
• Die Länge der verwendeten Gruppierungszeichen und evtl. Vorzeichen werden auf die Formatierungslänge angerechnet!
• Längenangaben sind im
Vorkommabereich : minimale Länge, bei Bedarf wird mit Füllzeichen (Standard '0') aufgefüllt
Nachkommabereich: maximale Länge, bei Bedarf wird mit '0' aufgefüllt oder auf Länge gerundet
• Bei Kommazahlen mit Ganzzahlmaske wird der Nachkommateil ohne Rundung abgeschnitten.
Beispiele (deutsches / englisches System: 0x0407 / 0x0009)
ZAHL MASKE FÜLLZEICHEN LCID GROUPING AUSGABE
------------------------------------------------------------------
1234.56 N6 '0' 0x0407 True 01.234
1234.56 N6 '0' 0x0407 False 001234
1234.56 N6.3 '0' 0x0407 True 01.234,560
1234.56 N6.3 '0' 0x0407 False 001234,560
34.56 N6.3 '#' 0x0407 False ##1234,560
1234.56 N6.1 '0' 0x0407 True 01.234,6
1234.56 N6.1 '0' 0x0407 False 001234,6
1234.56 N.3 '0' 0x0407 True 1.234,560
1234.56 N.3 '0' 0x0407 False 1234,560
1 N3 ' ' 0x0407 False 1
11 N3 ' ' 0x0407 False 11
100 N3 ' ' 0x0407 False 100
123 E ' ' 0x0407 False 1,230000E+002
123 E3 ' ' 0x0407 False 1,230000E+002
123 H ' ' 0x0407 False 0000007B
123 h ' ' 0x0407 False 0000007b
123 Hx ' ' 0x0407 False 0x0000007B
123 hx ' ' 0x0407 False 0x0000007b
123 H6 ' ' 0x0407 False 00007B
123 h6 ' ' 0x0407 False 00007b
123 Hx6 ' ' 0x0407 False 0x00007B
123 hx6 ' ' 0x0407 False 0x00007b
-1234.56 N6 '0' 0x0407 True -1.234
-1234.56 N6 '0' 0x0407 False -01234
-1234.56 N6.3 '0' 0x0407 True -1.235,560
-1234.56 N6.3 '0' 0x0407 False -01234,560
-1234.56 N.3 '0' 0x0407 True -1.234,560
-1234.56 N.3 '0' 0x0407 False -1234,560
-1 N3 ' ' 0x0407 False -1
-11 N3 ' ' 0x0407 False -11
-100 N3 ' ' 0x0407 False -100
------------------------------------------------------------------
1234.56 N6 '0' 0x0009 True 01,234
1234.56 N6 '0' 0x0009 False 001234
1234.56 N6.3 '0' 0x0009 True 01,234.560
1234.56 N6.3 '0' 0x0009 False 001234.560
1234.56 N6.1 '0' 0x0009 True 01,234.6
1234.56 N6.1 '0' 0x0009 False 001234.6
1234.56 N.3 '0' 0x0009 True 1,234.560
1234.56 N.3 '0' 0x0009 False 1234.560
1 N3 ' ' 0x0009 False 1
11 N3 ' ' 0x0009 False 11
100 N3 ' ' 0x0009 False 100
-1234.56 N6 '0' 0x0009 True -1,234
-1234.56 N6 '0' 0x0009 False -01234
-1234.56 N6.3 '0' 0x0009 True -1,235.560
-1234.56 N6.3 '0' 0x0009 False -01234.560
-1234.56 N.3 '0' 0x0009 True -1,234.560
-1234.56 N.3 '0' 0x0009 False -1234.560
-1 N3 ' ' 0x0009 False -1
-11 N3 ' ' 0x0009 False -11
-100 N3 ' ' 0x0009 False -100
#ce
; v 0.2 Fixed Grouping by one leading '0' ('0123' --> '.123')
; Added Scientific notation (Mask 'E'). Default length is 2 (possible sign & pre-decimal value)
; Added Hexadecimal notation (Mask 'H'/'h', 'Hx'/'hx').
; Added Right side addition of spaces by adding 'sn' ('s3', 's6'..) to the mask.
; Facilitates the alignment of integers and floating point numbers in a column.
; #FUNCTION# =======================================================================================
; Name ..........: NumberFormat
; Description ...: Formatierung von Zahlenwerten (mit und ohne Vorzeichen, Integer od. Float)
; Parameter(s)...: $_vString der zu formatierende Zahlenwert
; ...............: $_sMask Maske zum Bestimmen des Ausgabestrings, Bsp.:
; Für 'N'/'E'/'S' kann ebenso 'n'/'e'/'s' verwendet werden, nur bei 'H'/'h' ist Groß-/Kleinschreibung zu beachten.
; N3 Ganzzahl min. 3 Stellen, Auffüllen mit $_sFill. Wenn Float übergeben, keine Rundung
; N3.2 Float min. 3 Vorkommastellen (Auffüllen mit $_sFill), 2 Nachkommastellen (Ergänzen mit Nullen)
; N3S3 Ganzzahl min. 3 Stellen, Auffüllen mit $_sFill. Anhängen von 3 Leerzeichen (s3). Dadurch die Ganzzahl mit einer 'N3.2' in einer Spalte
; N.3 Float, Vorkommastellen wie übergeben, 3 Nachkommastellen (Ergänzen mit Nullen bzw. Runden auf Anzahl NK)
; E Exponentialschreibweise: [-]1,234567E[+-]012
; E3 Anzahl der Zeichen vor dem Komma (inkl. Vorzeichen). Minimum ist 2, auffüllen als Standard mit Leerzeichen.
; '0' kann hier nicht als Füllzeichen verwendet werden, aber jedes andere übergebenee Zeichen.
; H Hexadezimalzahl in Schreibweise '123ABF', Länge 8 / 16 (wird an den Zahlenbereich angepasst)
; h Hexadezimalzahl in Schreibweise '123abf', Länge 8 / 16 (wird an den Zahlenbereich angepasst)
; Hx/hx wie vorab aber Ausgabe mit Präfix '0x'
; H8/hx4 '123ABCEF' / '0x12ab' - Zahlenangabe zum Definieren der Länge. Wenn kürzer als die Zahl, wird diese von links abgeschnitten
; Hx4S4 '0x12AB ' - Anhängen von Leerzeichen
; ....[optional].: $_sFill Auffüllzeichen (Default: '0')
; ....[optional].: $_LCID Windows Language Code Identifier (Default: ''=UserDefaultLCID), 'Null'=LocaleInfo wird nicht verwendet
; ...............: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/70feba9f-294e-491e-b6eb-56532684c37f
; ...............: Wird eine LCID übergebn, die im Release des Rechners nicht verfügbar ist, wird stattdessen "UserLocale" verwendet.
; ....[optional].: $_bGrouping Gruppieren der Ausgabe (Default: False) - LCID muss dann <> Null sein!
; Return values .: Success Der formatierte Zahlenwert
; ...............: Failure Originalstring (Ungültige Maske)
; Author ........: BugFix
; Remarks .......: Bei negativen Zahlenwerten wird das Vorzeichen mit zur Anzahl der Vorkomma/Stellen eingerechnet
; ==================================================================================================
Func _NumberFormat($_vString, $_sMask, $_sFill='0', $_LCID='', $_bGrouping=False)
Local $g, $f, $l, $p, $aM, $sFill = '', $sResult, $sSign = '', $sAdd = ''
Local $nN = StringRegExp($_sMask, '^[NEneHh](\d*)', 1)[0]
If $_sFill <> '0' And $nN <> '' Then
$p = StringInStr($_vString, '.')
$l = $p = 0 ? StringLen($_vString) : $p -1
Local $nF = $nN -$l
If $nF > 0 Then
For $i = 1 To $nF
$sFill &= $_sFill
Next
EndIf
EndIf
Local $aAdd = StringRegExp($_sMask, '[sS](\d+)', 1)
If Not @error Then
For $i = 1 To $aAdd[0]
$sAdd &= ' '
Next
EndIf
Switch StringLeft($_sMask, 1)
Case 'N'
If StringInStr($_sMask, '.') Then
$aM = StringRegExp($_sMask, '(\d+)(\.\d+)', 3) ; [VK, .NK]
If @error Then Return _NumberFormat($_vString, StringReplace($_sMask, 'N', 'N1') , $_sFill, $_LCID, $_bGrouping)
$g = Int($_vString)
$f = Abs($_vString) - Abs($g)
$f = StringFormat(StringFormat('%%%s%sf', $aM[1]), $f)
$g = $g + Floor($f)
If $_sFill = '0' Then
$g = StringFormat(StringFormat('%%%s%dd', $_sFill, $aM[0]), $g)
$sResult = StringFormat('%s.%s', $g, StringRegExp($f, '\.(\d+)', 1)[0])
Else
$sResult = StringFormat('%s%s.%s', $sFill, $g, StringRegExp($f, '\.(\d+)', 1)[0])
EndIf
Else
Local $nN = StringRegExp($_sMask, '^[Nn](\d+)', 1)[0]
If $_sFill = '0' Then
$sResult = StringFormat(StringFormat('%%%s%dd', $_sFill, $nN), $_vString)
Else
$sResult = StringFormat('%s%s', $sFill, $_vString)
EndIf
EndIf
Case 'E'
$l = 2 ; VK-Länge definiert ? - Auffüllen mit $sFill. Minimum: 2 (evtl. Vorzeichen & VK)
If StringLen($_sMask) > 1 Then $l = StringRegExp($_sMask, '[Ee](\d+)', 1)[0]
If $l < 2 Then $l = 2
$sResult = StringFormat(StringFormat('%%%ds', 12+$l), StringFormat('%E', $_vString))
If $sFill <> '' Then $sResult = StringRegExpReplace($sResult, '^\s+', $sFill)
Case 'H'
Local $aMask = StringRegExp($_sMask, '([hH])([xX]*)(\d*)', 3)
If $aMask[0] == 'H' Then
Select
Case $aMask[1] = '' And $aMask[2] = ''
$sResult = StringUpper(Hex($_vString))
Case $aMask[1] = 'x' And $aMask[2] = ''
$sResult = '0x' & StringUpper(Hex($_vString))
Case $aMask[1] = '' And $aMask[2] <> ''
$sResult = StringUpper(Hex($_vString, $aMask[2]))
Case $aMask[1] = 'x' And $aMask[2] <> ''
$sResult = '0x' & StringUpper(Hex($_vString, $aMask[2]))
EndSelect
Else
Select
Case $aMask[1] = '' And $aMask[2] = ''
$sResult = StringLower(Hex($_vString))
Case $aMask[1] = 'x' And $aMask[2] = ''
$sResult = '0x' & StringLower(Hex($_vString))
Case $aMask[1] = '' And $aMask[2] <> ''
$sResult = StringLower(Hex($_vString, $aMask[2]))
Case $aMask[1] = 'x' And $aMask[2] <> ''
$sResult = '0x' & StringLower(Hex($_vString, $aMask[2]))
EndSelect
EndIf
Case Else
$sResult = $_vString
EndSwitch
If $_LCID <> Null Then
Local $sDec = __GetLocaleInfo(0xE, $_LCID, True)
If @error Then ; use UserLocale
$_LCID = ''
$sDec = __GetLocaleInfo(0xE, $_LCID)
EndIf
$sResult = StringReplace($sResult, '.', $sDec)
If StringLeft($_sMask, 1) = 'E' Then Return $sResult & $sAdd
If $_bGrouping Then
Local $sThousand = __GetLocaleInfo(0xF, $_LCID, True)
Local $iGrouping = StringRegExp(__GetLocaleInfo(0x10, $_LCID, True), '(\d+)', 1)[0]
Local $aR = StringRegExp($sResult, '([^\' & $sDec & ']+)(.*)', 3), $sTmp = '', $iTrim = 0
While StringRegExp($aR[0], '(\d{' & $iGrouping +1 & '})$')
If StringTrimRight($aR[0], $iGrouping) = '0' Then ExitLoop
$sTmp = $sThousand & StringRight($aR[0], $iGrouping) & $sTmp
$aR[0] = StringTrimRight($aR[0], $iGrouping)
$iTrim += 1
WEnd
$sResult = $aR[0] & $sTmp
If UBound($aR) > 1 Then $sResult &= $aR[1]
If $iTrim > 0 Then
If StringLeft($sResult, 1) = '-' Then
$sSign = '-'
$sResult = StringTrimLeft($sResult, 1)
EndIf
EndIf
While $iTrim > 0
If StringLeft($sResult, 1) = '0' Then
$sResult = StringTrimLeft($sResult, 1)
$iTrim -= 1
Else
ExitLoop
EndIf
WEnd
$sResult = $sSign & $sResult
EndIf
EndIf
Return $sResult & $sAdd
EndFunc ;==>_NumberFormat
; #FUNCTION# =======================================================================================
; Name ..........: _GetLocaleInfo
; Description ...: Retrieves information about a locale specified by identifier.
; Parameter(s)...: $_LCType https://docs.microsoft.com/en-us/windows/win32/intl/locale-information-constants
; ....[optional].: $_LCID Windows Language Code Identifier (Default: '' = GetUserDefaultLCID)
; ....[optional].: $_bErrEmptyRes Treat empty result as error (Default: False)
; Return values .: Success Value for LCType and LCID
; ...............: Failure empty string, @error = 1 (only if $_bErrEmptyRes=True)
; Author ........: BugFix
; ==================================================================================================
Func __GetLocaleInfo($_LCType, $_LCID='', $_bErrEmptyRes=True)
Local $ret, $sBuffer, $iLen, $iErr
Local $hDll = DllOpen("kernel32.dll")
If $_LCID = '' Then $_LCID = DllCall($hDll, 'long', 'GetUserDefaultLCID')[0]
$ret = DllCall($hDll, 'long', 'GetLocaleInfo', 'long', $_LCID, 'long', $_LCType, 'str', $sBuffer, 'long', 0)
$iLen = $ret[0]
$ret = DllCall($hDll, 'long', 'GetLocaleInfo', 'long', $_LCID, 'long', $_LCType, 'str', $sBuffer, 'long', $iLen)
DllClose($hDll)
$iErr = ($_bErrEmptyRes = True And $ret[3] = '') ? 1 : 0
Return SetError($iErr, 0, $ret[3])
EndFunc ;==>__GetLocaleInfo
Alles anzeigen
DL bisher: 9