Author: Tomas Rutkauskas
I would like to know how to save TListView items and subitems into a file and
reload them into the listview on a button click or the next time the program starts.
Answer:
Solve 1:
The answer depends on what information you need to save and restore: only the
strings or also image indices, if the latter, which indices? If it's only the
strings one could do it this way:
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 ComCtrls,
8 StdCtrls;
9
10 type
11 TForm1 = class(TForm)
12 ListView1: TListView;
13 SaveButton: TButton;
14 ClearButton: TButton;
15 LoadButton: TButton;
16 procedure ClearButtonClick(Sender: TObject);
17 procedure SaveButtonClick(Sender: TObject);
18 procedure LoadButtonClick(Sender: TObject);
19 private
20 { Private declarations }
21 public
22 { Public declarations }
23 end;
24
25 var
26 Form1: TForm1;
27
28 implementation
29
30 {$R *.DFM}
31
32 {
33 Function IScan:
34 Parameters:
35 ch: Character to scan for
36 S : String to scan
37 fromPos: first character to scan
38 Returns: position of next occurence of character ch, or 0, if none found
39 Description: Search for next occurence of a character in a string
40 Error Conditions: none
41 Created: 11/27/96 by P. Below
42 }
43
44 function IScan(ch: Char; const S: string; fromPos: Integer): Integer;
45 var
46 i: Integer;
47 begin
48 Result := 0;
49 for i := fromPos to Length(S) do
50 begin
51 if S[i] = ch then
52 begin
53 Result := i;
54 Break;
55 end;
56 end;
57 end;
58
59 {
60 Procedure SplitString:
61 Parameters:
62 S: String to split
63 separator: character to use as separator between substrings
64 substrings: list to take the substrings
65 Description: Isolates the individual substrings and copies them into the passed
66 stringlist. Note that we only add to the list, we do not clear it first! If two
67 separators follow each other directly an empty string will be added to the list.
68 Error Conditions: will do nothing if the stringlist is not assigned
69 Created: 08.07.97 by P. Below
70 }
71
72 procedure SplitString(const S: string; separator: Char; substrings: TStringList);
73 var
74 i, n: Integer;
75 begin
76 if Assigned(substrings) and (Length(S) > 0) then
77 begin
78 i := 1;
79 repeat
80 n := IScan(separator, S, i);
81 if n = 0 then
82 n := Length(S) + 1;
83 substrings.Add(Copy(S, i, n - i));
84 i := n + 1;
85 until
86 i > Length(S);
87 end;
88 end;
89
90 resourcestring
91
92 eInvalidViewstyle = '%s: the listview %s is not in vsReport mode.';
93
94 {
95 Procedure SaveListviewStrings:
96 Parameters :
97 listview : listview to save, must be in vsreport mode, <> nil
98 filename : full pathname of file to create
99 Description:
100 Iterates over the items of the passed listview and saves the item and
101 subitem strings to file. The created file is a plain text file, each item
102 occupies one line, subitems are separated by tab characters.
103 Error Conditions:
104 An exception will be raised if the listview is not in vsreport mode or if the
105 file cannot be written to.
106 Created: 2.4.2000 by P. Below
107 }
108
109 procedure SaveListviewStrings(listview: TLIstview; const filename: string);
110 var
111 sl: TStringlist;
112 S: string;
113 i, k: Integer;
114 item: TLIstItem;
115 begin
116 Assert(Assigned(listview));
117 if listview.ViewStyle <> vsReport then
118 raise Exception.CreateFmt(eInvalidViewstyle, ['SaveListviewStrings',
119 listview.name]);
120 sl := TStringlist.Create;
121 try
122 for i := 0 to listview.items.count - 1 do
123 begin
124 item := listview.Items[i];
125 S := item.Caption;
126 for k := 0 to item.SubItems.Count - 1 do
127 S := S + #9 + item.Subitems[k];
128 sl.Add(S);
129 end;
130 sl.SaveToFile(filename);
131 finally
132 sl.free
133 end;
134 end;
135
136 {
137 Procedure LoadListviewStrings:
138 Parameters :
139 listview : listview to load, must be in vsreport mode, <> nil
140 filename : full pathname of file to read
141 Description:
142 Reads the file into a stringlist and then dissects each line into another list
143 of strings. It expects the lists elements to be separated by tab characters. For
144 each line read a new listitem is added to the listview and its caption and subitems
145 are set from the lines elements. Note that the listview is not cleared
146 first, so the new items will be added to whatever items the listview already
147 contains.
148 Error Conditions:
149 An exception will be raised if the listview is not in vsreport mode or if the file
150 cannot be loaded.
151 Created: 2.4.2000 by P. Below
152 }
153
154 procedure LoadListviewStrings(listview: TLIstview; const filename: string);
155 var
156 sl, lineelements: TStringlist;
157 i: Integer;
158 item: TLIstItem;
159 begin
160 Assert(Assigned(listview));
161 if listview.ViewStyle <> vsReport then
162 raise Exception.CreateFmt(eInvalidViewstyle, ['LoadListviewStrings',
163 listview.name]);
164 sl := TStringlist.Create;
165 try
166 sl.LoadFromFile(filename);
167 lineelements := Tstringlist.Create;
168 try
169 for i := 0 to sl.count - 1 do
170 begin
171 lineelements.Clear;
172 SplitString(sl[i], #9, lineelements);
173 if lineelements.Count > 0 then
174 begin
175 item := listview.Items.Add;
176 item.Caption := lineelements[0];
177 lineelements.Delete(0);
178 item.SubItems.Assign(lineelements);
179 end;
180 end;
181 finally
182 lineelements.free;
183 end;
184 finally
185 sl.free
186 end;
187 end;
188
189 const
190 testfilename = 'c:\temp\testfile.txt';
191
192 procedure TForm1.ClearButtonClick(Sender: TObject);
193 begin
194 listview1.items.clear;
195 end;
196
197 procedure TForm1.SaveButtonClick(Sender: TObject);
198 begin
199 SaveListviewStrings(listview1, testfilename);
200 end;
201
202 procedure TForm1.LoadButtonClick(Sender: TObject);
203 begin
204 LoadListviewStrings(listview1, testfilename);
205 end;
206
207 end.
Solve 2:
Subclass TListView and add these to your new component:
208 unit MyListView;
209
210 interface
211
212 uses
213 SysUtils, Classes, ComCtrls, Forms, Windows, Menus, Controls;
214
215 type
216
217 TCheckBoxString = class(TComponent)
218 private
219 FTheString: string;
220 protected
221 public
222 published
223 property CheckBoxString: string read FTheString write FTheString;
224 end;
225
226 TMyListView = class(TListView)
227 private
228 public
229 procedure SaveToFile(FileName: string);
230 procedure LoadFromFile(FileName: string);
231 published
232 end;
233
234 procedure register;
235
236 implementation
237
238 procedure TMyListView.SaveToFile(FileName: string);
239 var
240 FStream: TMemoryStream;
241 i: Integer;
242 FStrings: TCheckBoxString;
243 begin
244 FStream := TMemoryStream.Create;
245 FStrings := TCheckBoxString.Create(nil);
246 try
247 FStream.WriteComponent(Self);
248 if Self.Checkboxes then
249 begin
250 FStrings.CheckBoxString := '';
251 for i := 0 to Self.Items.Count - 1 do
252 begin
253 if Self.Items[i].Checked then
254 FStrings.CheckBoxString := FStrings.CheckBoxString + 'T'
255 else
256 FStrings.CheckBoxString := FStrings.CheckBoxString + 'F';
257 end;
258 FStream.WriteComponent(FStrings);
259 end;
260 FStream.SaveToFile(FileName);
261 finally
262 FStream.Free;
263 FStrings.Free;
264 end;
265 end;
266
267 procedure TMyListView.LoadFromFile(FileName: string);
268 var
269 FStream: TFileStream;
270 i: Integer;
271 FStrings: TCheckBoxString;
272 begin
273 FStream := TFileStream.Create(FileName, fmOpenRead);
274 FStrings := TCheckBoxString.Create(nil);
275 try
276 Self.Columns.BeginUpdate;
277 Self.Items.BeginUpdate;
278 Self.Items.Clear;
279 Self := FStream.ReadComponent(Self) as TMyListView;
280 if Self.Checkboxes then
281 begin
282 FStrings := FStream.ReadComponent(FStrings) as TCheckBoxString;
283 for i := 0 to Self.Items.Count - 1 do
284 begin
285 if (i + 1) <= Length(FStrings.CheckBoxString) then
286 Self.Items[i].Checked := (FStrings.CheckBoxString[i + 1] = 'T');
287 end;
288 end;
289 finally
290 FStream.Free;
291 FStrings.Free;
292 Self.Columns.EndUpdate;
293 Self.Items.EndUpdate;
294 end;
295 end;
|