Entwickler-Ecke

Datenbanken - Record anzeigen


Systanas - Di 15.12.09 12:26
Titel: Record anzeigen
Hallo liebe Delphi-Community,
ich soll für unseren Lehrer, der uns Datenbanken über Records anfertigen lässt, eine selbige erstellen.
Ich habe nun das Problem das ich irgendwie auf dem Schlauch stehe und nicht weiß wie ich den gespeicherten Text in das StringGrid ausgeben lasse. Könnt ihr mir helfen damit ich endlich weiter machen kann und mich dann am speichern und laden probieren kann :D .

MfG Sys


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

interface

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

type tVerbund = record
         dkp : Integer;
         Name : String;
         Item : String;
         Boss : String;
          end;
     tFeld = array[0..1000of tVerbund;

  TForm1 = class(TForm)
    Raid1: TStringGrid;
    DSatz: TLabel;
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Raid : tFeld;
  datensatznummer : Integer;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var i : Integer;
begin
   //'Speichern'
  Raid1.Cells[1,0] := 'Name';
  Raid1.Cells[2,0] := 'DKP';
  Raid1.Cells[3,0] := 'Item';
  Raid1.Cells[4,0] := 'Boss';

  FOR i:=1 to 9 DO Raid1.Cells[0,i] := IntToStr(i);
  datensatznummer := 1;
  DSatz.Caption := IntToStr(datensatznummer);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
DSatz.Caption := IntToStr(datensatznummer);

Raid[datensatznummer].Name := Edit1.Text;
Raid[datensatznummer].DKP := StrToInt(Edit2.Text);
Raid[datensatznummer].Item := Edit3.Text;
Raid[datensatznummer].Boss := Edit4.Text;

inc(datensatznummer);
DSatz.Caption := IntToStr(datensatznummer);

Edit1.Text := '';
Edit2.Text := '';
Edit3.Text := '';
Edit4.Text := '';
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
// Ausgabe? :(
end;

end.


Moderiert von user profile iconNarses: Anhang als Code eingefügt.


ZeitGeist87 - Di 15.12.09 12:29

Und dein Lehrer spielt World of Warcraft? (=


Systanas - Di 15.12.09 12:36

Nee, der spielt sowas nicht :D ! Wir durften uns ein Thema aussuchen und da ich gelegentlich mal für meinen Bruder spiele hab ich mir gedacht verbinde ich das nützliche mit dem praktischen und mach ne Raid Datenbank ^^ unserm Lehrer is das schnupee Hauptsache eine Datenbank.

LG


Wolle92 - Di 15.12.09 13:01

dann bring ihn dazu, WoW zu spielen... mit dem ganzen kurs... Info-LK@Ulduar bockt doch :P


Systanas - Di 15.12.09 13:54

Ne lieber nich ... wenn wir wipen bekommen wir ne 6 oder so ^^.

@Wolle92 glückwunsch zum 4. Platz :D
@Topic ... weiß einer wie man das macht? Das ausgeben im StringGrid (Name: 'Raid' ^^).

.pas Datei ist ja im Anhang!


ZeitGeist87 - Di 15.12.09 14:32

Du lässt einfach eine Schleife über Raid laufen fügst mit jedem Durchlauf die Daten aus Raid[datensatznummer].<Feld> in Grid.cells[x,y] ein :)

Der Nachteil an dem Aufbau in deiner .pas:

Du hast die Größe des Records fix auf 1.000 gestellt. Sind weniger Datensätze drin, werden dennoch 1.000 aufgelistet.
Hast du mehr als 1.000 bekommst du eine Zugriffsverletzung.

Abhilfe schaffen Suche in der Entwickler-Ecke DYNAMISCHE ARRAYS

LG
Stefan


Systanas - Di 15.12.09 15:02

Boah ich bin ein Knubb ^^,
Danke!

Jetzt klappts :D , jetz muss ich irgendwie noch das Speichern und Laden in eine .txt Datei realisieren!

MfG


ZeitGeist87 - Di 15.12.09 15:05

Willst du das StringGrid speichern oder den Record ;-)


Systanas - Di 15.12.09 15:10

Tja ich glaube da hab ich mir für mein wissen ein wenig zuviel vorgenommen :'(

Ich denke ich will das StringGrid speichern d.h. irgendwie in einer Datei Speichern sodass ich das im StringGrid wieder abrufen kann beim nächsten start.

Ich werde da wohl bissl warten müssen bis da mein wissens stand wächst denn was ich nicht im ansatz selbst machen kann hilft mir ja auch nich :D ABER es wäre cool wenn mir das jemand erklären bzw. im Quellcode aufschreiben kann sodass mein programm funktioniert und ich das nutzen kann, wird dann natürlich nicht für meinen Lehrer implementiert ist ja nicht meine arbeit :)

LG


ZeitGeist87 - Di 15.12.09 15:24

Mir fallen gerade zig Ansätze ein.

Ein Beispiel, bei dem du auch was über INIfiles lernst.

Du schreibst oben in deine uses noch die Suche in der Entwickler-Ecke INIFILES dazu.

Wie INI benutzen

Deklariere eine globale Variable INI vom Type TINIFile.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function erzeugeINI(Datei: String): Boolean;
begin;
 result:= false;
 try
  INI:= TINIFile.create(Datei);
 finally
  result:= true;
 end;
end;


Der Übergabeparameter ist so gehalten, dass du das Ganze mit einem Opendialog kompinieren kannst.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
if opendialog1.execute then
begin
 if erzeugeINI(opendialog1.filename) then
 begin
  //Weitermachen
 end
 else
 begin
  messagebox(application.handle, pchar('Beim Erzeugen der INI gab es Probleme'), pchar('INI erzeugen'), MB_IconWARNING);
  exit;
 end;
end;


Danach kannst du deine Daten speichern, indem du für jede Datensatznummer deines Records eine neue Sektion in der INI anlegst


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
function speichereDatensatz(Nummer: Integer): Boolean;
begin;
 result:= false;
 try

  {
    Hier könnte man noch prüfen, ob Nummer auch 
    im Low- und Highrange des Records ist.
  }
    
  
  INI.WriteString(IntToStr(Nummer), 'Raid', <DeinRecord>[Nummer].Raid);
  INI.WriteString(IntToStr(Nummer), 'DKP', <DeinRecord>[Nummer].DKP);
  INI.WriteString(IntToStr(Nummer), 'Boss', <DeinRecord>[Nummer].Boss);
  //Beliebig erweiterbar
 finally
  result:= true;
 end;
end;


Zu guter Letzt schließen wir die INI, nachdem alles geschrieben ist.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function closeINI: Boolean;
begin;
 result:= false;
 try
  INI.free;
 finally
  result:= true;
 end;
end;


Anmerkung:: Der Ansatz ist sehr sehr rudimentär und ich würde auch davon abraten, INI global zu nutzen und von Funktion zu Funktion offen zu halten.

Das Laden funktioniert analog über Suche in der Entwickler-Ecke INI.READSTRING.

LG
Stefan


Systanas - Di 15.12.09 15:57

Ok, soweit mir das möglich war hab ich das im großen und ganzen verstanden. Das einzigste was ich nicht zuordnen kann ist
der OpenDialog. Das ist mir noch völlig unklar 1. Was das ist 2. Wohin das kommt (Quelltext) und 3. Wozu das gut ist?

EDIT: Achso, das schließen der INI. Wie soll ich das denn benutzen? In den Speicher Button mit rein schreiben ? :?:

Wäre noch nett wenn du mir das erklären könntest den rest versuche ich nachher mal zu implementieren und zu testen!
Danke schon einmal für die Mühe!

LG


ZeitGeist87 - Di 15.12.09 16:00

Kein Problem.

Der Opendialog ist ein Objekt, welches du oben im Reiter "Dialoge" findest.

Du kennst doch diese Fenster, die sich öffnen, wenn du etwas speichern/öffnen möchtest.
Genau das ist der Dialog ;-)

Zu deiner zweiten Frage:

Ich drücks mal grob aus

1. INI erzeugen
2. Schleife über Raid laufen lassen
3. Speichern des Datensatzes
4. alles gespeichert -> INI schließen.

LG
Stefan


Systanas - Di 15.12.09 17:11


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:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
unit UTRaid;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls,INIFiles;

type tVerbund = record
         dkp : Integer;
         Name : String;
         Item : String;
         Boss : String;
          end;
     tFeld = array[0..1000of tVerbund;

  TForm1 = class(TForm)
    Raid1: TStringGrid;
    DSatz: TLabel;
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
   // function erzeugeINI(Datei: String): Boolean;
    { Public declarations }
  end;

var
  Form1: TForm1;
  Raid : tFeld;
  datensatznummer : Integer;
  INI : TIniFile;

implementation

{$R *.dfm}

function erzeugeINI(Datei: String): Boolean;
begin
 result:= false;
 try
  INI:= TINIFile.create(Datei);
 finally
  result:= true;
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i : Integer;
begin
  Raid1.Cells[1,0] := 'Name';
  Raid1.Cells[2,0] := 'DKP';
  Raid1.Cells[3,0] := 'Item';
  Raid1.Cells[4,0] := 'Boss';

  FOR i:=1 to 9 DO Raid1.Cells[0,i] := IntToStr(i);
  datensatznummer := 1;
  DSatz.Caption := IntToStr(datensatznummer);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
DSatz.Caption := IntToStr(datensatznummer);

Raid[datensatznummer].Name := Edit1.Text;
Raid[datensatznummer].DKP := StrToInt(Edit2.Text);
Raid[datensatznummer].Item := Edit3.Text;
Raid[datensatznummer].Boss := Edit4.Text;

inc(datensatznummer);
DSatz.Caption := IntToStr(datensatznummer);

Edit1.Text := '';
Edit2.Text := '';
Edit3.Text := '';
Edit4.Text := '';
end;

procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
begin
 // i:=1;
  Raid1.rowcount:=datensatznummer;
  Raid1.ColCount:=5;
  for i:=1 to datensatznummer do
    begin
      Raid1.Cells[1,i]:= Raid[i].Name;
      Raid1.Cells[2,i]:= floattostr(Raid[i].dkp);
      Raid1.Cells[3,i]:= Raid[i].Item;
      Raid1.Cells[4,i]:= Raid[i].Boss;
    end;

end;

function speichereDatensatz(datensatznummer: Integer): Boolean;
begin;
 result:= false;
 try
  INI.WriteString(IntToStr(datensatznummer), 'Name', Raid[datensatznummer].Name);
  INI.WriteString(IntToStr(datensatznummer), 'DKP', IntToStr(Raid[datensatznummer].DKP));
  INI.WriteString(IntToStr(datensatznummer), 'Boss', Raid[datensatznummer].Boss);
  INI.WriteString(IntToStr(datensatznummer), 'Item', Raid[datensatznummer].Item);
 finally
  result:= true;
 end;
end;

function closeINI: Boolean;
begin;
 result:= false;
 try
  INI.close;
 finally
  result:= true;
 end;
end;
    {
function ladeDatensatz(datensatznummer: Integer): Boolean;
begin;
 result:= false;
 try
  INI.ReadString(IntToStr(datensatznummer), 'Name', Raid[Datensatznummer].Name);
  INI.ReadString(IntToStr(datensatznummer), 'DKP', Raid[Nummer].DKP);
  INI.ReadString(IntToStr(datensatznummer), 'Boss', Raid[Nummer].Boss);
  INI.ReadString(IntToStr(datensatznummer), 'Item', Raid[datensatznummer].Item);
 finally
  result:= true;
 end;
end;
              }

end.

Ok, dafür bin ich iwie zu dumm das versteh ich noch nicht :( .
Hoffe trotzdem das wir das zusammen iwie fixen und zum laufen bekommen. Also so wie der Text oben steht hab ich erstmal die functions rein kopiert und umgeschrieben bekomme aber ziemlich viele Fehler:

Quelltext
1:
2:
3:
4:
5:
6:
7:
Build
  [Hint] UTRaid.pas(52): Value assigned to 'erzeugeINI' never used
  [Hint] UTRaid.pas(109): Value assigned to 'speichereDatensatz' never used
  [Error] UTRaid.pas(124): Undeclared identifier: 'close'
  [Error] UTRaid.pas(135): Undeclared identifier: 'Nummer'
  [Error] UTRaid.pas(135): Incompatible types: 'String' and 'Integer'
  [Fatal Error] TRaid.dpr(5): Could not compile used unit 'UTRaid.pas'

Puuh ganz schön schwer ich hab noch einen langen weg vor mir!
Bitte erleuchte mich weiser Mann ! :D

LG

Moderiert von user profile iconNarses: Code- durch Delphi-Tags ersetzt


JDF - Di 15.12.09 19:03

Hallo Systanas!

Du hast sehr gute Hilfen von ZeitGeist87 erhalten.

Bitte denke mal über folgend Punkte nach:
1. die Gültigkeitsbereiche deiner Variablen und Funktionen,
2. Objekte kann man nur nutzen wenn man sie erzeugt hat,
3. "Nummer" ist nicht gleich "datensatznummer".


die Variablen sollten private Variablen des Formulars sein:

Delphi-Quelltext
1:
2:
3:
Raid : tFeld;  
datensatznummer : Integer;  
INI : TIniFile;


diese Funktionen sollten als Methoden des Formulars definiert sein:

Delphi-Quelltext
1:
2:
3:
4:
function erzeugeINI(Datei: String): Boolean;
function speichereDatensatz(datensatznummer: Integer): Boolean;
function closeINI: Boolean;
function ladeDatensatz(datensatznummer: Integer): Boolean;


Gruß
Jürgen


Systanas - Di 15.12.09 19:21

user profile iconJDF hat folgendes geschrieben Zum zitierten Posting springen:

Bitte denke mal über folgend Punkte nach:
1. die Gültigkeitsbereiche deiner Variablen und Funktionen,
2. Objekte kann man nur nutzen wenn man sie erzeugt hat,
3. "Nummer" ist nicht gleich "datensatznummer".


Delphi-Quelltext
1:
2:
3:
Raid : tFeld;  
datensatznummer : Integer;  
INI : TIniFile;


diese Funktionen sollten als Methoden des Formulars definiert sein:


Hi Jürgen,
jah der Zeitgeist ist ein ganze netter! Allerdings hab ich ja schon zugegeben das ich noch nicht so die Ahnung davon habe und ich es mal versuchen würde aber mir die HIntergründe noch fehlen ich mich trotzdem freuen würde wenn ich das Programm zu meiner unterstützung nutzen könnte.

Also,
1. Wie meinst du das? :D
2. Worauf genau bezogen (welches Obejekt?)
3. nicht? was ist es dann?

Zu den Variablen die sind unter var in den globalen drinne!
Zu den methoden: Die hatte ich unter Public deklariert, allerdings hatte er trotzdem gemeckert deswegen hab ich sie rausgenommen.. was er jetz aber immernoch macht >.<

Ich bitte euch nicht so streng zu sein :D

LG


JDF - Mi 16.12.09 10:20

Hi Systanas!

zu 3. bezieht sich auf eine Fehlermeldung


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
[Error] UTRaid.pas(135): Undeclared identifier: 'Nummer'


function ladeDatensatz(datensatznummer: Integer): Boolean;
begin
  result:= false; 
  try  
    INI.ReadString(IntToStr(datensatznummer), 'Name', Raid[Datensatznummer].Name);  
    INI.ReadString(IntToStr(datensatznummer), 'DKP', Raid[N U M M E R].DKP);  
    INI.ReadString(IntToStr(datensatznummer), 'Boss', Raid[Nummer].Boss);  
    INI.ReadString(IntToStr(datensatznummer), 'Item', Raid[datensatznummer].Item); 
  finally  
    result:= true; 
  end;
end;



zu 2. Das TIniFile-Objekt.
Du hast in deinem Programm die Funktion "erzeugeINI" nicht aufgerufen.
Die Objektfreigabe gehört ebenfalls zu einem guten Programm, also den Aufruf
der Funktion "closeINI" nicht vergessen.

zu 1.

In der ObjektOrientiertenProgrammierung sollte man globale Variablen nur mit größter Vorsicht einsetzen.
z.B. Du erstellst mehrere Instanzen deines Formulars und Alle greifen auf die eine INI-Variable zu
--> Bei angenommenen 4 Formular-Instanzen würden 3 TIniFile-Instanzen im Nirvana verschwinden, da die
INI-Variable nur die Referenz zu einem Objekt halten kann.
Also: die INI-Variable in den "privat"-Bereich deines Formulars.
Und stell Dir mal das Durcheinander mit dem Satzzeiger "datensatznummer" und dem "Raid"-Record vor.

Darum: wenn Objektorientiert, dann alle intern verwendeten Variablen ins Formular!

Mit den Funktionen verhält es sich ähnlich:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
type
  TForm1 = class(TForm)
  ...
  private
    INI : TIniFile;
    function erzeugeINI(Datei: String): Boolean;
  ...
  public
  ...
  end;


function TForm1.erzeugeINI(Datei: String): Boolean;
begin
...
end;



Gruß
Jürgen


ZeitGeist87 - Mi 16.12.09 11:59

Wunderschönen guten Morgen!

Danke Jürgen, dass du weitergemacht hast ;-)

Ich hab nicht mehr viel hinzuzufügen außer, dass in der Funktion closeINI es INI.free; heißen muss :)

In aller Eile hab ich das vollkommen übersehen.

LG
Stefan


elundril - Mi 16.12.09 12:03

Kleine Frage, warum INIs anstelle von typisierten Dateien? Würden die sich bei einem Record nicht geradezu aufdrängen?

lg elundril


ZeitGeist87 - Mi 16.12.09 12:15

user profile iconZeitGeist87 hat folgendes geschrieben Zum zitierten Posting springen:
Mir fallen gerade zig Ansätze ein.

Ein Beispiel, bei dem du auch was über INIfiles lernst.
...


JDF - Mi 16.12.09 13:04

Hi elundril!

Die Frage nach den typisierten Dateien hatte ich mir auch gestellt.
Aber die Definition des Records


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  tVerbund = record         
    dkp : Integer;         
    Name : String;         
    Item : String;         
    Boss : String;          
  end;


ist mit den großen Strings angelegt.

Das Speichern in typisierten Dateien ist aber nur mit ShortStrings (1..255 Zeichen, z.B. String[255] ) problemlos ausführbar.
Die Änderung des Record wäre bestimmt nicht das Problem, aber bei eventuellen Erweiterungen der Record-Struktur passen die bereits erfassten Daten nicht mehr. Und die Einarbeitung in die Dateiarbeit ist auch nicht ohne.

Für einen Beginner sind das zu viele Stolperfallen.
Wir wollen doch einen begeisterten Delphi-Programmierer gewinnen.

Gruß
Jürgen


ZeitGeist87 - Mi 16.12.09 13:07

Beim Beispiel hier mit World of Warcraft würde es sogar funktionieren, da die Namen der Gegner und Gegenstände ziemlich kurz gehalten sind und nicht über 255 hinausgehen.

Aber wie gesagt, ich fand diese Möglichkeit mit eine der einfachsten.
Somit lernt er gleich für die Zukunft.

Wer jetzt sagt, Inifiles sind out, der denkt nicht nach. ;-)


elundril - Mi 16.12.09 15:23

Sag ich nicht, sag ich nicht, ich speichere die Einstellungen all meiner Programme immer noch in INI-Files weil diese Einfach am Portabelsten sind und auch besser zu löschen als irgendwelche Registryeinträge. Ich dachte mir nur das es sicher erwähnenswert ist, da man auch dann tieferen Einblick in Dateioperationen bekommt und es sicher für die Fähigkeiten förderlich ist.

lg elundril