Delphi Clinic | C++Builder Gate | Training & Consultancy | Delphi Notes Weblog | Dr.Bob's Webshop |
![]() |
![]() |
![]() |
|
Analysing TClientDataSet data files
In this article, I'll demonstrate how to analyse TClientDataSet data files in XML or CDS format and produce a plain text or HTML output with the results.
Based on the original article from 2001, where I describe how to analyse a BDE Alias (and later a dbExpress connection to a database), I recently had the need to analyse a set of XML files that contained the data from a collection of TClientDataSets.
This actually makes the analysing process a lot easier, since I only had to assign the filename to the TClientDataSet (it supports both the XML and binary CDS format) and process the FieldDefs and IndexDefs.
Instead of producing HTML output, I needed two possible results: one with tabs (so I could use the resulting output and have MS-Word generate a nice table from it), and a comma separated result, so we could import the definitions themselves in a meta-table database.
The program below contains a Delimit: Char variable that is used to store the tab character (by default) or the second command-line argument (where you can pass a comma or any other character you want to use as delimiter).
program XMLlias; {$APPTYPE CONSOLE} uses Classes, DB, DBClient; const TAB = #9; var i: Integer; Delimit: Char; begin with TClientDataSet.Create(nil) do try FileName := ParamStr(1); if ParamCount > 1 then Delimit := ParamStr(2)[1] else Delimit := TAB; Open; // TClientDataSet if Delimit = TAB then // write tablename and records begin writeln(FileName,' ',RecordCount:4); for i:=1 to Length(FileName)+5 do write('='); writeln; end; // write field (meta) data definitions writeln('Field',Delimit,'Name',Delimit,'Type',Delimit,'Req'); for i:=0 to Pred(FieldCount) do begin write(i,Delimit); write(Fields[i].DisplayName,Delimit); write(FieldDefs[i].FieldClass.ClassName); if FieldDefs[i].DataType = ftString then write('[',FieldDefs[i].Size,']'); if FieldDefs[i].Required then write(Delimit,'Yes'); writeln end; // write index (meta) definitions IndexDefs.Update; if IndexDefs.Count > 0 then begin writeln; writeln('Index',Delimit,'Name',Delimit,'Fields'); for i:=0 to Pred(IndexDefs.Count) do begin write(i,Delimit); write(IndexDefs[i].DisplayName,Delimit); write(IndexDefs[i].Fields); writeln end end; Close // TClientDataSet finally Free // TClientDataSet end end.
I apolgise for using the with statement here, but for small utility like console applications like this, with no ambuguity regarding the scope, I felt it could do little harm...