![]() |
String Grid speichern nur mit Fehler
Hallo Zusammen
Ich bin schon länger auf der Suche nach einem Code eine StringGrid abzuspeichern und wieder genau so einzulesen. Leider gelingt mir das nicht mehr. In meiner Stinggrid werden auch drei Memos eingetragen wo vermutlich auch das Problem passiert, da nach dem Memo immer min. ein Absatz existiert
Delphi-Quellcode:
Hat jemand eine Idee wie man das Grid genau so lesen kann wie es gespeichert wird ?.
procedure TForm2.BitBtn5Click(Sender: TObject);
var F: TStringList; x1,y1: Integer; begin F := TStringList.Create; SaveDialog1.Filter := 'Datenbank (*.dbs)|*.DBS'; if savedialog1.Execute then begin; try //F.Add(IntToStr(StringGrid1.RowCount)); //F.Add(IntToStr(StringGrid1.ColCount)); for y1 := 1 to 500 do begin; for x1 := 1 to 70 do begin; F.Add(StringGrid1.cells[x1,y1]); end; end; F.SaveToFile(savedialog1.FileName+'.dbs'); finally F.Free; end; end; end; procedure TForm2.BitBtn6Click(Sender: TObject); var F: TStringList; x1,y1,a: Integer; begin OpenDialog1.Filter := 'Datenbank (*.dbs)|*.DBS'; if Opendialog1.Execute then begin; a:=0; F := TStringList.Create; try F.LoadFromFile(opendialog1.FileName); for y1 := 1 to 500 do begin; for x1 := 1 to 70 do begin; a:=a+1; StringGrid1.cells[x1,y1]:= F.Strings[a-1]; end; end; finally F.Free; end; end; end; Grüße Thomas |
AW: String Grid speichern nur mit Fehler
Schau Dir mal die Eigenschaft vom Stringgrid : Delmiter bzw. die Methode DelimitedText an :-)
|
AW: String Grid speichern nur mit Fehler
Hallo und Willkommen hier...:dp:
Der Kardinalfehler deines Vorhabens sind (u.a.): 1. Visuelle Komponenten zur Datenhaltung zu benutzen. :zwinker: 2. ein Text Format zur Speicherung zu nutzen. XML als "Datenbank" zu benutzen ist OK durch die Struktur und Erweiterbarkeit. (PS: ich stehe auf richtige Datenbanken. Es kommt immer auf die Menge an Daten an :wink:) 3. Wenn dir die Optik deiner Oberfläche nicht mehr gefällt und du die Spalten anders anordnest, passen die Daten nicht mehr. Tipps: 1. Trennung in Oberfläche, Logic, Daten -> Form mit Stringgrid - Logic lädt die Daten - Logic übergibt der Form die Daten zum Darstellen -> Speicherung1: die Logic liest das Grid aus - überträgt das in z.B. XML - Speicherung in Datei -> Speicherung2: die Logic bekommt den aktuell geänderten Wert der Zelle - überträgt das direkt in z.B. XML -> Speicherung in Datei nach Wunsch direkt oder komplett 2. ein geeignetes Dateiformat (für zukünftige Änderungen, imho kein Binärformat) 3. Bitte den Quellcode ordentlich formatieren. Dann ist es besser für Andere zu lesen. Es hilft dir ob z.B. die begin/end zusammenpassen wenn sie untereinander stehen. :zwinker: zur Frage: Vieleicht kannst du mal anhängen was du erwartest. (Bild vor Speicherung, die Datei, Bild nach dem Einlesen) :wink: Im ersten Durchlauf:
Delphi-Quellcode:
...sollte eigentlich passen. :gruebel: Aber nur mit einzeiligen Werten. Sonst stimmt evt. der Index nicht. Deshalb das Muster der Datei...:wink:
a := 0; // A = 0
F := TStringList.Create; try F.LoadFromFile(opendialog1.FileName); for y1 := 1 to 500 do begin for x1 := 1 to 70 do begin a := a + 1; // A = 1 StringGrid1.cells[x1,y1] := F.Strings[a - 1]; // Index = 0 end; end; Zitat:
|
AW: String Grid speichern nur mit Fehler
Hallo
Entschuldigung das ich mich erst jetzt melde. Liege mit Corona flach und kann mich derzeit nicht immer aufraffen am Project weiter zu wurschteln. Ich benutze die Stringgrid (die nicht sichtbar ist) zum Datenspeichern. Bisher hatte ich nie Probleme da ich ja keine Memofelder reinbastelte. Das Project dient nur einem, mir selbst. Es ist ohne weiterem Nutzen. Eine Datenbank wollte ich nicht, was vermutlich einfacher geht (Zumindest aus meiner Erinnerung heraus), aber was auch schlechte Eigenschaften hervorruft wenn jene auch mal kaputt geht. Wir arbeiten hauptsächlich mit Datenbanken berufsbezogen, und es kommt nicht selten vor das es eine verhacktstückelt (Access). Ein reines Textfile kann ich händisch wieder reparieren. Wenn ich das nun richtig verstehe, geht es so einfach nicht. Ich werde jetzt mal versuchen jeden Datensatz mit einer Soderzeichencombi zu trennen, und hoffen das ich es wieder zusammenbekomme. Grüße Thomas |
AW: String Grid speichern nur mit Fehler
Liste der Anhänge anzeigen (Anzahl: 1)
Anbei mal die Oberfläche
|
AW: String Grid speichern nur mit Fehler
Ich versuche nun immer zwischen den Feldern ein Absatzzeichen einzufügen, um es danach wieder besser aufzusplitten.
Delphi-Quellcode:
var
F: TStringList; x1,y1: Integer; begin F := TStringList.Create; SaveDialog1.Filter := 'Datenbank (*.dbs)|*.DBS'; if savedialog1.Execute then begin; try //F.Add(IntToStr(StringGrid1.RowCount)); //F.Add(IntToStr(StringGrid1.ColCount)); for y1 := 1 to 500 do begin; for x1 := 1 to 70 do begin; F.Add(StringGrid1.cells[x1,y1]); F.Add('#Q#Q'); end; end; F.SaveToFile(savedialog1.FileName+'.dbs'); finally F.Free; end; end; end; |
AW: String Grid speichern nur mit Fehler
PS, da es wie eine Datenbank klingt (dbs),
warum dann nicht "wirklich" Eine benutzen? * z.B. SQLite via TSQLQuery bzw. TFDQuery * oder TLocalSQL oder TDataSetProvider gegen eine Objekt/Record-Liste * oder einfach TClientDataSet bzw. TSimpleDataSet (die kennen auch ein SaveToFile/LoadFromFile) da dran dann normale TDBEdit, TDBComboBox, TDBMemo oder auch ein TDBGrid usw. Und warum überhaupt eine unsichtbare visuelle Komponente, um interne Daten zu speichern? Nicht nur die unnötig komplizierte/datenhungrige/langsame Datenhaltung, sondern dann auch nochmal sinnlos manuell das alles mit den Eingabe-Controls (Edits) zu synchronisieren. :freak: Für sowas nimmt man eben möglivhst passende Datenhaltungs-Komponenten, oder von mit aus auch eine ObjektListe oder verschachtelte StringListen oder z.B. eine TMemIniFile (Row-Index = Section-Name und Col-Index/Name = Value-Name) oder XML, JSON usw. oder ... |
AW: String Grid speichern nur mit Fehler
Zitat:
Ansonsten könnte man ja auch noch 'nen ClientDataSet nutzen, kann damit auch alle datensensitiven Komponenten nutzten. Speichern kann man mit ClientDataSet.SaveToFile und laden mit ClientDataSet.LoadFromFile. ![]() Es geht also auch ohne Datenbank deutlich einfacher als mit 'nem unsichtbaren StringGrid. |
AW: String Grid speichern nur mit Fehler
Moin...8-)
...ein paar Fragen: 1. Zitat:
2. Zitat:
3. Zitat:
4. Zitat:
5. Zitat:
PS: Zitat:
|
AW: String Grid speichern nur mit Fehler
Hallo
Bin ja jetzt vor Gericht ;-) 1. Zitat: Wir arbeiten hauptsächlich mit Datenbanken berufsbezogen Wer ist wir? Die Firma, 20 Entwickler? Es gibt keine Entwickler sondern nur Facharbeiter für Fördertechnik (Elektriker,Mechaniker,Büroleute (Keine Programierer)) 2. Zitat: Das Project dient nur einem, mir selbst Machst du Programmieren hauptberuflich in der Firma? (XE8) Nur für mich, früher mehr für andere aber immer nur so. 3. Zitat: Ein reines Textfile kann ich händisch wieder reparieren ...was ist wenn man nichts reparieren muß? Vernünftige Datenbank oder XML? Wie gesagt ich wollte es einfach mit einem Textfile. 4. Zitat: Anbei mal die Oberfläche ...die Oberfläche repräsentiert EINEN Datensatz? Was ist, wenn zu den Katzen ein Tiger (Spaß ) hinzukommt? Man spricht auch von einer sogenanten Laufkatze. Sie fährt an der Kranbrücke und beinhaltet das Hubwerk oder Hebezeug. 5. Zitat: Ich benutze die Stringgrid (die nicht sichtbar ist) zum Datenspeichern Willst du über den Tellerand schauen und es richtig lernen? Hast du Zeit und den Willen dazu? Ich möchte nur dieses kleine Projekt für mich machen und es dieses Jahr abschließen. Es hat keinen Nutzen sondern dient nur zum Auffrischen meines Kopfes. Besser geht es immer ;-) PS: Zitat: und es kommt nicht selten vor das es eine verhacktstückelt (Access) |
AW: String Grid speichern nur mit Fehler
Hallo Zusammen
Weis jemand wie ich die Strings wieder untereinander ins Memofeld bekomme ? Danke im Vorfeld. Einzelne Zeilen gehen gut. nur das aneinanderreihen von Memozeilen geht warum auch immer nicht. Grüße von der schwäbischen Alb.
Delphi-Quellcode:
procedure TForm2.BitBtn6Click(Sender: TObject);
var F: TStringList; x1,y1,a,ie: Integer; strV: string; begin OpenDialog1.Filter := 'Datenbank (*.dbs)|*.DBS'; if Opendialog1.Execute then begin; strV:=''; a:=-1; F := TStringList.Create; try F.LoadFromFile(opendialog1.FileName); for y1 := 1 to 499 do begin; for x1 := 1 to 70 do begin; a:=a+1; edit28.text:=inttostr(a); repeat strV:=strV+F.Strings[a]; a:=a+1; until F.Strings[a]='#Q#Q'; stringgrid1.cells[x1,y1]:= strV ; strV:=''; end; end; finally F.Free; end; end; end; |
AW: String Grid speichern nur mit Fehler
Moin,
so wie du das machst (StringGrid zum Datenspeichern) habe ich vor kurzen auch noch gemacht. Ich selber speichere meine Daten immer noch (meistens) in CSV-Dateien auf der Platte. Das einzige was ich jetzt anders mache ich das ich die Daten selber in TStringList vorhalte und dafür eine paar Routinen habe mit denen ich eine CSV-Liste bearbeiten kann. Wenn wie bei dir das einfach mit den Mitteln löschen soll die man kennt und nicht groß was neu lernen will dann würde ich wahrscheinlich für die Memos eine separate Textdatei machen bei der die erste Zeile eines Absatzes der Verweis auf den eigentlichen Datensatz ist. Wie gesagt, das geht 1000mal besser, sicherer, moderner … aber um das ganze neue zu lernen muss man auch erst einmal die Nerven und die Zeit dafür haben. Gruß Hans |
AW: String Grid speichern nur mit Fehler
Ich glaube Du kannst "Memo" Einträge nicht mit TStrings.SavetoFile und TStrings.LoadfromFile abspeichern und wieder zurück laden.
LoadFromFile benutzt
Code:
als trennzeichen und
#13#10
Code:
als QuoteChar und
"
beide können in einem Memo in verschiedensten Kombinationen auftreten. Es kann helfen, wenn du vor dem Speichern die Strings ersetzt die dein Speicherformat durcheinander bringen.
Delphi-Quellcode:
Und dann nach dem Einlesen auf alle Gitterzellen AStrings.Add(Replace(Zelle, Astrings.Linebreak, '~newline~', [rfReplaceAll] );
Delphi-Quellcode:
Zelle := Replace(Zelle,'~newline~', Astrings.Linebreak, [rfReplaceAll] );
Andernfalls hilft nur ein Dateiformat das NICHT das TStrings dateiformat ist. TiniFile z.b. könnte helfen. Und ist auch humanreadable. |
AW: String Grid speichern nur mit Fehler
Hallo Ihr Zwei
Vielen lieben Dank für eure Antworten. Hier muß ich mal nochmal in mich gehen und probieren was noch möglich ist. Es ist eigentlich der letzte große Posten. Ob ich mich mal etwas tiefer in die Programmierung einarbeiten soll, das sagt mir die Zeit. Habe ja auch noch mein Haus zu richten. Aber Programmieren macht halt auch Spaß und hält das Hirn fit. Probiere mal eure ansätze durch und gebe Bescheid. Grüße und Danke Thomas |
AW: String Grid speichern nur mit Fehler
Du musst vor dem Speichern, im Memo-Text CR/LF (#13#10) mit etwas anderem ersetzen (siehe z.B. Post von QuickAndDirty). Beim Laden machst du das umgekehrte und wandelst die Zeichenfolge, die du für CR/LF genutzt hast, wieder in die richtige CR/LF (#13#10) Zeichenfolge um.
|
AW: String Grid speichern nur mit Fehler
Meine derzeitige Lösung sieht so aus:
Der Vorgang geht natürlich zu lange, was die Progessbar auch anzeigt, da es sich auch um 35000 Einträge handelt. Wartezeit beim Laden sind ca 3 Sekunden. Ist nicht Super aber ich hatte auch nichts erwartet. Zum Darstellen habe ich mir eine Memo4 unsichtbar auf das Formfeld geholt und von dort aus wieder eingelesen. Ich lege das hier mal ab als Beispiel wie man es nicht macht ;-)
Delphi-Quellcode:
var F: TStringList; x1,y1,a,ie,bV,aha,z: Integer; strV: string; begin OpenDialog1.Filter := 'Datenbank (*.dbs)|*.DBS'; if Opendialog1.Execute then begin; strV:=''; a:=-1; F := TStringList.Create; try F.LoadFromFile(opendialog1.FileName); for y1 := 1 to 500 do begin; progressbar1.Position:=Y1; for x1 := 1 to 70 do begin; a:=a+1; edit28.text:=inttostr(a); bv:=1; memo4.Lines.Clear; repeat strV:=strV+F.Strings[a]; memo4.Lines.add (F.Strings[a]); bv:=bv+1; a:=a+1; until F.Strings[a]='#Q#Q'; if bv >2 then stringgrid1.Cells[x1,y1]:=memo4.text else stringgrid1.cells[x1,y1]:= strV ; strV:=''; end; end; finally F.Free; end; end; progressbar1.Position:=0; |
AW: String Grid speichern nur mit Fehler
Für was brauchst du eigentlich das Memo? Zeigst du damit irgendwas an oder ist das nur für diese Routine? Was du damit in deinem Code machst, ist unsinnig und sehr langsam. Dann hast du vermutlich nicht verstanden, was wir mit "Ersetzen von CR/LF" genau meinen. Ich nehme an, du hast das mit dem "#Q#Q" versucht zu steuern oder ist das was anderes? Gehe ich richtig der Annahme, dass du da pro Gridzelle eine Zeile im File willst? Das folgende Beispiel basiert auf diese Annahme.
Du weisst sicher in welchen Spalen dein Memo drin ist oder? Dann musst du diese Spalte speziell behandeln wie im foglenden Beispiel. Beim Speicher musst du genau das umgekehrte machen. Aber achtung dieer Ansatz ist generell sehr schlecht und du wirst grosse Probleme bekommen, wenn das dein Grid mal eine anderen Aufbau bekommen soll. Dann passen deine Dateien nicht mehr zum Grid und sind wertlos. Hier mal ein Beispiel wie du es sinnvoler machen kannst:
Delphi-Quellcode:
procedure LoadData;
var F: TStringList; x1,y1,a: Integer; strCell: string; begin OpenDialog1.Filter := 'Datenbank (*.dbs)|*.DBS'; if Opendialog1.Execute then begin; strV:=''; a:=-1; F := TStringList.Create; try F.LoadFromFile(opendialog1.FileName); for y1 := 1 to 500 do begin; progressbar1.Position:=y1; for x1 := 1 to 70 do begin; a:=a+1; edit28.text:=inttostr(a); strCell := F.Strings[a]; { In Spalte 50 soll das Memo rein. Die Zeilen (Spalten), die wir beim Speichern von #13#10 (CR/LF) in '#13#10' (String) umgewandelt haben, müssen nun wieder in korrektet CR/LF zurückgewandelt werden. } if x1 = 50 then strCell := StringReplace(strCell, '#13#10', #13#10, [rfReplaceAll]); stringgrid1.cells[x1,y1]:= strCell; end; end; finally F.Free; end; end; progressbar1.Position:=0; end; Beim Speichern der Datei müsstest du die mehrzeiligen Zellen (hier im Beispiel Spalte 50) wie folgt umwandeln, damit das Laden richtig funktioniert:
Delphi-Quellcode:
{ Beim Speichern der Spalte 50, müssen Zeilenumbruche (CR/LF) in Stringkonstanten umgewandelt werden }
strCell := stringgrid1.cells[x1,y1]; if x1 = 50 then strCell := StringReplace(strCell, #13#10, '#13#10', [rfReplaceAll]); ... |
AW: String Grid speichern nur mit Fehler
Zitat:
35 TAUSEND Einträge. Datenbank. Punkt. Alles andere ist Irrsinn bei der Menge an Daten, egal ob privates Spielprojekt oder nicht! Für kleine Projekte wo man nur eine Tabelle braucht nehme ich gerne eine Memtable. CSV zum speichern und laden. Macht die Memtable (KbmMemtable) selber. Für alles andere gibt es sicher schöne schlanke embedded Lösungen. Ich habe bisher Absolute Database verwendet, das ist aber wohl vorbei das ist mir jetzt zu teuer! |
AW: String Grid speichern nur mit Fehler
Für ihn ist jede Gridzelle ein Datensatz, was natürlich Quatsch ist. Sein Grid hat 35'000 Zellen (500 Zeilen X 70 Spalten).
|
AW: String Grid speichern nur mit Fehler
Das TStringGrid ist dann intern auch mehrere StringListen, also pro Zeile eine TStringList und je Column Cell ein String.
Auch wenn es hier zum Glück "aktuell" geht, so ist es mit mehreren "Zeilen" je Cell (ListenZeile) eher als problematisch anzusehen. Hier gleich mal ein gutes Beispiel, dass der Unterschied zwischen Daten-Komponente und GUI-Komponente schnell relevant sein kann. Also TMemo (Memo.Lines = TMemoStrings) versus TStringList : * das Memo speichert eigentlich alles in einem Stream ... also quasi in .Text, was "ein" String ist * übergibt man einem Lines[i] einen mehrzeiligen String, dann * * wird das in mehrere Zeilen aufgetrennt (nachfolgende Zeilen verschieben sich) * * man muß aufpassen welche Zeilenumbrüche man benutzt, denn #13#10, #10 und #13, aka CRLF, LF und CR, werden vom Memo unterschiedlich behandelt * * ändert man eine Line (egal ob mehrzeilig oder nicht), wird der komplette Stream und womöglich auch die ganze Speicherverwaltung umgeschrieben, wenn sich der gesamte Stream/String sich ändert * * und bei vielen Zeilen / größeren Änderungen wird das TMemo extrem unperformant * bei der TStringList dagegen ist/bleibt jede Line ein eigener String, auch wenn Mehrzeiliges zugewiesen wird. * aber beim Zugriff .Text wird dann alles wieder zu einem String und die Lines trennen sich auf, vor allem auch beim SaveToFile/LoadFromFile |
AW: String Grid speichern nur mit Fehler
Zitat:
Es würde sich trotzdem lohnen auf eine Memorytable / ClientDataset. Schon alleine der 70 Spalten wegen die aktuelle alle mit einem Index angesprochen werden. Da mal was hinzuzufügen oder zu entfernen macht keinen spass. Außerdem sind richtige Datentypen viel schöner als alles in Strings und dauernd zu konvertieren. Und wenn man mal suchen oder filtern muss, wozu soll man sich die Mühe machen um alles selber zu implementieren? |
AW: String Grid speichern nur mit Fehler
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Jungs
Erst einmal vielen lieben Dank für Eure Hilfestellungen. Wie ich bereits geschrieben habe ist das was ich gemacht habe nicht zur Nachahmung gedacht gewesen. Meine Idee war einfach ein bischen das Gehirn in Wallung zu bringen. Das das was ich gemacht habe schon beim programmieren mich selbst zum zweifeln gebracht hat lass ich mal außen vor. Meine Maske ist im Anhang: Unsere Maske in der Firma mit Access sieht ähnlich aus jedoch nur mit einem Hubwerk (Lauf-Katze). Etwa 5 % der Anlagen habe aber zwei oder mehr "Katzen". Mein Nachbar ist von Beruf Programmierer und hatte auch einen anderen Ansatz. Für mich jedoch wichtig war das ich den Code möglichst alleine erstellt bekomme. Was Gott sei Dank auch gelang. Der Code ist allerdings sehr sehr schlecht, was ein weiterführen unsinig macht. Aber es geht. Mich hat es gefreut das ich es hinbekommen habe trotz meines Stroke vor etwa vier Jahren. Nun jedoch nochmal den Nachtrag : Es sind 500 Datensätze mit maximal 70 Einträge. Dies ist nicht ungewöhnlich viel. Eine Firma die ich viel betreue hat knapp über 300 Krananlagen. Eine Firma wo ich immer mal wieder arbeite hat über 1400 Krananlagen. Also die Zahl von 500 ist nicht weit hergeholt. Jedoch habe ich nun eine Frage an Euch : 1. Kann ich mit Delphi XE8 Datenbankanwendungen schreiben ohne das ich die Datenbank selbst auf dem Rechner installiert habe (Access ....)? 2. Kann ich diese Datenbank auch auf einem Handy oder Tablet benutzen ? 3. Kann man mit XE8 auch Handy oder Tablet Anwendungen schreiben? 4. Ist es mit der derzeit Kostenlosen und freien Version Möglich so etwas zu machen (Datenbank,Handy und Tablet Version) ? Nun wünsche ich Euch ein schönes Weihnachtsfest und ein paar schöne Tage mit Euren Liebsten. Grüße Thomas PS: Danke für die Hilfe und auch der Kritik |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz