BCS XE3 Utilities Component


The BCS XE3 Utilities component is designed to increase efficacy and eliminate code redundancy. DRY (don’t repeat yourself) is an admiral virtue for software development.
The component documentation for BCSXE3Utils can be found here.  The complete source can be found here.
Component documentation for all available components can be found here.
The Select A Directory feature allows any application using this component to select a directory or sub directory by invoking its calling sequence.

{*-----------------------------------------------------------------------------
 Procedure: btnSelDirClick
 Date:      20-May-2013
 @Param Sender TObject Primary Object For Dialog
 @Return    None
 -----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.btnSelDirClick(Sender: TObject);
begin
  SelADir;
  lblSelDir.Caption := DirSel;
end;
{*-----------------------------------------------------------------------------
 Procedure: SelADir
 Author:    AMB01
 Date:      20-May-2013
 @Return    String
 -----------------------------------------------------------------------------}
function TBCSXE3UtilsC.SelADir: String;
begin
  DirSel := '';
  if SDCaption = '' then
  begin
    dlgSelDir.Title := 'Select A Directory Now!';
  end
  else
  begin
    dlgSelDir.Title := SDCaption;
  end;
  if dlgSelDir.Execute then
  begin
    DirSel := IncludeTrailingPathDelimiter(dlgSelDir.FileName);
    Result := DirSel;
  end;
end;

Notice the caption of the directory selection may be changed via the SDCaption property.  The selected directory is then appended with the required trailing path delimiter so the results are ready to rock. The DirSel property has the directory that was selected.
The Get File List allows the user to retrieve a list of files after the directory is selected.  The list of files is populated in the list box and their contents are also available in the property FilRetOc.  The number of lines in the dynamic string array is contained in the property FileLen.
The invoking sequence is as follows:

{*-----------------------------------------------------------------------------
 Procedure: btnGetFileNamesClick
 Author:    AMB01
 Date:      20-May-2013
 @Param Sender TObject Primary Object For Dialog
 @Return    None
 -----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.btnGetFileNamesClick(Sender: TObject);
begin
  SelADir;
  FilRetOc := GetFileNames(DirSel, GetUserInput('Select File Extension',
    'Specify File Extension Now', '*.zip'));
  PopulateListBox(FilRetOc, FilLen, lbxFileLB);
  lblFileCount.Caption := FormatFloat('#,###', FilLen);
end;

The GetUserInput is a function that prompts the user for input.  Its code is listed below.

{*-----------------------------------------------------------------------------
 Procedure: GetUserInput
 Author:    AMB01
 Date:      20-May-2013
 @Param     rcap, rpro, rdef: String
 @Return    String
 -----------------------------------------------------------------------------}
function TBCSXE3UtilsC.GetUserInput(rcap, rpro, rdef: String): String;
begin
  Result := InputBox(rcap, rpro, rdef);
end;

Notice the string parameters that are passed to the InputBox routine which makes a handy portal for getting text information from the user.
The GetFileNames function populates the dynamic string array and also sets the FileLen property it the appropriate value for the contents of the dynamic string array.

{*-----------------------------------------------------------------------------
 Procedure: GetFileNames
 Author:    AMB01
 Date:      20-May-2013
 @Param     path, ext: String
 @Return    System.Types.TStringDynArray
 -----------------------------------------------------------------------------}
function TBCSXE3UtilsC.GetFileNames(path, ext: String)
  : System.Types.TStringDynArray;
var
  oc: TStringDynArray;
begin
  oc := TDirectory.GetFiles(path, ext, TSearchOption.soAllDirectories);
  FilLen := Length(oc);
  Result := oc;
end;

There is code block used here that uses a dynamic string array to populate the list box.  The procedure name is PopulateListBox.  The code for PopulateListBox follows below.
 

{*----------------------------------------------------------------------------- Procedure: PopulateListBox Author: AMB01 Date: 20-May-2013 @Param ai: TStringDynArray; incnt: Integer; var lbx: TListBox @Return None   -----------------------------------------------------------------------------}   procedure TBCSXE3UtilsC.PopulateListBox(ai: TStringDynArray; incnt: Integer; var lbx: TListBox); var i: Integer; begin lbx.Items.Clear; i := 0; Repeat lbx.Items.Add(ai[i]); Inc(i) Until (i > (incnt - 1)); end;

 
When you click on a file in the list box the shell execute API in invoked and any associated application is launched for that file.  As an example if the file extension is .docx then Microsoft Word would stat up and the clicked on file would appear in word for further processing and editing.
The code for the shell execute API is listed below.

{*-----------------------------------------------------------------------------
 Procedure: lbxFileLBClick
 Author:    AMB01
 Date:      20-May-2013
 @Param     Sender: TObject
 @Return    None
 -----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.lbxFileLBClick(Sender: TObject);
begin
  XQTPgm(lbxFileLB.Items[lbxFileLB.ItemIndex]);
end;

As you can see any command in the form of a string can be passed to the XQTPgm routine and that command will be invoked immediately.
The code for XQTPgm is listed below.
 

{*-----------------------------------------------------------------------------
 Procedure: XQTPgm
 Author:    AMB01
 Date:      20-May-2013
 @Param     cmd: string
 @Return    None
 -----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.XQTPgm(cmd: string);
begin
  ShellAPI.ShellExecute(Handle, PWideChar('open'), PWideChar(cmd), '',
    PWideChar(XQTDir), sw_Normal);
end;

If the program requires a execute from a specific directory the XQTDir parameter should be set prior to calling XQTPgm.  To set and clear the XQTDir property use the SetXQTDir and ClearXQTDir procedures respectively.  Of course SetXQTDir uses the SelADir function that was discussed earlier.
The get directories function is listed below.

{*-----------------------------------------------------------------------------
 Procedure: btnGetDirsClick
 Author:    AMB01
 Date:      20-May-2013
 @Param Sender TObject Primary Object For Dialog
 @Return    None
 -----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.btnGetDirsClick(Sender: TObject);
begin
  lbxDirLB.Items.Clear;
  SelADir;
  DirRetOc := GetDirs(DirSel);
  PopulateListBox(DirRetOc, DirLen, lbxDirLB);
  lblDirCount.Caption := FormatFloat('#,###', DirLen);
end;

As usual the SelADir function is used to get the initial directory.  Then the GetDirs function is invoked and a dynamic string array is populated with the list of directories. The DirRetOc is the property that contains the list of directories and the DirLen property contains the number of items in the dynamic string array.  Finally the directory list box is populated with the PopulateListBox function which was previously discussed.
The GetDirs function is listed below.

{*-----------------------------------------------------------------------------
 Procedure: GetDirs
 Author:    AMB01
 Date:      20-May-2013
 @Param     path: String
 @Return    System.Types.TStringDynArray
 -----------------------------------------------------------------------------}
function TBCSXE3UtilsC.GetDirs(path: String): System.Types.TStringDynArray;
var
  oc: TStringDynArray;
begin
  oc := System.IOUtils.TDirectory.GetDirectories(path);
  DirLen := Length(oc);
  Result := oc;
end;

To detect the first and last day of any given week simply click the Find First and Last Day of Week control.
The invoking procedure is listed below.

{*-----------------------------------------------------------------------------
 Procedure: btnFDowLDowClick
 Author:    AMB01
 Date:      22-May-2013
 @Param     Sender: TObject
 @Return    None
 -----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.btnFDowLDowClick(Sender: TObject);
begin
  hide;
  if BCSGetDateTimeCmp1.Execute then
  begin
    show;
    rdt := BCSGetDateTimeCmp1.SelDateTime;
    lblCurDateTime.Caption :=
      FormatDateTime('dddd   , mmmm    dd,yyyy hh:m:ss', rdt);
    GetFLDOW(rdt);
    lblFDow.Caption := FormatDateTime('mm/dd/yyyy', FirstDayOfWeek);
    lblLDow.Caption := FormatDateTime('mm/dd/yyyy', LastDayOfWeek);
  end;
  show;
end;

As you have noticed the BCSGetDateTimeCmp1 component allows the user to select the desired date and time.
The GetFLDOW routine performs the heave lifting and can be viewed below.

{*-----------------------------------------------------------------------------
  Procedure: GetFLDOW
  Date:      25-May-2013
  @Param     var rdt: TDateTime
  @Return    None
-----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.GetFLDOW(var rdt: TDateTime);
begin
  FirstDayOfWeek := StartOfTheWeek(rdt);
  LastDayOfWeek := EndOfTheWeek(rdt);
end;

The FirstDayOfWeek and LasDayOfWeek properties will house the first and last day of the selected week respectively.
The increment date and time function allow the user to traverse dates and times my increments of months, days, years, hours, minutes and seconds. First the user is prompted to provide the increment values. A negative value will move the date and time to a date and time in the past. Positive values will yield a date in the future. Finally a starting date and time via the BCS Get Date And Time Component must be selected. The calculation commence with the date is selected. The date selected and the newly created date are readily visible for review.

{*-----------------------------------------------------------------------------
 Procedure: btnIncDateTimeClick
 Date:      26-May-2013
 @Param     Sender: TObject
 @Return    None
 -----------------------------------------------------------------------------}
procedure TBCSXE3UtilsC.btnIncDateTimeClick(Sender: TObject);
var
  rdt : TDateTime;
begin
  hide;
  if BCSGetDateTimeCmp1.Execute then
  begin
    show;
    rdt := BCSGetDateTimeCmp1.SelDateTime;
    ReportDateTime(lblInitDate, rdt);
    rdt := IncMonth(rdt, StrToInt(edtMonths.Text));
    edtMonths.Text := '0';
    ReportDateTime(lblAfterAdd, rdt);
    rdt := IncDay(rdt, StrToInt(edtDays.Text));
    edtDays.Text := '0';
    ReportDateTime(lblAfterAdd, rdt);
    rdt := IncYear(rdt, StrToInt(edtYears.Text));
    edtYears.Text := '0';
    ReportDateTime(lblAfterAdd, rdt);
    rdt := IncHour(rdt, StrToInt(edtHours.Text));
    edtHours.Text := '0';
    ReportDateTime(lblAfterAdd, rdt);
    rdt := IncMinute(rdt, StrToInt(edtMinutes.Text));
    edtMinutes.Text := '0';
    ReportDateTime(lblAfterAdd, rdt);
    rdt := IncSecond(rdt, StrToInt(edtSeconds.Text));
    edtSeconds.Text := '0';
    ReportDateTime(lblAfterAdd, rdt);
  end;
  show;
end;

These routine are prepared to demonstrate capabilities and to serve as a baseline documentation for utilizing many of the new facilities in Delphi XE3.
Modifications will be made to this component as new requirements are called for through further application development.
Mr. Arch Brooks, Software Engineer, Brooks Computing Systems authored this article.

Leave a Reply

Your email address will not be published. Required fields are marked *