1. Technology

How to Auto Complete Date Value Input

By

Date Input Auto Complete

Components like TDateTimePicker and similar that are designed specifically for entering dates or times are useful when we want some visual representation of a date. However, why bother with visual components that are 'not-so-input-friendly when everything we want is just one Edit box to type the date into.

In this article you will find one great function designed to make date processing a bit faster.

Date Manipulation

The following DateComplete function is used to auto complete the given string value to a date representation.

The whole idea is to allow our users to only start typing the date and to finish it from code when appropriate (in most cases in the OnExit event of some edit-enabled control.)

For example, if the default Windows short date format is 'dd.mm.yyyy' then assigning '29' to the StrLikeDate variable will, after calling the DateComplete procedure, result in '29.01.2006'. Of course, this is all true if the current month and year are January, 2006.

 procedure DateComplete(var StrLikeDate : string; const NowIfError:boolean = True) ;
 var
    DateStr : string;
    Year, Month, Day : Word;
    cnt, SepCount : Integer;
 begin
    DateStr:=StrLikeDate;
 
    if DateStr = '' then Exit;
    SepCount := 0;
 
    for cnt := 1 to Length(DateStr) do
    begin
     if not (DateStr[cnt] in ['0'..'9']) then
     begin
      DateStr[cnt] := DateSeparator;
      inc(SepCount) ;
     end;
    end;
 
    while (DateStr <> '') and (DateStr[Length(DateStr)]=DateSeparator) do
    begin
     Delete(DateStr, Length(DateStr), 1) ;
     Dec(SepCount) ;
    end;
 
    DecodeDate(Now, Year, Month, Day) ;
 
    if SepCount = 0 then
    begin
     case Length(DateStr) of
     0 : DateStr := DateToStr(Now) ;
     1, 2 : DateStr := DateStr+DateSeparator+IntToStr(Month) ;
     4 : Insert(DateSeparator, DateStr, 3) ;
     6, 8 : begin
             Insert(DateSeparator, DateStr, 5) ;
             Insert(DateSeparator, DateStr, 3) ;
            end;
      end; {case}
     end; {if SepCount}
 
     try
      StrLikeDate := DateToStr(StrToDate(DateStr)) ;
     except
      if NowIfError = true then
       StrLikeDate := DateToStr(Date)
      else
       StrLikeDate := '';
     end;
 end; 

The DateComplete Procedure

As we can see from the procedure header:
 procedure DateComplete(var StrLikeDate : string; const NowIfError:boolean = True) ; 
The DateComplete takes the StrLikeDate string parameter by reference using the var keyword, meaning that DateComplete function is able to alter the value in StrLikeDate. The second parameter (optional, defaults to True) NowIfError is used in the exception handler part to check for bad date (for example: letters in StrLikeDate). If NowIfError is True (default if omitted) and there is an error while trying to convert the StrLikeDate value to date representation, the value of StrLikeDate will become the current date (Now), otherwise (NowIfError = False) the StrLikeDate will be returned as an empty string ('').

With the previous discussion in our mind, the DateComplete function can be called as:

 procedure TForm1.edDateExit(Sender: TObject) ;
 var
    s : string;
 begin
   s := edDate.Text;
   DateComplete(s, True) ; {or DateComplete(s)}
   edDate.Text := s;
 end; 
Note: The DateComplete procedure will alter the StrLikeDate value to a date format 'dd.mm.yyyy', where date separator '.' is stored in the global variable DateSeparator (Delphi reads this value from the Regional Settings in the Control Panel).

mm/dd/yyyy ?
If you (your users) are not using the 'dd.mm.yyyy' but 'mm/dd/yyyy' date format then DateComplete needs some modification to work properly. Take a look at the next line:

 case Length(DateStr) of
 ...
     1, 2 : DateStr:=DateStr + DateSeparator + IntToStr(Month) ;
 ...
 
This piece of code handles the situation when only one or two digits are entered - only day (remember: 'dd.mm.yyyy'). DateStr becomes DateStr + Month (current).

If you are working with 'mm/dd/yyyy' short date format, simply change the previous code to:

 case Length(DateStr) of
 ...
     1, 2 : DateStr:=DateStr + DateSeparator + IntToStr(Day) ;
 ...
 
That's it.

©2014 About.com. All rights reserved.