Avatar billede bergstein Nybegynder
21. februar 2010 - 16:16 Der er 7 kommentarer og
2 løsninger

Validering

Hej.

Jeg forsøger at indarbejde noget validering på en form med 3 indtastningsmuligheder og en OK og annuller knap.

Dertil har jeg lavet en funktion...

Function Validering: boolean;

... som jeg kalder fra OK-knappens onclick event med...

If Validering = true then

... hvorefter der sker et resultat.


Funktionen Validering ser nogenlunde sådan ud :

function Tform4.Validering: boolean;
begin
  Result := true;

  //Validering 1
  If strtoint(edit1.Text) <> VARIABEL then
  begin
    Result := false;
    showMessage('Fejlinformation til brugeren');
  end;

  // Validering 2
  If strToDate(edit2.Text) > now then
  begin
    Result := false;
    showMessage('Fejlinformation til brugeren');
  end;

// Validering 3 osv.
...
end;

Ovenstående fungerer efter hensigten, når der kun er 1 fejl i rækken af muligheder jeg validerer på.

Men er der 2+ fejl, så kommer der først en boks frem med første fejlbeskrivelse. Når der klikkes OK kommer næste boks frem osv.

Er der en smartere måde at validere inputtet på eller kan man lave noget ala try-finally-end, hvor man så snart den første fejl dukker op stopper funktionen og undlader at validere resten
Avatar billede preppydude Nybegynder
21. februar 2010 - 20:10 #1
Først, så skal du passe på EConvertError. Den gives hvis du laver fx StrToInt(Edit1.Text) og Edit1 ikke er en "rigtig" integer (hvis der fx er bogstaver osv.). Du kan undgå sådan en fejl ved at bruge endnu en funktion til at tjekke om det faktisk er en ordentlig integer, noget lignende:

function IsInteger(const AStr: String): Boolean;
begin
  Result := True;
  try
    StrToInt(AStr);
  except
    on E:EConvertError do
      Result := False;
  end;
end;

Derefter vil jeg råde dig til at lave en liste med samtlige fejl til brugeren, så han/hun kan få et overblik over hvad der er forkert uden at skulle klikke sig igennem over flere gange.

function TForm4.Validate: Boolean;
var
  ErrorMsg: String;
begin
  Result := False;
  ErrorMsg := '';
  try
    if (StrToInt(Edit1.Text)<>VARIABEL) then
      ErrorMsg := ErrorMsg + #13#10'- Edit1';

    if (StrToDate(Edit2.Text)>Now) then
      ErrorMsg := ErrorMsg + #13#10'- Edit2';
  finally
    Result := not (ErrorMsg<>'');
    if not (Result) then ShowMessage('Der blev fundet fejl i følgende:' + ErrorMsg);
  end;
end;
Avatar billede martinlind Nybegynder
22. februar 2010 - 00:38 #2
vil gerne diskret henlede publikums opmærksomhed på den meget oversete funktion VAL() den er hurtigere og fuldt brugbar frem for strtoint()

:-)
Avatar billede preppydude Nybegynder
22. februar 2010 - 02:03 #3
@martinlind:
Val() varierer ved forskellige compiler directives (tror jeg nok) og forskellige Delphi versioner (ved jeg, senest D2009). Udover det er det minimalt hvor meget hurtigere den er. :)

Her har du en simpel test:
Testing with 1,000,000 convertions (64-bit).
Val(): 280ms
StrToInt(): 283ms
Bye.

Testing with 1,000,000 convertions (32-bit).
Val(): 316ms
StrToInt(): 332ms
Bye.
Avatar billede hrc Mester
22. februar 2010 - 01:51 #4
Der er to (tre) metoder:
a. Enten validere mens der tastes.

Her kan valideres via TEdit.OnKeyPressed eller tvinge brugeren til at indtaste korrekt via TMaskedEdit (men den komponent er lidt dum)

b. Valideres når data "comittes".

c. Eller en kombination af begge.

Jeg plejer at bruge c'eren og validerer i forbindelse med at formen lukkes (m. ModalResult = mrOK). Dette gøres i OnCloseQuery og skrivning af data foretages i OnClose

I OnCloseQuery plejer jeg da at have en try-except a la dette:

uses
  DateUtils;

const
  ErrorMsg = 'Fejl i indtastning (%s)';
..
CanClose := true;
if ModalResult = mrOK then
  try
    if StrToIntDef(Edit1.Text,MaxInt) <> VARIABEL then
      raise Exception.CreateFmt(ErrorMsg1,['Edit1']);

    if StrToDateDef(Edit2.Text,0.0) > DateOf(Now) then // tester kun dato
      raise Exception.CreateFmt(ErrorMsg1,['Edit2']);
  except
    on e: exception do
    begin
      MessageDlg(e.Message,mtInformation,[mbOK],0);
      CanClose := false;
    end;
  end;

Lidt flere tips

1. Jeg plejer at bruge StrToIntDef og StrToDateDef (måske min egen metode, kan ikke huske om den kom med i D2009). De er handy mange gange da de ikke raiser en exception.
2. Man kan tvinge en TEdit til kun at acceptere heltal. Der er en property til det.
3. Skal der indtastes datoer kan TMaskedEdit være en løsning - eller endnu bedre en TDateTimePicker.
Avatar billede bergstein Nybegynder
23. februar 2010 - 20:08 #5
Hej.

Jeg har nu kigget på det og kombinerer Preppydude og hrc's forslag. Vil i lægge et svar.
Avatar billede bergstein Nybegynder
23. februar 2010 - 20:12 #6
Hvad er der i øvrigt, der sker i flg.


(%s)
(fra hrc's kodestump: ErrorMsg = 'Fejl i indtastning (%s))

og

#13#10
(fra Preppydudes kodestump: ErrorMsg := ErrorMsg + #13#10'- Edit1)';
Avatar billede hrc Mester
23. februar 2010 - 20:51 #7
Konstanten, med %s, bliver jo brugt når jeg raiser en exception. Dens constructor hedder CreateFmt der dækker over den kan det samme som format(), dvs. den erstatter %s med det der står i [].

Grunden til jeg laver teksten som konstant er den simple, at den bruges 2 steder.
Avatar billede hrc Mester
23. februar 2010 - 20:51 #8
... åh. Var det et svar du skrev?
Avatar billede bergstein Nybegynder
28. februar 2010 - 11:55 #9
Preppydude vil du venligst lægge et svar, så jeg kan få pointene fordelt til jer.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester