Entwickler-Ecke

Open Source Units - Speichern eines ListViews


ChriDDel - Di 01.03.05 10:47
Titel: Speichern eines ListViews
Wie kann ich ein ListView speichern?

Mit diesen 2 Methoden kann ein Listview in eine Datei gespeichert, und aus dieser wieder geladen Werden.
Dabei ist die Anzahl der Spalten nicht relevant.
Es werden alle Zeilen (ohne Überschriften aber mit dem IconIndex) gespeichert und geladen.

In den Inline-Kommentaren beziehe ich mich auf eine ListView ansicht als Report.

ps: Das speichern der Überschriften ist auch nicht das Problem, kommt evtl. noch nach.
Dieser Punkt war für mich aber nicht interessant.


Delphi-Quelltext
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:
unit ListViewEdit;

interface
uses
   SysUtils, Classes, ComCtrls;

  procedure ListViewSaveToFile(Filename : String; ListView : TListView);
  procedure ListViewLoadFromFile(Filename : String; ListView : TListView);

implementation


{
Vers: 0.0.0.1

Wie kann ich ein ListView speichern?

Mit diesen 2 Methoden kann ein Listview in eine Datei gespeichert, und aus dieser wieder geladen Werden.
Dabei ist die Anzahl der Spalten nicht relevant.
Es werden alle Zeilen (ohne Überschriften aber mit dem IconIndex) gespeichert und geladen.

In den Inline-Kommentaren beziehe ich mich auf eine ListView ansicht als Report.

(ChriDDel)

ps: Das speichern der Überschriften ist auch nicht das Problem, kommt evtl. noch nach.
    Dieser Punkt war für mich aber nicht interessant.

}




procedure ListViewSaveToFile(Filename : String; ListView : TListView);
{Copyright Christoph D. 2005}
var
  TextFile: TStringList;
  i: integer;
begin
try
  TextFile:= TStringList.Create;

    for i := 0 to (ListView.Items.Count - 1do // Geht alle Zeilen durch (ohne Überschriften)
    begin
      ListView.Items.Item[i].SubItems.Delimiter:='#'//Trennzeichen zum Speichern. Sollte eines sein, das nicht im Text vorkommt.
      TextFile.Add(  IntToStr(ListView.Items.Item[i].ImageIndex)  //Index des Images für diese Zeile
            +'#'            //Trennzeichen (siehe oben)
            +ListView.Items.Item[i].Caption      //Erste Spalte
            +'#'            //Trennzeichen (siehe oben)
            +ListView.Items.Item[i].SubItems.DelimitedText);//Alle weitere Spalten
    end;

  TextFile.SaveToFile(Filename); //Speichern des ListViews in eine Datei
finally
  TextFile.Free;
end;
end;

procedure ListViewLoadFromFile(Filename : String; ListView : TListView);
{Copyright Christoph D. 2005}
var
   TextFile,TextFile2 : TStringList;
   NewListItem: TListItem;
   i,x: integer;
begin
try
  ListView.Clear;
  TextFile:= TStringList.Create;
  TextFile2:= TStringList.Create;

  TextFile.LoadFromFile(Filename);  //ListView aus der Datei laden.

  TextFile2.Delimiter:='#';    //Trennzeichen, wie beim Speichern angegeben

  for i:=0 to TextFile.Count-1 do   // Geht alle Zeilen durch (ohne Überschriften)
  begin
    TextFile2.DelimitedText:=TextFile.Strings[i];  //Erste Zeile aus der gespeicherten Datei in die Richtigen Spalten schreiben

    NewListItem := ListView.Items.Add;        //Neues Item anlegen  
    NewListItem.ImageIndex:=StrToInt(TextFile2.Strings[0]);  //Index des Images für diese Zeile
    NewListItem.Caption :=TextFile2.Strings[1];      //Erste Spalte
    for x:=2 to TextFile2.Count-1 do        //Geht die restlichen Spalten durch
    begin
      NewListItem.SubItems.Add(TextFile2.Strings[x]);    //Spalten mit dem text aus der Datei füllen
    end;

  end;
finally
  TextFile.Free;
  TextFile2.Free;
end;
end;

end.


Moderiert von user profile iconAXMD: Code- durch Delphi-Tags ersetzt.


Harry Hunt - Di 01.03.05 10:55

Das geht auch einfacher...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create('C:\MeineDatei.dat', fmCreate);
  Stream.WriteComponentRes('', ListView1);
  Stream.Free;
end;


Das laden geht dann über ReadComponentRes. Im Gegensatz zu deiner Variante speicher diese Methode aber die ganze Komponente mit allen Eigenschaften und es wird ein binäres und kein plain-text Format verwendet.


AXMD - Di 01.03.05 10:56

:welcome:

Und wo genau liegt jetzt dein Problem? Code zum Speichern hast du ja...

AXMD


maximus - Di 01.03.05 12:11

AXMD hat folgendes geschrieben:
:welcome:

Und wo genau liegt jetzt dein Problem? Code zum Speichern hast du ja...

AXMD


Nun seid mal nicht so garstig! Das hier ist der OpenSource units bereich. Hier kann jeder seine units veröffentlichen. Und wenn es einer besser kann, dann kann er hier auch gerne seine eigene unit einbringen...

Also nicht gleich drauf hauen :D


AXMD - Di 01.03.05 12:15

maximus hat folgendes geschrieben:
AXMD hat folgendes geschrieben:
:welcome:

Und wo genau liegt jetzt dein Problem? Code zum Speichern hast du ja...

AXMD


Nun seid mal nicht so garstig! Das hier ist der OpenSource units bereich. Hier kann jeder seine units veröffentlichen. Und wenn es einer besser kann, dann kann er hier auch gerne seine eigene unit einbringen...

Also nicht gleich drauf hauen :D


Und ich dachte, es wär eine Frage - bis ich gesehen hab, dass es eine Open Source-Unit ist :autsch:

Sorry
AXMD


ChriDDel - Di 01.03.05 12:38

Das ist natürlich die kürzere und genauere Variante, aber für mich leider un interessant, da ich die Files auch mit einem Notepad bearbeiten können muss.


maximus - Di 01.03.05 14:35

ChriDDel hat folgendes geschrieben:
Das ist natürlich die kürzere und genauere Variante, aber für mich leider un interessant, da ich die Files auch mit einem Notepad bearbeiten können muss.


Das wäre kein problem, wenn du den stream mit ObjectBinaryToText in lesbaren DFM-text konvertierst. Ist aber hierfür ein bisschen übertrieben.


kuba67 - Do 27.11.08 17:43

Hallo,

ich habe mit dem Laden ein Problem wenn ich ein Leerzeichen in meinem ListView verwende.
Alle Spalten verrutschen je Leerzeichen um eine Spalte weiter.

Weiss jemand woran das liegt ? Kann im Code keine Prüfung auf Leerzeichen feststellen.

KUBA


napsterforever - Fr 07.08.09 23:27

habe das gleiche Problem, jedoch keine Ahnung wie ich es lösen kann!
Kann jmd helfen?


jaenicke - Sa 08.08.09 05:55

Einfach nach dem Setzen von Delimiter in Zeile 72 diese Zeile einfügen:

Delphi-Quelltext
1:
  TextFile2.StrictDelimiter := True;                    


napsterforever - Sa 08.08.09 14:40

das kennt er nicht?

[Fehler] ListViewEdit.pas(64): Undefinierter Bezeichner: 'StrictDelimiter'

Wird wohl an meine Delphi Version liegen, gibt es noch eine andere Möglichkeit?


jaenicke - Sa 08.08.09 14:56

Was hast du denn für eine alte Delphiversion?

Entweder holst du dir eine etwas aktuellere Version wie Turbo Delphi [http://www.delphi-library.de/viewtopic.php?p=539975] oder du musst es eben manuell umschreiben. Dazu habe ich aber wenig Lust, da es ja in aktuellen Delphiversionen wohl klappt.


napsterforever - Sa 08.08.09 15:36

Borland Delphi 7 Personal


jaenicke - Sa 08.08.09 16:00

Dann musst du den Quelltext eben entsprechend manuell ändern, wenn du diese Version unbedingt nutzen willst / musst. :nixweiss:
Beispiel:
Alle Leerzeichen durch Platzhalter ersetzen und beim Laden umgekehrt.
Oder das ganze direkt selbst machen ohne die Delimiter von StringLists als Hilfe.


ElTonno - Do 10.09.09 21:30

hei leute,
versuche auch schon seit std. ein Listview mit ner txt datei voll zu kriegen.
Speichern tut er die auch aber nich laden.



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Button2Click(Sender: TObject);
var
   i:integer;
   S:TStringList;
 begin
   S := TStringList.Create;
   for i := 0 to ListView1.Items.Count-1 do
   S.Add('"'+ ListView1.Items[i].Caption +'",'+ ListView1.Items[i].SubItems.CommaText);
   S.SaveToFile('stunden.txt');
   S.Free;
end;

end.


jaenicke - Do 10.09.09 21:32

Ich sehe auch keinen Code, mit dem du das Laden versucht hättest, von alleine kann es ja nicht gehen. :nixweiss:


ElTonno - Mo 21.09.09 23:48


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
   i:integer;
   S:TStringList;
begin
   OD.Execute; // OD = OpenDialog
   S := TStringList.Create;
   for i := 0 to ListView1.Items.Count-1 do
   S.Add('"'+ ListView1.Items[i].Caption +'",'+ ListView1.Items[i].SubItems.CommaText);
   S.LoadFromFile(OD.FileName);
   S.Free;


sry, falsch gepostet. Hab das mit speichern was super funzt. Woran kann es liegen das er das nicht lädt???
Hab es auch schon mit Stream und assign probiert nix funzt.
Für ne hilfe wär ich sehr dankbar.


jaenicke - Di 22.09.09 00:22

Sorry, wenn ich das jetzt so direkt sage, aber hast du eigentlich auch nur eine Sekunde überlegt was du da tust?

Ich fasse einmal zusammen was du da versuchst:
Du führst einen Öffnen-Dialog aus. Ignorierst dabei, ob der Benutzer den abbricht und gar nichts auswählt.
Dann gehst du alle Einträge der ListView durch (sind da vor dem Laden denn welche?) und packst die in die StringList?!?
Jetzt überschreibst du die, indem du die evtl. ausgewählte Datei in die StringListe lädst.
Und statt dann erst einmal mit dem geladenen Inhalt der Datei etwas zu machen, entfernst du den Inhalt direkt wieder aus dem Speicher...

Um es ganz deutlich zu sagen:
Es bringt nichts, wenn du herumrätst und nicht überlegst was du eigentlich tust. Dann lass das Programmieren lieber ganz...