Mega Code Archive

 
Categories / Delphi / Examples
 

WRITING SMART IS WRITING LESS

Title: WRITING SMART IS WRITING LESS Question: We are children of the visual era. Thick books are not in fashion.That is a very fact and it doesnt matter if one likes it or not. You maybe know someone of the old-generation developers who still strongly believes in writing more code instead of using visual components and so on. But the time when every byte had to be taken into consideration has gone. Computers are different today. Developers are different too. Writing as quickly as possible (or even faster) and writing easily are the goals and this simple meanswriting less. Answer: Delphi gives you the opportunity to choose your own way. If you prefer the wooden plough, you can write a whole application even without a Tform, only by using the Windows API functions. But for those who would rather relax, there are perfect solutions too. And the outcome in the most cases will be even better. Here is an example. The task is to create a report(with Quickreport) which presents the changes in the lookup tables. There are 25 lookup tables in this Oracle database, each of them with 4 common fields: CREATEUSER(NUMBER), LASTUSER (NUMBER), CREATETIME(DATE) and LASTTIME(DATE).On insert or on update triggers write to these fields. The report have to process the information from them and to present a list of all new and all changed records according to a user definited period of time. Obviously, one of the approaches is to create a run-time Tquery which delivers the data from the tables one after another and fills a temporary table (it is possible to use a TClientDataSet instead of a table) and then to use this table as a dataset for the report. The presumed advantage for this solution is a saving on visual components which leads to a smaller and maybe faster executable. But after quite a lot of lines of boring code, the reward may not be so worthy: the user will have an even faster report if it is developed trough the visual way and today 100K more or less are really of no importance So, a datamodule is added to the project with 2 TQuery components. One of them for the new records: SELECT * FROM WHERE CREATEDATE IS = :STARTDATE AND CREATEDATE IS = :STARTDATE AND LASTDATE IS Figure1: Data Module with 50 TQuery components for 1 report: it is simple and really fast. It is not compulsory to write a lot in order to assign a value to each of the exactly 100 parameters here and to open all 50 queries. Several plain lines of code are enough: function TDataM.GetData(stDate,EndDate: TDateTime):boolean; var i:integer; begin try For i:=0 to Self.ComponentCount-1 do begin if (Self.Components [i] is TQuery ) then begin ) Self.Components [i] as TQuery).Close; ) Self.Components [i] as TQuery).ParamByName ('StartDate').AsDateTime:= stDate; (Self.Components [i] as TQuery).ParamByName ('EndDate').AsDateTime:= EndDate; (Self.Components [i] as TQuery).Open; end; end; Result:=true; except result:=false; end; end; Now there are 50 independent datasources. It is possible to create 50 different simple reports with them (which run almost simultaneously) and to receive the data in no time: in fact 1 Quickreport with 50 subdetail bands does the job. Every subdetail band has a dataset property which should be assigned to the corresponding TQuery at design time. Setting another property PrintifEmpty to false makes it possible to show only tables in which records where added or updated. In this case no detail band is needed, nor a line of additional coding. But writing smart doesnt mean using visual at any cost. In every query of our example there is CREATEUSER or LASTUSER field a foreign key to the USERS table which is in fact a lookup table for all our lookup tables. The report should present not the numbers but the names of the users who have added or changed records. One way is to attach a persistent lookup field to every TQuery component and to define it at design time (using the fields editor). But these 50 new persistent fields could be replaced by 4 lines of code: procedure TQRListForm.QRDBText1Print(sender: TObject; var Value: String); begin Query1.Close; Query1.Params[0].AsInteger := (Sender as TQRDBText).DataSet.FieldByName( (Sender as QRDBText).DataField).AsInteger; Query1.Open; Value:= Query1.Fields[0].AsString ; end; Lets analyse them shortly. Another TQuery component is added straight onto the report form. The SQL statement is simple too: SELECT NAME FROM USERS WHERE ID = :ID. There are two types of datasets and two type of corresponding TQRDBTexts: assigned to CREATEUSER or LASTUSER fields. They both receive the right value due to this procedure to which their OnPrint events are assigned. Here is another short procedure which uses a very similar way to obtain the right field name for the ORDER BY clause of the SQL: procedure TForm1.DBGrid1TitleClick(Column: Tcolumn); begin try Column.Field.DataSet.Active := false; If Pos('ORDER BY', (Column.Field.DataSet as TQuery).SQL [(Column.Field.DataSet as TQuery).SQL.Count-1])0 then (Column.Field.DataSet as TQuery).SQL.Delete((Column.Field.DataSet as TQuery).SQL.Count-1); (Column.Field.DataSet as TQuery).SQL.Add('ORDER BY '+Column.Field.FieldNam(; Column.Field.DataSet.Active := True; except End; end; The task is to sort the grid according to the clicked column. This procedure deletes the old order by clause and writes a new one to the SQL of the TQuery datasource . Again, thanks to the casting and the dynamic reading of the properties, the code is quite universal and works for every column, no matter how many they are. In Delphi little code is needed to make a good application. You can just relax andwrite smart.