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.