Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Prüfung auf Geld-format


michaelarban - Fr 30.07.10 17:47
Titel: Prüfung auf Geld-format
hallo,

wie kann ich in Delphi am besten prüfen, ob ein String eine Zahl im "Geld-Format" enthält,

z.B.:

Delphi-Quelltext
1:
2:
3:
4:
5:
myBetrag := '1.234.567';
myBetrag := '1.234.567,89';
myBetrag := '1234567';
myBetrag := '1234567,08';
myBetrag := '10.234.567';

aber nicht so was:

Delphi-Quelltext
1:
2:
3:
myBetrag := '1.2.34.567';
myBetrag := '1.23,4.567';
myBetrag := '1.234.567,897';

kennt ihr solche Delphi-Funktionen oder entsprechende Reguläre Ausdrücke?

danke

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


jaenicke - Fr 30.07.10 19:52


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function IsMyCurrencyFormat(const Value: string): Boolean;
var
  Temp: Double;
  SepPos: Integer;
begin
  Result := TryStrToFloat(Value, Temp);
  if Result then
  begin
    SepPos := Pos(DecimalSeparator, Value);
    Result := (SepPos = 0or (SepPos = Length(Value) - 2);
  end;
end;
Ungetestet, aber so müsste es passen.
// EDIT: klar, Boolean :D


Stundenplan - Fr 30.07.10 20:43

Muss der Rückgabewert nicht Boolean sein? :gruebel:


HotCoffee - Fr 30.07.10 21:34

Hallo,
also ich würde das wie folgt lösen.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
function  isCurrency  (pCheck : String) : Boolean;
VAR i,a         : integer;
begin
  result:=TRUE;
  a:=0;
  FOR i:=length(pCheck) DOWNTO 1 do
  begin
    a:=a+1;
    IF ((pCheck[i]='.'AND (a=4)) OR ((pCheck[i]=','AND (a<=3)) 
    THEN a:=0 
    ELSE 
      IF (pCheck[i]='.'OR (pCheck[i]=','
      THEN result:=FALSE
  end;
  pCheck:=stringreplace(pCheck,'.','',[RFREPLACEALL]);
  try
   IF (strtofloat(pCheck)*100-trunc(strtofloat(pCheck)*100)=0THEN;
  except 
    result:=FALSE
  end;
end;


jaenicke - Sa 31.07.10 09:24

Also erstens akzeptiert der Code auch "4,", also nur das Komma ohne Nachkommastellen. Zweitens hast du leider den DecimalSeparator nicht berücksichtigt, was wenn das Windows englisch eingestellt ist?

Ja, und dann:
user profile iconHotCoffee hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
  try
   IF (strtofloat(pCheck)*100-trunc(strtofloat(pCheck)*100)=0THEN;
  except 
    result:=FALSE
  end;
Autsch, schau dir mal an wie es richtig geht (wie bei mir mit TryStrToFloat (oder auch TryStrToCurr gibts)...).

Jetzt habe ich meine Variante getestet, aber leider ignoriert TryStrToFloat den ThousandSeparator. Alles ist korrekt gesetzt, es sagt aber, dass es keine gültige Zahl sei... :autsch:
Von den Nachkommastellen her passt es. Also geht wohl wirklich nur stellenweise alles analysieren.


HotCoffee - Sa 31.07.10 12:40

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:

Autsch

Okay :D du hast Recht, ich habs mir nochmal angeschaut und festgestellt, dass ich Try doof finde. Daher habe ich mal etwas anderes gebastelt. Diese Funktion überprüft, ob es sich um eine Währung handelt, egal ob sie Deutsch oder Englisch angegeben ist. Sie wird aufgerufen durch IsCurrency( ZuUeberpruefendeZahl,' ',0);.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
function IsCurrency(Str : String; Sep  : Char; Co : Integer) : Boolean;
VAR l : Char;
begin
 l:=Str[length(Str)];
 delete(Str,length(Str),1);
 IF length(Str)>0
 THEN
   IF l in ['0'..'9']
   THEN result:=IsCurrency(Str,Sep,Co+1)
   ELSE
      IF l in [',','.']
      THEN IF (0<Co) AND (CO<3AND (Sep=' ')
           THEN result:=IsCurrency(Str,l,0)
           ELSE
            IF (Co=3AND (Sep<>l)
            THEN result:=IsCurrency(Str,Sep,0)
            ELSE result:=FALSE
      ELSE result:=FALSE
 ELSE result:=TRUE;
end;

Wenn es nur auf deutsche Währung reagieren soll, dann einfach in Zeile 12 ein  And (l=',') und ergänzen, sowie in Zeile 15 (Sep='.') ändern.
Ich weiss, umständlich, dafür funktioniert es :D


Jakob_Ullmann - Sa 31.07.10 13:34

@jaenicke: Das lässt sich ja leicht korrigieren.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function ThousandsSetCorrect(value: string): Boolean;
var
  i: Byte;
begin
  Result := value[1] <> ThousandSeparator;
  if Result and (Pos(DecimalSeparator) > 3then
    for i := 1 to Pos(DecimalSeparator) - 1 do
      if value[i] = ThousandSeparator then
        Result := Result and
          (Pos(DecimalSeparator) > i) and
          (0 = (Pos(DecimalSeparator) - i) mod 3);
end;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function cIsMyCurrencyFormat(value: string): Boolean;
begin
  Result :=
    IsMyCurrencyFormat(StringReplace(value, ThousandSeparator, '', [rfReplaceAll])) and
    IsThousandsSetCorrect(value);
end;


ist aber ebenfalls ungetestet.


jaenicke - Sa 31.07.10 17:42

Ok, nach dem ganzen Pos usw. poste ich dann doch noch ne Variante, die das alles direkt macht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
function IsCurrencyString(const AValue: string; ADecimalSeparator,
  AThousandSeparator: Char): Boolean; overload;
var
  i, DecCounter: Integer;
  ThousandSep: Boolean;
begin
  DecCounter := 0;
  Result := True;
  ThousandSep := False;
  for i := Length(AValue) downto 1 do
    if AValue[i] in ['0'..'9'then
      if ThousandSep and (DecCounter > 2then
        Result := False
      else
        Inc(DecCounter)
    else if AValue[i] = ADecimalSeparator then
      if (i = 1or (i <> Length(AValue) - 2then
        Result := False
      else
        DecCounter := 0
    else if AValue[i] = AThousandSeparator then
    begin
      ThousandSep := True;
      if (i = 1or (DecCounter <> 3then
        Result := False
      else
        DecCounter := 0
    end
    else
      Result := False;
end;

function IsCurrencyString(const AValue: string): Boolean; overload;
begin
  Result := IsCurrencyString(AValue, DecimalSeparator, ThousandSeparator);
end;
Entweder man übergibt explizite Zeichen für die Trennzeichen oder es werden die des Systems benutzt. Funktioniert in einem Durchlauf durch die Buchstaben und braucht keine Umwandlung oder Pos oder so. ;-)

Beispielaufruf:

Delphi-Quelltext
1:
  ShowMessage(BoolToStr(IsCurrencyString('1.222.333,55'), True));