-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathMemDBF.pas
136 lines (124 loc) · 3.73 KB
/
MemDBF.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
unit MemDBF;
////////////////////////////////////////////////////////////////////////////////
//
// Class to manipulate a dbf file. Data are read into a FireDac memory table to be
// manipulated. The manipulated table can be saved to file again.
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Author: Jaap Baak
// https://github.com/transportmodelling/Utils
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
interface
////////////////////////////////////////////////////////////////////////////////
Uses
SysUtils, Data.DB, FireDac.Comp.Client, DBF;
Type
TMemDBF = Class
private
FFileName: String;
FTable: TFDMemTable;
Fields: TArray<TDBFField>;
OwnsTable: Boolean;
public
Constructor Create(const FileName: String); overload;
Constructor Create(const FileName: String; const Table: TFDMemTable); overload;
Procedure Save;
Procedure SaveAs(const FileName: String);
Destructor Destroy; override;
public
Property FileName: String read FFileName;
Property Table: TFDMemTable read FTable;
end;
////////////////////////////////////////////////////////////////////////////////
implementation
////////////////////////////////////////////////////////////////////////////////
Constructor TMemDBF.Create(const FileName: String);
begin
Create(FileName,TFDMemTable.Create(nil));
OwnsTable := true;
end;
Constructor TMemDBF.Create(const FileName: String; const Table: TFDMemTable);
begin
inherited Create;
if FileExists(FileName) then
begin
// Set property values
FFileName := FileName;
FTable := Table;
// Read table
var DBFReader := TDBFReader.Create(FileName);
try
// Read fields
Fields := DBFReader.GetFields;
FTable.FieldDefs.Clear;
for var Field in Fields do
case Field.FieldType of
'C': FTable.FieldDefs.Add(Field.FieldName,ftString,Field.FieldLength);
'D': FTable.FieldDefs.Add(Field.FieldName,ftDate);
'L': FTable.FieldDefs.Add(Field.FieldName,ftBoolean);
'F','N':
if Field.DecimalCount = 0 then
FTable.FieldDefs.Add(Field.FieldName,ftInteger)
else
FTable.FieldDefs.Add(Field.FieldName,ftFloat)
end;
FTable.CreateDataSet;
// Read data
for var Rec := 1 to DBFReader.RecordCount do
try
if DBFReader.NextRecord then
begin
FTable.Append;
for var Field := 0 to DBFReader.FieldCount-1 do
FTable.Fields[Field].Value := DBFReader[Field];
end else
raise exception.Create('Error reading DBF-file');
except
on E: Exception do raise Exception.Create(E.Message + ' record ' + Rec.ToString);
end;
FTable.First;
finally
DBFReader.Free;
end;
end else
raise Exception.Create('DBF-file does not exist');
end;
Procedure TMemDBF.Save;
begin
SaveAs(FFileName);
end;
Procedure TMemDBF.SaveAs(const FileName: String);
begin
// Set property value
FFileName := FileName;
// Write dbf-file
var DBFWriter := TDBFWriter.Create(FFileName,Fields);
try
FTable.DisableControls;
try
// Save data
FTable.First;
while not FTable.Eof do
begin
for var Field := low(Fields) to high(Fields) do
DBFWriter.FieldValues[Field] := FTable.Fields[Field].Value;
DBFWriter.AppendRecord;
FTable.Next;
end;
finally
FTable.EnableControls;
end;
finally
DBFWriter.Free;
end;
end;
Destructor TMemDBF.Destroy;
begin
if OwnsTable then FTable.Free;
inherited Destroy;
end;
end.