3 StrDb.pas is an attempt at a small database engine for KOL Objects.
4 It provides database functionality to the TStrList KOL Object.
5 As in KOL, the emphasis is on small. The test program, TestStrDB.exe is 29K.
9 The records are fixed width strings.
10 The fields are fixed width substrings of the records.
11 This simpifies the database functions since everything is stored as a string
12 including floats, dates etc.
16 The TStrTable object encapsulates:
18 An array of Field Definition records (FldDefArray)
20 A TStrList containing all the records (RecList)
22 A string holding the current record (RecStr)
24 A Current Record Number integer (fCurrRecNum)
26 Several Database functions and procedures (AddFldDef, First, EditRec, etc)
30 The TStrTable is created with the NewStrTable function.
32 Field Definitions are then added which provides the Field Name and Field Width.
34 The table can be populated manually then saved. (See TestStDb.dpr)
36 Alternately, fixed width data can be exported from an existing database or
39 Data is copied into the Current Record string (RecStr) via named fields.
41 Ex: SetFld('Name',E1.Text);
43 SetFld('EMail',E2.Text);
45 SetFld('URL',E3.Text);
47 When complete, RecStr is stored in the TStrList (RecList) via Insert or AddRec.
49 The First, Prior, Next, Last and SetCurrRec procedures copy the indexed RecList
50 string into RecStr (the current record).
52 The data is retrieved from RecStr via GetFld('Name'), etc.
54 This can then be modified and stored back in RecList via PostRec.
56 This manner of adding and editing records is different from the normal methods:
58 (Insert, Fill Fields, Post -and- Edit, Modify Fields, Post)
60 This method is better suited to the StrTable object.
62 If desired, the user interface can be programmed to work normally:
64 (Insert a Blank Record, Make That Field Current, Enter the Data, Post Record
66 or Delete the Blank Record if the User Cancels.)
69 Access to all the TStrList's methods and properties are available via
72 In this way Sorting, LoadFromFile, SaveToFile etc can be accomplished.
74 Incidently, Windows API appears to simplify sorting the listview by columns via
79 A typical program stores and loads it's table via RecList.LoadFromFile and RecList.SaveToFile. Note that data is entered into RecList is not saved to disk until RecList.SaveToFile is executed.
83 LoadFromFile is only one means of loading the RecList.
85 If only certain records in a file are needed, a file could be opened via
86 TFileStream, filtering could be done and the desired records can be Added
91 Additionally, two procedures are provided to automatically load a TListView
92 object from a StrTable:
94 FillListView adds columns with the same names as the field names. It then calls:
96 FillListGrid which adds the records found in the RecList as items.
98 FillListGrid can be called as required to repaint the grid and reflect RecList.
100 The column width is currently 4pixels * the field width.
102 This can be adjusted after the Listview is loaded (even to 0 to hide the column). }
114 {* Record stored in FldDefArray containing Field Definitions for TStrTable}
120 PStrTable
= ^TStrTable
;
121 TStrTable
= object( TObj
)
122 {* String Table object for accessing fields as substrings from a record string}
125 fCurrRecNum
: integer; //Used by Next, Prior, Post, InsertRec, DeleteRec
127 FldDefArray
: array of TFldDefRec
;
128 {* Array of Field Def Records - one FldDefRec for each Field in table}
129 destructor Destroy
; virtual;
132 {* StringList of all string records}
134 {* String containing record to get or set data from ( = current record)}
135 procedure AddFldDef(const FieldName
: string; FieldWidth
: integer);
136 {* Used To Add Field Definitions}
137 function GetFld(const FieldName
: string): string;
138 {* This is used to retrieve data from a record. Returns Data as substring of RecStr based on FieldName in Field Defs (see FldDefArray)}
139 procedure SetFld(const FieldName
, Data
: string);
140 {* This is used to modify data in a record. Replaces substring of RecStr with Data based on FieldName in Field Defs. (see FldDefArray)}
142 {* Goto First Record - Loads RecStr with First string from RecList and updates CurrRecNum }
144 {* Goto Last Record - Loads RecStr with Last string from RecList and updates CurrRecNum }
146 {* Goto Next Record - Loads RecStr with Next string from RecList and updates CurrRecNum }
148 {* Goto Prior Record - Loads RecStr with Prior string from RecList and updates CurrRecNum }
149 procedure SetCurrRec(RecNum
: integer);
150 {* Goto RecNum Record - Loads RecStr with RecNum string from RecList and updates CurrRecNum }
151 property CurrRecNum
: integer read fCurrRecNum write SetCurrRec
;
152 {* Current index of string in RecList - Assigning sets current record}
153 property EOF
: boolean read fEOF
;
154 {* End Of File Indicator}
155 property BOF
: boolean read fBOF
;
156 {* Beginning File Indicator}
158 {* Saves RecStr (current record) into RecList at CurrRecNum}
160 {* Inserts RecStr (current record) into RecList before CurrRecNum}
162 {* Adds RecStr to end of RecList}
164 {* Deletes string in RecList of index CurrRecNum
165 TStrTable.First is then executed to keep CurrRecNum in sync}
169 1. Editing and Inserting records operate differently than in TDataSet
171 To Edit: SetCurrRec then SetFld(s) then PostRec - There is no Edit proc.
173 To Insert: SetCurrRec then SetFld(s) then InsertRec - Do not use PostRec
175 To Append: SetFld(s) then AddRec - CurrRecNum is not used
177 2. Any database that can connect to fixed width text files can link to tables generated by TStrTable. For Example:
179 a) Save the table via TStrList.RecList.SavetoFile to a filename.asc.
181 b) Link to the table in MS Access as a Text file - Fixed width.
183 c) MS Access can use this ISAM linked table in a limited manner:
185 -- New records can be added, existing records can be read - but not edited or
188 -- For import into MS Access, records can be copied to another table if editing
191 -- For export into a StrTable, an update query can copy data to the linked table.
193 -- Select queries etc. in MS Access should be no problem.
197 function NewStrTable
: PStrTable
;
198 {* Creates a new TStrTable}
200 procedure FillListView( GivenListView
: PControl
; GivenStrTable
: PStrTable
);
201 {* Automatically adds columns to GivenListView with the same names as the field names found in GivenStrTable. It then calls FillListGrid. The column width is currently 4pixels * the field width. This can be adjusted after the Listview is loaded (even to 0 to hide the column).}
203 procedure FillListGrid( GivenListView
: PControl
; GivenStrTable
: PStrTable
);
204 {* FillListGrid adds the records found in GivenStrTable.RecList as items to GivenListView. FillListView should be called first to set up the columns. FillListGrid can be called as required to repaint the grid and reflect RecList.}
208 function NewStrTable
: PStrTable
;
210 New( Result
, Create
);
211 Result
.RecList
:= NewStrList
;
212 setlength(result
.FldDefArray
,0);
215 Result
.fCurrRecNum
:= 0;
218 procedure FillListView( GivenListView
: PControl
; GivenStrTable
: PStrTable
);
220 NoOfCols
, f
: integer;
222 NoOfCols
:= length(GivenStrTable
.FldDefArray
);
223 GivenListView
.Width
:= ( GivenStrTable
.FldDefArray
[NoOfCols
- 1].FldStart
+
224 GivenStrTable
.FldDefArray
[NoOfCols
- 1].FldWidth
) * 4 + 20;
225 for f
:= 1 to NoOfCols
do
227 GivenListView
.LVColAdd(GivenStrTable
.FldDefArray
[f
-1].FldName
, taLeft
,
228 GivenStrTable
.FldDefArray
[f
-1].FldWidth
* 4);
230 FillListGrid(GivenListView
, GivenStrTable
);
233 procedure FillListGrid( GivenListView
: PControl
; GivenStrTable
: PStrTable
);
235 CurRecNo
, NoOfCols
, NoOfRecs
, f
, g
: integer;
237 CurRecNo
:= GivenStrTable
.CurrRecNum
;
238 NoOfCols
:= length(GivenStrTable
.FldDefArray
);
239 NoOfRecs
:= GivenStrTable
.RecList
.Count
;
242 for f
:= 0 to NoOfRecs
- 1 do
243 with GivenListView
^, GivenStrTable
^ do
245 LVAdd( '', 0, [ ], 0, 0, 0 );
246 for g
:= 0 to NoOfCols
- 1 do
248 LVItems
[ f
, g
] := GetFld(FldDefArray
[g
].FldName
);
252 GivenStrTable
.CurrRecNum
:= CurRecNo
;
255 procedure TStrTable
.AddFldDef(const FieldName
: string; FieldWidth
: integer);
257 count
, FieldStart
: integer;
259 count
:= length(FldDefArray
);
261 FieldStart
:= FldDefArray
[count
- 1].FldStart
262 + FldDefArray
[count
- 1].FldWidth
265 setlength(FldDefArray
, count
+ 1);
266 with FldDefArray
[count
] do
268 FldName
:= FieldName
;
269 FldStart
:= FieldStart
;
270 FldWidth
:= FieldWidth
;
274 function TStrTable
.GetFld(const FieldName
: string): string;
279 TotFDs
:= length(FldDefArray
);
280 for f
:= 0 to TotFDs
- 1 do
282 if FldDefArray
[f
].FldName
= FieldName
then
284 result
:= copy(RecStr
, FldDefArray
[f
].FldStart
+ 1,
285 FldDefArray
[f
].FldWidth
);
291 procedure TStrTable
.SetFld(const FieldName
, Data
: string);
295 TotFDs
:= length(FldDefArray
);
296 for f
:= 0 to TotFDs
- 1 do
297 with FldDefArray
[f
] do
299 if FldName
= FieldName
then
301 RecStr
:= copy(RecStr
, 1, FldStart
) +
302 copy (Data
+ stringofchar(' ',FldWidth
), 1, FldWidth
) +
303 copy (RecStr
, FldStart
+ FldWidth
+ 1,
304 length(RecStr
) - FldStart
+ FldWidth
);
310 procedure TStrTable
.First
;
314 if RecList
.Count
= 0 then
319 RecStr
:= RecList
.Items
[0];
323 procedure TStrTable
.Last
;
326 if RecList
.Count
= 0 then
334 fCurrRecNum
:= RecList
.Count
- 1;
335 RecStr
:= RecList
.Items
[fCurrRecNum
];
339 procedure TStrTable
.Prior
;
341 if RecList
.Count
= 0 then
348 if fCurrRecNum
= 0 then
354 fCurrRecNum
:= fCurrRecNum
- 1;
355 RecStr
:= RecList
.Items
[fCurrRecNum
];
359 procedure TStrTable
.Next
;
361 if RecList
.Count
= 0 then
368 if fCurrRecNum
= RecList
.Count
- 1 then
374 fCurrRecNum
:= fCurrRecNum
+ 1;
375 RecStr
:= RecList
.Items
[fCurrRecNum
];
379 procedure TStrTable
.SetCurrRec(RecNum
: integer);
381 if RecList
.Count
= 0 then
388 if RecNum
>= RecList
.Count
then
397 fCurrRecNum
:= RecNum
;
398 RecStr
:= RecList
.Items
[fCurrRecNum
];
402 procedure TStrTable
.PostRec
;
404 RecList
.Items
[fCurrRecNum
] := RecStr
;
407 procedure TStrTable
.InsertRec
;
409 RecList
.Insert(fCurrRecNum
, RecStr
);
412 procedure TStrTable
.AddRec
;
417 procedure TStrTable
.DeleteRec
;
419 RecList
.Delete(fCurrRecNum
);
423 destructor TStrTable
.Destroy
;
426 setlength(FldDefArray
,0);