09/12/2021 (Version 1.2)
04/13/2021 (Version 1.1)
03/27/2021 (Version 1.0)
When you are working on your software project, you always need to store some data into a INI file or some text file, as a configuration file or other information.
So, the options you have is INI file, or plain text. And almost always you need a table with some fields.
In a plain text, you can use one record per line, and separate fields using tab character, or pipe character, or another one. But you have some problems with this method: you need to take care about the separator char, not using it at fields value; and you have a biggest problem: in a future version, if you need to add a column, you lose the compatibility at this file when there are already data stored.
If you are working with INI file, you can specify the field names, but even that, you have problems to store one record per section, and is difficult to reorder records, delete records and name the record.
But don't worry, here is the solution.
The DzXMLTable is a non-visual component where you can store records with fields and values, and you can name the field, so you don't need to worry at future versions. You can add new fields at any time, just reading and writing them.
This is a new concept of my previous DzMiniTable component.
Supports Delphi XE3..Delphi 11
type
TContact = class
ID: Integer;
Name: string;
Phone: string;
Active: Boolean; //new field in some new program version
end;
procedure LoadContactsExample(List: TObjectList<TContact>);
var
XML: TDzXMLTable;
Rec: TDzRecord;
Contact: TContact;
begin
XML := TDzXMLTable.Create(nil);
try
XML.FileName := 'C:Data.xml';
XML.Load;
for Rec in XML do
begin
Contact := TContact.Create;
Contact.ID := Rec['ID'];
Contact.Name := Rec['Name'];
Contact.Phone := Rec['Phone'];
Contact.Active := Rec.ReadDef('Active', True); //saved xml in old version could not have this field, so, read with default value.
List.Add(Contact);
end;
finally
XML.Free;
end;
end;
The field name is always case-insensitive in all methods and properties parameter.
FileName: string
= Specifies the full XML file name to Open and Save the table
RequiredFile: Boolean
= When this property is disabled (default), if the file does not exist at Open method, the table will be loaded empty without raising any exception.
RequiredField: Boolean
= When this property is disabled (default), you can read a non-exitent field without raising and exception, returning Unassigned
variant value.
Rec[Index: Integer]: TDzRecord
(default component property) = Returns record object by index.
RecCount: Integer
= Returns record count.
procedure Load;
Load the table from file specified at FileName property
procedure Save;
Save the table to file specified at FileName property
procedure Clear;
Clear all data in the table
function New(Index: Integer = -1): TDzRecord;
Create a new record in the table and returns record object. You can specify the new record position in the table, using Index
parameter. If you leave Index = -1
, the record wil be added at the end of the table.
procedure Delete(Index: Integer);
Delete a record by index.
function FindIdxByField(const Name: string; const Value: Variant): Integer;
Returns the first record index that matches same Name and Value. If no record is found, the function will return nil
.
function FindRecByField(const Name: string; const Value: Variant): TDzRecord;
Returns the first record object that matches same Name and Value. If no record is found, the function will return nil
.
function FindIdxBySameText(const Name: string; const Value: Variant): Integer;
Returns the first record index that matches same Name and Value, where Value is compared as String using case-insensitive. If no record is found, the function will return nil
.
function FindRecBySameText(const Name: string; const Value: Variant): TDzRecord;
Returns the first record object that matches same Name and Value, where Value is compared as String using case-insensitive. If no record is found, the function will return nil
.
procedure Move(CurIndex, NewIndex: Integer);
Moves a record from CurIndex
to NewIndex
position in the table.
Field[const Name: string]: Variant
= Returns or defines field value as variant by field name.
When getting field value, if the field does not exist, an exception will be raised, unless the RequiredField
property is False (in this case, an Unassigned
value will be returned.
When setting field value, if the field does not exist, it will be automatically created with specified name and value.
FieldIdx[Index: Integer]: TDzField
= Returns field object by field index.
Warning: One record can contain fields that are different from another record. So, you should never use a fixed index to a specific field (like a column) across the records.
FieldCount: Integer
= Returns number of fields in this record.
function ReadDef(const Name: string; DefValue: Variant): Variant;
Returns field value by field name. If field does not exist in the record, return DefValue
.
function FindField(const Name: string): TDzField;
Returns field object by field name. If field does not exist, returns nil
.
function FieldExists(const Name: string): Boolean;
Returns true if field exists by specified field name.
procedure ClearFields;
Clear all fields data in the record (It doesn't just remove the value from the fields, but the fields altogether).