Autor |
Beitrag |
hRb
Beiträge: 269
Erhaltene Danke: 12
|
Verfasst: Fr 11.11.22 21:43
|
|
ub60
Beiträge: 762
Erhaltene Danke: 127
|
Verfasst: Fr 11.11.22 23:00
Vielleicht einfach selber schreiben (ohne DelimitedText):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure SaveGrid(StringGrid1: TStringGrid; fileName: string); var iRow, iCol: integer; sl: TStringList; s: String; begin try sl := TStringList.Create; for iRow := 0 to StringGrid1.RowCount - 1 do begin s:=StringGrid1.Cells[0, iRow]; for iCol := 1 to StringGrid1.ColCount - 1 do s:=s+'|'+StringGrid1.Cells[iCol, iRow]; sl.Add(s); end; sl.SaveToFile(fileName); finally sl.Free; end; end; |
ub60
|
|
hRb
Beiträge: 269
Erhaltene Danke: 12
|
Verfasst: Fr 11.11.22 23:57
Ja, das ist natürlich möglich. Aber man speichert nicht, wenn nicht auch wieder gelesen werden soll und da ist die "automatische Trennzeichen-Auswertung" schon elegant. Siehe unten
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure LoadFromFile(StringGrid1: TStringGrid; txt: TFileName); var sRows, sCols: TStrings; i: Integer; begin sRows := TStringList.Create; sRows.LoadFromFile(txt); sCols := TStringList.Create; sCols.CommaText := sRows[0]; StringGrid1.ColCount := sCols.Count; sCols.Free; StringGrid1.RowCount := sRows.Count; for i := 0 to Pred(sRows.Count) do StringGrid1.Rows[i].CommaText := sRows[i]; sRows.Free; end; |
also ganz einfach:
Delphi-Quelltext 1:
| StringGrid1.Rows[i].CommaText := sRows[i]; |
Deshalb auch hier die Frage: wie? (für mich als Nichtprofi auch zusätzlich ein Punkt zum weiteren Lernen)
|
|
Th69
Beiträge: 4784
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Sa 12.11.22 09:08
Hallo,
die Eigenschaft heißt Delimiter - lies dir auch die Beschreibung zu DelimitedText durch.
|
|
hRb
Beiträge: 269
Erhaltene Danke: 12
|
Verfasst: So 13.11.22 01:33
Danke, Th69
Diese Beschreibung habe ich auch vorab gelesen. Unter DelimitedText steht jedoch nur, dass DelimitedText ein Wert zuzuweisen sei. Ein Beispiel fehlt!
Ich dachte, dass anstelle CommaText, einfach die von mir auskommentierte Zeile zu schreiben wäre.
Unter QuoteChar finde ich folgendes Beispiel:
Delphi-Quelltext 1:
| MyStringList.QuoteChar := #0; |
bei mir also
Delphi-Quelltext
wird vom Compiler angenommen. Auch die Zeile
Delphi-Quelltext 1:
| sx.Add(StringGrid1.Rows[iRow].Delimitedtext; |
also hier nochmals
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure SaveGrid(StringGrid1: TStringGrid; fileName: string); var iRow: integer; sx: TStringList; begin try sx := TStringList.Create; sx.QuoteChar := '|'; for iRow := 0 to StringGrid1.RowCount - 1 do sx.Add(StringGrid1.Rows[iRow].Delimitedtext); sx.SaveToFile(fileName); finally sx.Free; end; end; |
Das Ergebnis beim Trennzeichen ist aber nach wie vor das Komma.
Die weiteren Seiten in der Hilfe zum Thema habe ich alle gelesen: jedoch ohne lauffähiges Beispiel. Hat mir alles nicht geholfen.
Daher nochmals nachgefragt: Wie ändere ich den Delimiter?
Moderiert von Th69: URL-Titel hinzugefügt
|
|
Th69
Beiträge: 4784
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: So 13.11.22 07:48
Du weißt doch wie man Eigenschaften setzt:
Delphi-Quelltext 1:
| MyStringList.Delimiter := '|'; |
Bei dir also (vor dem Add):
Delphi-Quelltext 1:
| StringGrid1.Rows[iRow].Delimiter := '|'; |
PS: QuoteChar ist für das zusätzliche Setzen in Anführungszeichen (oder andere Zeichen), d.h. vor und nach jedem Eintrag. Dies wäre also eine andere Alternative, um Kommas in Texten abzuspeichern und wieder korrekt zu lesen (s.a. CommaText), d.h. dein ursprünglicher Code müßte einwandfrei (auch mit Kommas) funktionieren.
|
|
Sinspin
Beiträge: 1332
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Mo 14.11.22 13:09
Hey,
dank Th69 seiner guten Vorarbeit sollte alles zusammen dann etwa so aussehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure SaveGrid(StringGrid1: TStringGrid; fileName: string); var iRow: integer; sl: TStringList; begin try sl := TStringList.Create; for iRow := 0 to StringGrid1.RowCount - 1 do begin StringGrid1.Rows[iRow].DelimitedText := '|'; sl.Add(StringGrid1.Rows[iRow].CommaText); end; sl.SaveToFile(fileName); finally sl.Free; end; end; |
Dabei wird die TStringList "sl" gelassen wie eingestellt.
Vor dem Auslesen der Eigenschaft CommaText, der Zeile des TStringGrid müssen alle Eigenschaften gesetzt sein die CommaText verwendet um den formatierten String zu erzeugen.
Übrigens ist es keine gute Idee "#0" an irgend einer Stelle als Stringtrenner zu verwenden. Das kann(wird) zu lustigen Fehlern führen wenn man sein Programm mal aus der Delphiwelt heraus lässt.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
Th69
Beiträge: 4784
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 14.11.22 14:37
|
|
hRb
Beiträge: 269
Erhaltene Danke: 12
|
Verfasst: Mo 14.11.22 15:25
Also so wie im Beispiel angegeben funktioniert es nicht.
(Habe zunächst Schleifenvariable korrigiert in for j:=cFixRow = 1 to .., da eine Überschriftenzeile. Aber das nur nebenbei)
Meine Stringliste sah vor dem Speichern wie folgt aus (s. Image 4)
Nach der Procedure waren alle Einträge aus meiner Stringliste gelöscht und in Spalte 1 war überall | (s.Image5)
In der Textdatei in die ich die Liste speichere sieht es ähnlich aus:
Quelltext 1: 2: 3: 4: 5: 6:
| |,,,,,,,, |,,,,,,,, |,,,,,,,, |,,,,,,,, |,,,,,,,, |,,,,,,,, |
Anmerkung: Habe mich auch gewundert, dass StringGrid1.Rows[iRow].DelimitedText := '|'; innerhalb der Schleife und vor jedem Add steht und dann doch
Moderiert von Th69: Delphi-Tags hinzugefügt
Einloggen, um Attachments anzusehen!
|
|
hRb
Beiträge: 269
Erhaltene Danke: 12
|
Verfasst: Mo 14.11.22 15:27
Oh, jetzt sehe ich gerade den Korrektureintrag von Th69. Werde es testen
|
|
Th69
Beiträge: 4784
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 14.11.22 16:33
Hat es geklappt?
hRb hat folgendes geschrieben : | ... und dann doch |
Da fehlt das Ende des Satzes...
|
|
Sinspin
Beiträge: 1332
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Mo 14.11.22 18:18
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
hRb
Beiträge: 269
Erhaltene Danke: 12
|
Verfasst: Mo 14.11.22 18:37
Sorry, musste Einkaufen. Da wurde wohl ein halbfertiger Text gesendet.
So, in dieser Form funktioniert es:
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:
| procedure SaveGrid(StringGrid1: TStringGrid; fileName: string); var iRow: integer; rowStrings : TStringList; begin try rowStrings := TStringList.Create; for iRow := 1 to StringGrid1.RowCount - 1 do begin StringGrid1.Rows[iRow].Delimiter := '|'; rowStrings.Add(StringGrid1.Rows[iRow].DelimitedText); end; rowStrings.SaveToFile(fileName); finally rowStrings.Free; end; end;
procedure TForm1.BilderlisteSpeichern1Click(Sender: TObject); VAR Dateiname:string; begin if FileSaveDialog1.Execute then begin Dateiname := FileSaveDialog1.FileName; SaveGrid(Stringgrid1,Dateiname); end; end; |
Anmerkung1: Die optimierte Version rowStrings := StringGrid1.Rows[iRow] ; mag der Compiler nicht (Semikolon ist rot unterstrichen)
Anmerkung2: Zitat: | Übrigens ist es keine gute Idee "#0" an irgend einer Stelle als Stringtrenner zu verwenden. |
Da stimme ich zu, aber ich habe den Befehl einfach aus den Beispielen von Embarcadero übernommen.
Danke, Ihr seid schneller als ich. Dafür ist mein Kühlschrank wieder voll
|
|
Th69
Beiträge: 4784
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 14.11.22 18:50
Das würde mich jetzt aber doch interessieren, warum mein anderer Code nicht funktioniert (denn denselben Code mehrfach zu wiederholen, sollte man ja vermeiden). Welche genaue Fehlermeldung gibt es denn beim Kompilieren?
Edit: Sehe jetzt gerade, daß du ja jetzt sl nicht mehr benutzt, sondern stattdessen rowStrings - du brauchst schon 2 verschiedene Variablen dafür.
|
|
hRb
Beiträge: 269
Erhaltene Danke: 12
|
Verfasst: Di 15.11.22 00:40
Die Fehlermeldung lautet: Inkompatible Typen: TStringlist und TStrings
Zitat: | Sehe jetzt gerade, daß du ja jetzt sl nicht mehr benutzt, sondern stattdessen rowStrings - du brauchst schon 2 verschiedene Variablen dafür. |
Die Variable s1 (1=Zahl) wollte ich künftig nicht mehr nutzen. Im Delphi-Editor gibt es leicht Verwechslung mit sl (1=Zahl) und sl (= kleiner Buchstabe L)
2 verschiedene Variablen? Ok, wenn dies optimiert ist!
Läuft jetzt auch so (schwere Geburt, Danke fürs "Mitpressen")
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure SaveGrid(StringGrid1: TStringGrid; fileName: string); var iRow: integer; rowStrings : TStrings; sL:Tstringlist; begin try sL := TStringList.Create; for iRow := 1 to StringGrid1.RowCount - 1 do begin rowStrings := StringGrid1.Rows[iRow]; rowStrings.Delimiter := '|'; sL.Add(rowStrings.DelimitedText); end; sL.SaveToFile(fileName); finally sL.Free; end; end; |
|
|
Th69
Beiträge: 4784
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 15.11.22 09:46
Optimiert in dem Sinne, daß nur einmal (pro Schleifendurchgang) auf das Rows-Array zugegriffen wird (die zusätzliche lokale Variable wird Delphi wohl im Release-Modus als Register benutzen, d.h. keine Stackvariable dafür anlegen) - dies ist zwar laufzeittechnisch nur eine Mikrooptimierung, ich finde den Code aber so schöner zu lesen, so daß je Objekt nur ein Zugriff darauf passiert (bei einer Funktion würde man diese ja auch nicht mehrfach aufrufen).
|
|