Entwickler-Ecke

Sonstiges (Delphi) - Speichern Button


Speter - So 01.05.11 14:42
Titel: Speichern Button
Hey Leute,

hab ein Fragebogen jetzt erstellt wo Leute Fragen beantworten indem sie auf die Radiobuttons klicken.
Jetzt wollte ich einen Button "Speichern"
Sprich die Ergebnisse werden in einer Datei abgelegt und gespeichert.
Könnt ihr mir sagen wie man sowas genau macht?

Mit freundlichen Grüßen


trm - So 01.05.11 15:04

Hallo.

Ich gehe einfach mal davon aus, dass Du einzelne Radiobuttons 'durchläufst'.

Die Frage ist nun, wie das Ergebnis gespeichert werden soll.

1. Lesbar als Textdatei z.B., als Klartext der Antworten
2. Nicht lesbar, in spezifischen Werten (gut für anonyme Datensammlungen)

1. Die einfachste Möglichkeit am Anfang ist eine TMemo-Komponente, in welcher Du die Ergbnisse Zeilenweise als String einträgst. Der Vorteil ist, dass Du siehst, was da passiert. Speichern kannst Du dann direkt über das Memo ( Memo1.savetofile('dateiname.txt'); )


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
// Schreiben:

function booltostring(dummy_bool:boolean):String;
begin
case dummy_bool of
true: result:=' Markiert';
false: result:=''
end;
end;

var
dummy_string:String;
begin
dummy_string:=Radiobutton1.Caption;
dummy_string:=dummy_string+': '+booltostring(Radiobutton1.checked);
memo1.lines.add(dummy_string);
memo1.savetofile('dateiname.txt');
end;



2. Hier ist die einfachste Möglichkeit eine IniFile-Instanz.


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:
[..]
uses inifiles;
[..]

// Schreiben:

var
dummy_inifile:tinifile;
begin
dummy_inifile:=tinifile.create('dateiname.ini');
dummy_inifile.writeboolean('Inifile_section','radiobutton1',radiobutton1.checked);
dummy_inifile.free;
end;

// Lesen:

var
dummy_inifile:tinifile;
begin
dummy_inifile:=tinifile.create('dateiname.ini');
radiobutton1.checked:=dummy_inifile.readboolean('Inifile_section','radiobutton1',false);
dummy_inifile.free;
end;


Die aufgezeigten Möglichkeiten sind nur Beispiele, das erste ist ein Weg, der für Dein Beispiel nicht praktibale ist, aber einen Lerneffekt verursacht :)

Andere Möglichkeiten sind Streams, aber für den Anfang ist dies zu kompliziert.
Eine weitere Möglichkeit ist die Benutzung von TStringList.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
dummy_stringlist:TStringlist;
begin
dummy_Stringlist:=Tstringlist.create;
// Hier analoges Arbeiten zum TMemo, außer, dass statt lines direkt in die Items der Liste eingetragen wird:
dummy_stringlist.items.add('ein string');
//speichern wieder direkt per Stringlistinstanz:
dummy_Stringlist.savetofile('dateiname.txt');
dummy_Stringlist.free;


In der Delphihilfe findest Du weitere Erklärungen :)

Viel Erfolg, viele Grüße
~Mathias

Edit: Syntaxfehler gefunden (glaube ich)


Speter - So 01.05.11 15:10

Hey viele dank :)
die Datei soll als .csv Datei gespeichert werden.
ist das überhaupt möglich?


trm - So 01.05.11 15:15

Ja, das ist möglich :)


Andreas L. - So 01.05.11 15:43

@trm: Es ist ja schön das du Speter gleich so umfangreich geholfen hast, macht ja nicht jeder :zustimm: Aber trotzdem wäre es schön wenn du es Ihm auch gleich richtig zeigst (Ressourcenschutzblöcke, Absolute Dateinamen, ordentliche Formatierung). Er scheint Anfänger zu sein, und mit dem Code wird er früher oder später teils merkwürdige Probleme bekommen.

@Speter:

Die einfachste Möglichkeit:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.Button1Click(Sender: TObject);
var
  sl: TStrings;
begin
  sl := TStringList.Create;
  try
    sl.add('Eine Zeile hinzufügen');
    sl.add('Noch eine Zeile...');

    // Immer kompletten Pfad angeben, niemals relativ. Dateien am Besten im Anwendungsdaten-Ordner speichern (Suchbegriff im Forum: GetShellFolder, SHGetSpecialFolderLocation, ...)
    sl.SaveToFile('D:\Ordner\Datei.dat');
  finally
    sl.Free;
  end;
end;


Wenns dann zur Veranschaulichung in einem Memo ausgegeben werden soll, reicht noch folgendes:

Delphi-Quelltext
1:
2:
3:
  ...
  Memo1.Text := sl.text;
  ...


Besser für dein Problem geeignet sind aber Ini-Dateien:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
var
  ini: TMemIniFile;
begin
  // Wieder kompletten Pfad angeben!
  ini := TMemIniFile.Create('C:\Datei.ini');
  try
    // String schreiben
    ini.writeString('Sektion''Schlüssel''Wert');

    // Boolean schreiben (geeignet für einen RadioButton)
    ini.writeBool('Sektion''RadioButton1', RadioButton1.Checked); 

    // Auslesen geht analog dazu ( s ist ein String)
    s := ini.readString('Sektion''Schlüssel''defaultWert');
  finally
    ini.Free;
  end;
end;


CSV-Dateien könnte man natürlich dazu auch nutzen. Schreiben ist auch kein Problem. Aber zum Laden wirst du die Datei entweder parsen müssen oder eine fertige Bibliothek verwenden. Ist für einen Anfänger sicher nicht ganz trivial. Ich würde an deiner Stelle vorerst bei den Inis bleiben.


Speter - So 01.05.11 20:52

hey wow vielen dank :)


---Moderiert von user profile iconNarses: Beiträge zusammengefasst---


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var
ini: TMemInifile;
begin
ini := TmemInifile.Create('C:\Datei.ini');
try
  ini.WriteString('Sektion''Schlüssel''Wert');
  ini.writeBool('Sektion''RadioGroup', RadioGroup1.checked);
  s := ini.readString('Sektion''Schlüssel''defaultWert');
  finally
    ini.Free;
    end;
end.

so sieht das bei mir grad aus
aber checked kennt der bei mir nicht
Unidentifizierter Bezeichner: Checked
und muss ich den in der Mitte wo Radiogroup steht 10 mal einfügen?
weil ich hab 10 groups die zu 10 Fragen passen

Mit freundlichen Grüßen

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


jaenicke - So 01.05.11 20:56

user profile iconSpeter hat folgendes geschrieben Zum zitierten Posting springen:
ini.writeBool('Sektion', 'RadioGroup', RadioGroup1.checked);
[...]
aber checked kennt der bei mir nicht
Du hast ja auch eine RadioGroup und keinen RadioButton...
Dort gibt es ItemIndex, das den aktuell ausgewählten Eintrag angibt. Funktioniert bei dir die Hilfe nicht? :gruebel:


Speter - So 01.05.11 23:13


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:
unit Unit1;

interface

uses
  Windows, Messages, Inifiles, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Ueberschrift: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label7: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Speichern: TButton;
    Ende: TButton;
    RadioGroup1: TRadioGroup;
    RadioGroup2: TRadioGroup;
    RadioGroup3: TRadioGroup;
    Label6: TLabel;
    Label8: TLabel;
    RadioGroup4: TRadioGroup;
    RadioGroup5: TRadioGroup;
    RadioGroup6: TRadioGroup;
    RadioGroup7: TRadioGroup;
    RadioGroup8: TRadioGroup;
    RadioGroup9: TRadioGroup;
    RadioGroup10: TRadioGroup;
    procedure EndeClick(Sender: TObject);
    procedure SpeichernClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.EndeClick(Sender: TObject);
begin
close
end;

procedure TForm1.SpeichernClick(Sender: TObject);

var
dummy_inifile:tinifile;
begin
dummy_inifile:=tinifile.create('Auswertung.ini');
dummy_inifile.writeboolean('Inifile_section','radiogroup1',radiogroup1.ItemIndex);
dummy_inifile.free;
end;

// Lesen:

var
dummy_inifile:tinifile;
begin
dummy_inifile:=tinifile.create('dateiname.ini');
radiogroup1.checked:=dummy_inifile.readboolean('Inifile_section','radiogroup1',false);
dummy_inifile.free;
end;

das ist der code den ich im moment habe
Zitat:
[Fehler] Unit1.pas(63): Undefinierter Bezeichner: 'write'
[Fehler] Unit1.pas(63): ')' erwartet, aber ',' gefunden
[Fehler] Unit1.pas(73): Undefinierter Bezeichner: 'radiogroup1'
[Fehler] Unit1.pas(73): Operator oder Semikolon fehlt
[Fehler] Unit1.pas(73): Undefinierter Bezeichner: 'readboolean'
[Fehler] Unit1.pas(75): '.' erwartet, aber ';' gefunden
[Fataler Fehler] Project1.dpr(5): Verwendete Unit 'Unit1.pas' kann nicht compiliert werden

ich check das einfach nicht :D
sry leute das ich so blöde fragen stelle aber bin dabei zu lernen

danke für eure hilfe

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


trm - So 01.05.11 23:43

Den Fehler in Zeile 63 sehe ich nicht.

Aber ein Fehler bei der Speicherung:
Du versuchst einen Zahlenwert (0 - ...) als Ja/Nein zu speichern. Geht so nicht.
Daher:

dummy_inifile.writeboolean('Inifile_section','radiogroup1',radiogroup1.ItemIndex);
in
dummy_inifile.writeinteger('Inifile_section','radiogroup1',radiogroup1.ItemIndex);
ändern und beim Lesen auch:

radiogroup1.checked:=dummy_inifile.readboolean('Inifile_section','radiogroup1',false);
in
radiogroup1.itemindex:=dummy_inifile.readinteger('Inifile_section','radiogroup1',-1);


Das -1 am Ende heißt, dass, wenn in der inidatei noch nichts steht, oder die inidatei noch nicht existiert, keine Auswahl beim Lesen erfolgt.

:)


Speter - Mo 02.05.11 09:00


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:
unit Unit1;

interface

uses
  Windows, Messages, Inifiles, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;



type
  TForm1 = class(TForm)
    Ueberschrift: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label7: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Speichern: TButton;
    Ende: TButton;
    RadioGroup1: TRadioGroup;
    RadioGroup2: TRadioGroup;
    RadioGroup3: TRadioGroup;
    Label6: TLabel;
    Label8: TLabel;
    RadioGroup4: TRadioGroup;
    RadioGroup5: TRadioGroup;
    RadioGroup6: TRadioGroup;
    RadioGroup7: TRadioGroup;
    RadioGroup8: TRadioGroup;
    RadioGroup9: TRadioGroup;
    RadioGroup10: TRadioGroup;
    procedure EndeClick(Sender: TObject);
    procedure SpeichernClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

procedure TForm1.EndeClick(Sender: TObject);
begin
close
end;

procedure TForm1.SpeichernClick(Sender: TObject);

var
dummy_inifile:tinifile;
begin
dummy_inifile:=tinifile.create('Auswertung.ini');
dummy_inifile.writeinteger('Inifile_section','radiogroup1',radiogroup1.ItemIndex);
dummy_inifile.free;
end;

// Lesen:

var
dummy_inifile:tinifile;
begin
dummy_inifile:=tinifile.create('dateiname.ini');
radiogroup1.itemindex:=dummy_inifile.readinteger('Inifile_section','radiogroup1',-1);
dummy_inifile.free;
end;
end.


hab das jetzt so abgeändert es sind nur noch die kleinen Fehler da.

[Fehler] Unit1.pas(73): Undefinierter Bezeichner: 'radiogroup1'
[Fehler] Unit1.pas(73): Operator oder Semikolon fehlt
[Fehler] Unit1.pas(75): '.' erwartet, aber ';' gefunden
[Fataler Fehler] Fragebogen.dpr(5): Verwendete Unit 'Unit1.pas' kann nicht compiliert werden

Hab den rest bis jetzt alles soweit hinbekommen vielen dank leute :)


jaenicke - Mo 02.05.11 11:27

Wie wäre es, wenn du statt // Lesen: als Kommentar zu schreiben den folgenden Quelltext in eine Methode packst? :roll:
Der liegt da einzeln in der Unit, ohne Prozedur oder irgendwas...


Speter - Mo 02.05.11 11:40

Ja das habe ich auch schon gemerkt und jetzt läuft das Formular bis auf das Problem das es mir in die Datei nix reinschreibt.
Also nicht das was ich da angekreuzt habe oder so.
Aber das kriege ich auch noch hin danke leute :)


beastofchaos - Mo 02.05.11 12:34

Also ich kannte diese Möglichkeiten noch nciht, aber sie sind auf jeden Fall schnell und kurz. Ich habe bisher immer alles in einer Text mit einem bestimmten Muster gespeichert. Das Schreiben besteht zwar aus ca. 20 Zeilen, aber es ist wohl die primitivste Art, etwas zu speichern. Wichtig sind dabei diese Sachen:

Eine Variable vom Typ Textfile, eine vom Typ String und ein paar Prozeduren/ Funktionen:


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:
procedure Save(DateiName, Inhalt: String);  // Name ist einfach nur der Name der Datei inklusive Endung
                                            // Inhalt enthält alles, was gespeichert werden soll
var
  F: Textfile; 
  path: string;
begin
  path := ExtractFilePath(Application.ExeName);   // Ermittelt den Pfad der Exe-Datei 
  Assignfile(F, path + DateiName);                // Weißt F diese Datei zu (sie muss aber nicht vorhanden sein)
  if not FileExists(path + DateiName) then         // Wenn die Datei nicht existiert
    Rewrite(F)                                    // Wird sie erstellt und geöffnet zum Beschreiben
  else
    Reset(f);                                     // Öffnet die Datei zum Beschreiben (und Lesen)
  
  WriteLn(Inhalt);                                // Schreibt eine Zeile in die Textdatei mit dem Inhalt
  
  Closefile(f);                                   // Schließt den Prozess ab, da es sont Probleme beim Beenden des Programms gäbe
end;

function Read(DateiName: String): Array of String;
var
  F: Textfile;
  path: string;
  i: Integer;
begin
  path := ExtractFilePath(Application.ExeName);
  Assignfile(F, path + Dateiname);

  if not FileExists(path + Dateiname) then
    ShowMessage('Diese Datei existiert nicht!')

  else
    begin
    // FileMode := fmOpenRead;                      // Nicht notwendig, aber ist, glaub ich, nicht schlecht :P
    Reset(f);
    i := 0;
    while not EoF(F) do                             // Prüft, ob man in der letzten Zeile angelangt ist
      begin
      SetLength(Result, length(Result) + 1);        // Verlängert das dynamische array immer um einen Teil
      ReadLn(F, Result[i]);
      i := i + 1;                                   // bzw. Inc(i)
      end;
    Closefile(f);
    end;

end;



Das wollte ich nur mal kurz so zeigen, um auch eine Variante dafür zu geben.

Zum Öffnen/Lesen/Schreiben von Textdateien gibt es übrigens verschiedene Möglichkeit - Alle erwarten als Parameter ein Textfile:
- Reset(): Ermöglicht alles
- Rewrite(): Gibt zum Schreiben frei, erstellt außerdem die Datei, wenn sie nicht existiert
- Append(): Öffnet zum Schreiben eine Datei - geht dabei ans Ende der Textdatei

Vor Reset kann man folgendes schreiben, um die verschiedenen Möglichkeiten zu geben:
- "fmOpenRead : Read only"
- "fmOpenWrite : Write only"
- "fmOpenReadWrite : Read and write"

Ob das notwendig ist, weiß ich nicht, vorsichtshalber mach ich es aber lieber ;)

Grüße, beast alias Thomas


ALF - Mo 02.05.11 12:37

Und das ganze im CROSSPOST [http://www.delphipraxis.net/160196-speichern-button.html]

Gemeinsam ist man stark :lol:

Gruss ALf