Entwickler-Ecke

Datenbanken - Daten aus Datenbank in Textdatei geordnet speichern


Black_Fox - Di 01.04.08 21:01
Titel: Daten aus Datenbank in Textdatei geordnet speichern
Hi hab nichts wirklich dazu hier gefunden und wollte erstmal fragen ob dies überhaupt möglich ist Die Daten die sich in einer Datenbank befinden über enen Buton sortiert in einer Textatei abzuspeichern?

Ich bin dabei ein kleines Adressbuch als Schulprojekt zu programmieren und würde gerne die Daten geordnet in einer Textdatei abspeichern.


Delete - Di 01.04.08 21:36

ja das ist möglich, wenn du beim buttonclick noch 'n paar zeilen code hinterlegst... :-) <woher soll denn sonst delphi wissen, aus welcher datenbank, welcher tabelle, wie sortiert, welche felder, wohin...>


Black_Fox - Mi 02.04.08 09:17

Ah ok also ist es erstmal möglich das wollte ich bloß erstmal wissen dann werde ich mal probieren dass hinzubekommen und wenn Probleme auftreten melde ich mich nochmal.

Hab festgestellt das ne .csv datei doch besser wäre aber das kann ich ja mit nem filter in meinem savedialog machen.


Black_Fox - Do 03.04.08 17:07

hab das jetzt so gemacht funktioniert aber nicht kannst du mir sagen was daran falsh ist?:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
var Adressdaten : textfile;
begin
if DBSave.Execute then
begin
  assignfile(Adressdaten,DBSave.Filename+'.txt');
  rewrite(Adressdaten);
  TAdressdaten.FieldByName('Nachname').AsString := DBEdit1.Text;
  TAdressdaten.FieldByName('Vorname').AsString := DBEdit2.Text;
  TAdressdaten.FieldValues['Geburtsdatum'] := DBEdit3.Text;
  TAdressdaten.FieldByName('E-mail').AsString := DBEdit4.Text;
  TAdressdaten.FieldByName('Telefonnummer').AsString := DBEdit5.Text;
  TAdressdaten.FieldByName('Handy Nummer').AsString := DBEdit6.Text;
  TAdressdaten.FieldByName('Straße').AsString := DBEdit7.Text;
  TAdressdaten.FieldByName('Hausnummer').AsString := DBEdit8.Text;
  TAdressdaten.FieldByName('PLZ').AsString := DBEdit9.Text;
  TAdressdaten.FieldByName('Wohnort').AsString := DBEdit10.Text;
  closefile(Adressdaten);
end;


Black_Fox - Mo 07.04.08 10:55

Kann mir bitte jemand helfen? Ich will die Daten aus ner Datenbank in ner Textdatei speichern aber hab kein wirklichen Plan davon?


zuma - Mo 07.04.08 11:17

was ist TAdressdaten bei Dir ??
Wenn das deine Abfragekomponente ist, kanns auch nicht gehen, du überträgst die Daten der Anzeige in TAdressdaten ...

Ich denke, du solltest es evtl. so machen:
die Datenmenge durchlaufen, (First und dann z.b while not eof))
pro Datensatz einen String aufbereiten (Trennzeichen ';' verwenden, dann kannste auch CSV),
diesen in einer Stringlist speichern, (add('xy'))
nachdem du alle Datensätze durchlaufen hast, die Stringlist per savetofile speichern - fertig.


Zorro - Mo 07.04.08 11:35

user profile iconBlack_Fox hat folgendes geschrieben:
hab das jetzt so gemacht funktioniert aber nicht kannst du mir sagen was daran falsh ist?:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
var Adressdaten : textfile;
begin
if DBSave.Execute then
begin
  assignfile(Adressdaten,DBSave.Filename+'.txt');
  rewrite(Adressdaten);
  TAdressdaten.FieldByName('Nachname').AsString := DBEdit1.Text;
  TAdressdaten.FieldByName('Vorname').AsString := DBEdit2.Text;
  TAdressdaten.FieldValues['Geburtsdatum'] := DBEdit3.Text;
  TAdressdaten.FieldByName('E-mail').AsString := DBEdit4.Text;
  TAdressdaten.FieldByName('Telefonnummer').AsString := DBEdit5.Text;
  TAdressdaten.FieldByName('Handy Nummer').AsString := DBEdit6.Text;
  TAdressdaten.FieldByName('Straße').AsString := DBEdit7.Text;
  TAdressdaten.FieldByName('Hausnummer').AsString := DBEdit8.Text;
  TAdressdaten.FieldByName('PLZ').AsString := DBEdit9.Text;
  TAdressdaten.FieldByName('Wohnort').AsString := DBEdit10.Text;
  closefile(Adressdaten);
end;


Vergiss den ganzen Block, der mit "TAdressdaten.FieldByName..." beginnt und guck in der Hilfe zum Thema "write/writeln" nach. Hier werden Sie geholfen.

Greetz
Zorro


Zorro - Mo 07.04.08 11:36

user profile iconBlack_Fox hat folgendes geschrieben:
hab das jetzt so gemacht funktioniert aber nicht kannst du mir sagen was daran falsh ist?:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
var Adressdaten : textfile;
begin
if DBSave.Execute then
begin
  assignfile(Adressdaten,DBSave.Filename+'.txt');
  rewrite(Adressdaten);
  TAdressdaten.FieldByName('Nachname').AsString := DBEdit1.Text;
  TAdressdaten.FieldByName('Vorname').AsString := DBEdit2.Text;
  TAdressdaten.FieldValues['Geburtsdatum'] := DBEdit3.Text;
  TAdressdaten.FieldByName('E-mail').AsString := DBEdit4.Text;
  TAdressdaten.FieldByName('Telefonnummer').AsString := DBEdit5.Text;
  TAdressdaten.FieldByName('Handy Nummer').AsString := DBEdit6.Text;
  TAdressdaten.FieldByName('Straße').AsString := DBEdit7.Text;
  TAdressdaten.FieldByName('Hausnummer').AsString := DBEdit8.Text;
  TAdressdaten.FieldByName('PLZ').AsString := DBEdit9.Text;
  TAdressdaten.FieldByName('Wohnort').AsString := DBEdit10.Text;
  closefile(Adressdaten);
end;


Vergiss den ganzen Block, der mit "TAdressdaten.FieldByName..." beginnt und guck in der Hilfe zum Thema "write/writeln" nach. Hier werden Sie geholfen.

Greetz
Zorro


Black_Fox - Mo 07.04.08 11:54

ok thx für den tipp werd ich mal machen, wollte mal fragen ob das mit einer stringlist besser wäre?


Zorro - Mo 07.04.08 17:49

user profile iconBlack_Fox hat folgendes geschrieben:
ok thx für den tipp werd ich mal machen, wollte mal fragen ob das mit einer stringlist besser wäre?


Ich sach mal "Ansichtssache" - StringListen haben das Plus, dass du gaaaaanz bequem laden und speichern kannst, weil es entsprechende Methoden gibt, auch das Sortieren is n Klacks, dafür musst du sie brav als Objekt behandeln (also createn und freigeben).
Der Zugriff per textfile ist reines Pascal ohne Objekt-Schnickschnack (grins), dafür musst du eben mehr "zuu Fuß" machen.

Greetz
Zorro


Black_Fox - Mo 07.04.08 20:29

ah ok danke für die info also werd ich das mit ner stringlsit versuchen da ich die addressdaten ja auch mal importieren will und nicht nur exportieren


Black_Fox - Do 10.04.08 17:41

Das haut ni ganz hin, aber warum weiß ich nicht Login ist meine Paradox Tabelle also die Datenbank denke ich, aber wie kann ich jetzt die Daten darin auslesen bzw. abspeichern?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.Button3Click(Sender: TObject);
var i : integer;
    f : textfile;
    dsatz: string;
begin
if savedialog1.Execute then
begin
  assignfile(f,savedialog1.filename);
  rewrite(f);
  for i:= 0 to Adressliste.Count -1 do
  begin
    dsatz:='';
    dsatz:= (inttostr(i+1)+', '+ TLogin(Adressliste.Objects[i]).DBEdit1+', '+
    Tlogin(Adressliste.Objects[i]).DBEdit2+', '+
    writeln(f,dsatz);
  end;
  closefile(f);
end;
end;


SmileySN - Do 10.04.08 23:11

Bei einer Datenbank, holt man sich seine Daten nicht aus den DBEdit-Komponenten sondern direkt aus dem Datenbankfeld.
In CSV Dateien sollte man möglichst die Felder mit einem Semikolon trennen.
Falls man nicht ausschließlich Textfelder benutzt (in denen kein Semikolon vorkommt), sollte man die Feldeinträge in Anführungszeichen setzen.

Hier mal ein Beispiel wenn man ein Connection und ein Query Objekt benutzt.
Das Query-Objekt heißt hier QWork, der SQL string heißt: 'Select * From Tabellenname order by Name'
Durch den Feldnamen hinter 'order by' kann man sich aussuchen wonach sortiert wird.


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:
//******************************************************************************
//******************************* Daten exportieren ****************************
//******************************************************************************
procedure ExportCSV;
var
  ProgPath, KopfZeile: string;
  DateiOut: Textfile;
  Kopf: Boolean;

begin
  Kopf := True;
  ProgPath := ExtractFilePath(ParamStr(0));

  KopfZeile := 'Name; Vorname; Ort; PLZ; Strasse';
  AssignFile(DateiOut, ProgPath + 'Export.csv');
  try
    rewrite(DateiOut);

    if Kopf then WriteLn(DateiOut, KopfZeile);
    QWork.First;
    while not QWork.eof do
      begin
        Write(DateiOut,   QWork.FieldByName('Name').AsString + ';');
        Write(DateiOut,   QWork.FieldByName('Vorname').AsString + ';');
        Write(DateiOut,   QWork.FieldByName('Ort').AsString + ';');
        Write(DateiOut,   QWork.FieldByName('PLZ').AsString + ';');
        WriteLn(DateiOut, QWork.FieldByName('Strasse').AsString );

        QWork.Next;
      end;
  finally
    CloseFile(DateiOut);
  end;
end;


Wenn ich mir Deine Programmierversuche so ansehe, glaube ich jedoch, Du hast noch gar keine Adressdatenbank sondern wilst erst eine anlegen, das ist ein ganz anderes Problem.
Ich bin davon ausgegangen, dass Du schon eine Datenbank mit Adressdaten hast und diese sortiert in eine CSV Datei ausgeben willst.


Black_Fox - Fr 11.04.08 09:01

ne ich hab ne paradox datenbank über die datenbankoberlche angelegt und 3 test datensätze schon drin, also könnte ich das verwenden oder?


SmileySN - Fr 11.04.08 10:39

Wenn Du eine DB schon angelegt hast, dann geht das.
Falls Du auf deinem PC Access installiert hast, würde ich empfehlen damit eine DB anzulegen und mit den ADO Componenten darauf zuzugreifen.
aber zum ausprobieren spielt es erst mal keine Rolle was man einsetzt.
Setze ein connection Objekt, eine query, eine Datasource und ein DBGrid auf dein Formular.
In der Connection alles eintragen was nötig ist um die DB zu finden.
In der Query die Connection auswählen und den SQL-Text eingeben.
Die Datasource mit der Query verbinden.
Das DBGrid mit der Datasource verbinden.
Eventuell noch einen Navigator aufs Formular und mit der Datasource verbinden.
Damit kannst Du schon mal alles nötige machen und es tut sich was in Deinem Programm.


Black_Fox - Fr 11.04.08 11:40

was ist eine connection komponente? und für was ist die gut?


zuma - Fr 11.04.08 12:03

Connection-Komponente = Objekt, welches die Verbindung zur Datenbank herstellt.
Hier ist wohl die ADOConnection-Komponente gemeint, die auf dem Reiter ADO zu finden sein sollte. Dort kannst du dann die Daten angeben, die zur verbindung nötig sind (z.b die Database, den ConnectString, etc) und auf bestimmte Connect-Ereignisse (after-/before-connect, etc.) reagieren.
für was die gut ist, sollte sich damit erklären.
Ansonsten hat SmileySN schon gesagt, wie man damit mal testet.


SmileySN - Fr 11.04.08 14:05

Genau so ist es.
Wenn Du schon eine Table Komponente auf Deinem Formular hast um die Datenbank anzusprechen, dann muss diese ja auch über irgendwas angebunden werden.
Oder ist das bei den einfachen BDE Foxpro Komponenten nicht so ? Hab damit schon seit vielen Jahren nicht mehr gearbeitet und bin gerade nicht im Delphi um nachzusehen.
Die Frage ist erst mal hast Du Access aus dem Microsoft Office Paket auf Deinem Computer installiert. Wenn ja, kann ich Dich Schritt für Schritt weiterführen.
Auf die alte BDE mit DBase und Foxpro habe ich keine Lust. Das ist schon zu veraltet. Table benutze ich auch nur sehr selten. Mit einer Query kann man alles viel einfacher machen und SQL muss man irgendwann sowieso lernen wenn man mit Datenbanken arbeiten will.


Ydobon - Fr 11.04.08 15:20

Access ist doch eigentlich nicht unbedingt notwendig, die Jet Engine sollte doch ab 2000 bei Windows auch so dabei sein?


SmileySN - Fr 11.04.08 15:40

Es geht jier nur um das anlegen der Datenbank.
Darum benutzt er ja auch die Foxprodatenbank, weil dafür ein Datenbankerstellungstool bei den alten Delphiversionen dabei ist.
Für diesen Zweck nimmt man das Accessprogramm, danach braucht man es nur noch, wenn man Änderungen an der DB vornehmen will und sich noch nicht so gut mit den SQL-Befehlen fürs Ändern der Felder auskennt.
Ich kann auch gerne eine leere AccessDB zuschicken wenn ich weiß, welche Felder mit welchen Feld-Typen und -größen benötigt wird.
Man kann auch mit Firebird oder Advantage Database Server oder einfach MS-SQLExpress arbeiten, aber da ist einiges erst mal zu lernen bevor das läuft.


Ydobon - Fr 11.04.08 16:13

Das Erstellen einer DB geht auch per ADOX. Wenn man die gesamte Typenbibliothek nicht zu importieren braucht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
uses ...ComObj;
var cat: OLEVariant;
begin
  cat:=CreateOleObject('ADOX.Catalog');
  cat.Create('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\test.mdb');
  cat:=unassigned;
end;

Die DB kann man dann mit einer ADOConnection verbinden und durch SQL beliebig füllen.


SmileySN - Fr 11.04.08 17:09

Sehr gut, das hatte ich nach langem suchen auch mal rausgefunden.
In Delphi7 hatte ich die ADOX TypeLibrary eingebunden und dann den ADOXCatalog Befehl benutzt.
Das einbinden der TypeLib ist aber nicht ganz einfach und ab den höheren Versionen ging das dann gar nicht mehr.

Braucht man für diese Variante keine Typelib mehr ?

Ansonsten wollte ich nicht gleich mit Kanonen auf Spatzen schießen, aber wenn Du schon mal damit anfängst, dann biete ich hier mal eine vollständige Variante des ganzen.
Da habe ich dann auch irgendwann mal im Forum gefunden. wozu so ein Forum nicht alles gut ist :).


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:
uses {..,}Variants, ComObj{,..}; 
//.. 
const 
   dbVersion10   = 1; 
   dbVersion11   = 8; 
   dbVersion20   = 16; 
   dbVersion30   = 32; 
   dbVersion40   = 64; 

function CreateDB(const FileName: String; const Version: Integer; DelIfExists: Boolean = False): String; 
var 
   DBEngine, 
   Workspace, 
   Database  : OleVariant; 
   s         : String; 
const 
   dbLangGeneral = ';LANGID=0x0409;'; 
begin 
   Result  := ''; 
   if FileExists(FileName) And DelIfExists then 
      DeleteFile(FileName); 
   s       := dbLangGeneral + 'CP=' + IntToStr(GetACP()) + ';COUNTRY=0'; 
   DBEngine:= CreateOleObject('DAO.DBEngine.36'); 
   try 
      try 
         Workspace := DBEngine.Workspaces[0]; 
         Database  := Workspace.CreateDatabase(FileName, s, Version); 
         Database.Close; 
         Workspace.Close; 
      except 
         On E: Exception do 
            Result := E.Message; 
      end; 
   finally 
      Database  := NULL; 
      Workspace := NULL; 
      DBEngine  := NULL; 
   end; 
end; 

procedure TForm1.BtnDBNeu.Click(Sender: TObject); 
begin 
   CreateDB('test.mdb', dbVersion20); 
end;


Damit wäre erst mal die Datenbank angelegt.
Als nächste muss die Tabelle in der DB angelegt werden.

Das erfahren wir dann in der nächten Sendung :)


SmileySN - Fr 11.04.08 17:52

Hier dann wie man die Tabellen anlegt.
Habe das nur so im Editor zusammengestellt, gebe keine Garantie für die Funktion.
Soll ja auch nur zeigen wie man es macht.
Con1 ist die ADOConnection und QKonten und QWaehrung sind Querys die mit der ADOConnection verbunden sind.


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:
procedure CreateTable;
const
  cCreateKonten = 'CREATE TABLE Konten('
    + 'KontoNr char(5) PRIMARY KEY,'
    + 'Beschriftung char(50),'
    + 'KontenTyp char(1),'
    + 'SH char(1),'
    + 'Land char(30),'
    + 'USTID char(20))';

  cCreateWaehrung = 'CREATE TABLE Waehrung('
    + 'Nr AutoInc PRIMARY KEY,'
    + 'Beschreibung char(30),'
    + 'Eurokurs double,'
    + 'EuroSt double,'
    + 'EuLand char(2),'
    + 'BasisWBetrag double,'
    + 'BasisWKennung integer)';

begin
  Con1.Active:=True; // Datenbank aktivieren
  
  QKonten.SQL.Text:=cCreateKonten; // Tabelle Konten erzeugen
  QKonten.ExecSQL; // Da keine Daten zurückgegeben werden ExecSQL ausführen

  QWaehrung.SQL.Text:=cCreateWaehrung; // Tabelle Waehrung erzeugen
  QWaehrung.ExecSQL; // Da keine Daten zurückgegeben werden ExecSQL ausführen
    
  QKonten.SQL.Text := 'Select * From Konten'; // Daten in Konten Selektieren
  QKonten.open; // Hier werden Daten zurückgegeben, daher open ausführen
  QWaehrung.SQL.Text := 'Select * From Waehrung'; // Daten in Waehrung Selektieren
  QWaehrung.open; // Hier werden Daten zurückgegeben, daher open ausführen 
End;


Black_Fox - Fr 11.04.08 18:09

hi jop hab access 2007 und auch schonmal nen bissl damit in der schule gearbeitet, könnte auch mein kleines addressbuch ändern bloß nun hab ich die frage ob ich in der access datenbank auch bilder speichern kann?


SmileySN - Fr 11.04.08 19:34

Wenn Du Access 2007 hast, dann mustt Du nach dem anlegen der DB die DB als Access2000 Format speichern, das 2007er Format geht nicht mit den ADO Komponenten.

Man kann auch Bilder in der Datenbank speichern, das ist aber kompliziert, einfacher ist es die Bilder in einem separaten Pfad abzulegen und in der Datenbank nur den Pfad und Dateinamen abzulegen.

Glaub aber nicht, dass das Bild von alleine angezeigt wird wie in den DBEdit Komponenten, ein bisschen muss man dafür schon tun.
Setze eine Image Komponente aufs Formular und lade bei jedem Datensatzwechsel das Bild in die Image rein.


Black_Fox - Fr 11.04.08 22:25

klingt ja kompliziert^^ naja werd mich das we mal damit beschäftigen erstmal den aufbau mit den ado komponenten etc


Bernhard Geyer - Sa 12.04.08 00:54

user profile iconYdobon hat folgendes geschrieben:
Access ist doch eigentlich nicht unbedingt notwendig, die Jet Engine sollte doch ab 2000 bei Windows auch so dabei sein?

Jein. Bei den Embedded-Versionen von XP (und vermutlich auch Vista) kann man konfigurieren ob man auch die Jet-Engine haben will. Ist diese nicht konfiguriert kann sie nicht einzeln (per MDAC-Installer) nachinstalliert werden. Man braucht dann eine richtige Access-Installation.


Black_Fox - Sa 12.04.08 13:50

ok SmileySN kannste mir mal alle komponenten sagen die ich jetzt für die umsetzung mit access brauche?

hab zurzeit diese scon aufn formular:
adotable, adoconnection, adoquery, datasource

für das eintragen von daten:
dbnavigator, mehrere db edit felder, ein dbimage

für das anzeigen der daten:
dbgrid

z den ganzen komponenten kommen noch zusätzliche dige hinzu wie buttons und menü etc. aber denke die spielen erstmal keine rolle


SmileySN - Sa 12.04.08 15:01

OK, dann hast Du ja schon alles.
Die Table brauchen wir erst mal nicht.
Jetzt erst mal am besten mit dem assistenten im Objektinspector in der ADOConnection den ConnectionString aufbauen.
Doppelklick auf Connectionstring dann Button Aufbauen drücken dann "Microsoft Jet 4.0 OLE DB Provider" auswählen.
Weiter Button drücken.
Datenbank (mdb)auswählen mit ...
Verbindung Testen. Es sollte OK erscheinen.

Die Query auswählen und im Objectinspector unter Connection die ADOConnection auswählen.
SQL im Objectinspector auswählen mit doppelklick und folgendes eingeben: Select * from Tabellenname
(Hier den Tabellennamen der Tabelle in der Datenbank eingeben)

Datasourcekomponente auswählen.
Bei Dataset die Query auswählen.

Im DBGrid,DBEdit,Navigator jeweils die Datasource auswählen.

Beim DBEdit muss man noch das Datenfeld angeben das dort angezeigt werden soll.

Dann zum testen mal die connection auf active setzen, dann die query und dann die Datasource.

Jetzt sollten schon mal Daten im Grid und den Editfeldern erscheinen.


SmileySN - Sa 12.04.08 15:05

Wenn man seine Daten sortiert haben möchte, dann im Programm folgendes eingeben.

Delphi-Quelltext
1:
2:
Query.SQL.Text:='Select * from Tabellenname order by feldname';
Query.open;


danach sind die Daten nach Feldname sortiert.


SmileySN - Sa 12.04.08 15:19

Diesen Thread auch mal durchlesen für den nächsten Schritt: http://www.delphi-forum.de/viewtopic.php?t=82483


Black_Fox - So 13.04.08 13:54

k hab das jetzt soweit also die daten von einer tabelle in der datnebank werden in der grid angezeigt


SmileySN - So 13.04.08 14:30

Gut, und mit dem Navigator kannst Du Dich in der Tabelle auch bewegen, hinzufügen und löschen.
Was soll jetzt noch funktionieren ?


Black_Fox - So 13.04.08 16:22

jup geht, na bilder muss ich da jetzt noch irgendwie mit rein achen oder so wie du das gesagt hattest mit dem pfad der bilder aber hab kein plan wie ich das machen soll


SmileySN - So 13.04.08 20:43

Das mit dem Bild ist doch gar nicht schwer, man muss sich nur von dem Gedanken lösen, das es von alleine geht.
Mit irgendwas musst Du doch Deinen Datensatzzeiger bewegen um auf den nächsten Datensatz zu kommen.
Wenn Du noch mit dem Navigator arbeitest, dann solltest Du dor mal in die ereignisse gehen und dir die mal ansehen, da gibt es betimmt eines, das ausgelöst wird, wenn Du den Datensatz bewegst.
Da machst Du einen doppelklick drauf und kommst in eine neue Prozedur, darin kannst Du dann den Namen des Bildes aus der Datenbank lesen (der solte beim neuanlegen des Datensatzes mit OpenFileDialog abgelegt worden sein) und Das auf dem Formular sitzende Image damit füllen.
Image.Picture.Loadfromfile(Dateiname aus Datenbankfeld);
Jedesmal wenn Du eine Datensatzbewegung machst wird dieser Befehl ausgeführt und das Bild wird geladen und angezeigt.


Black_Fox - Mo 14.04.08 10:45

ok ich werds mal mit dem ereignis beforeaction probieren


SmileySN - Mo 14.04.08 12:15

Ich habe mir den DBNavigator mal angesehen, der ist zum Programmieren kaum zu gebrauchen, soweit ich das sehe.
Die einzelnen Funktionen haben kein eigenes Ereignis.
Ich benutze immer nur Buttons für die Funktionen, das ist ganz einfach.
Button auf Formular Caption umbenennen in "Weiter" und einen doppelklick drauf, dann "Query.next;" reinschreiben.
Query sollte der Name Deiner Querys sein.
Dasselbe mit Button "Zurück" "Query.Prior;"
Dann gibt es noch .Last und .First.
Für "Neu" kann man query.append benutzen.
Für "Speichern" Query.Post.
Wenn Du das hast, kannst Du in die Prozedur ButtonWeiter.Click dann auch das laden des Bildes mit einbauen, ebenso in die Zurück Prozedur.


Black_Fox - Mo 14.04.08 14:04

ok thx dann werd ich die navi weglassen und eigene buttons verwenden

Hab noch ne Frage:

Kann ich den Pfad so aus der Db lesen? und mit writeln speichern?


Delphi-Quelltext
1:
readln(ADOQuery1.FieldByName('Bild').asstring);                    



Delphi-Quelltext
1:
writeln(ADOQuery1.FieldByName('Bild').asstring);                    


Achja und muss die Spalte 'Bild' in meiner Db nun ein Blob Feld sein oder ein Textfeld?


SmileySN - Mo 14.04.08 19:22

Nein, nicht ganz richtig!!
ReadLn und WriteLn sind Befehle für TextFiles und werden folgendermaßen benutzt:

wenn F vom Typ Textfile ist:

Delphi-Quelltext
1:
2:
ReadLn(F,ADOQuery1.FieldByName('Bild').asstring));
WriteLn(F,ADOQuery1.FieldByName('Bild').asstring));


Wobei man beim ReadLn dann erst mal ein Query.edit machen muss, da sich die Datenbank sonst nicht beschreiben lässt.
Nach dem ReadLn muss dann auch noch ein Query.post kommen, damit der Datensatz auch weggeschrieben wird.
Sonst ist er nur im Cache. (Aber erst, wenn alle Felder gelen wurden einen post machen, nicht bei jedem Feld)

Mi WriteLn kannst Du aber keine CSV Datei erstellen wie Du es vorhast.
Dazu musst Du den Write Befehl nehmen und nach jedem Feld auch noch das Trennzeichen schreiben.
Erst wenn das letzte Feld geschrieben wird, dann macht man ein WriteLn.

Bein lesen ist das wieder anders, da liest Du einmal mit Readln in eine Variable und zerlegst diese dann in ihre Felder.

Somit wird das mit dem ReadLn und WriteLn mit Datenfeld direkt sowieso nichts.

Wenn ich es gleich finde, schick ich mal ne Lösung fürs schreiben in csv gleich hier rein.

Moderiert von user profile iconKlabautermann: Delphi-Tags hinzugefügt.


SmileySN - Mo 14.04.08 19:34

Hier ein Beispiel, wie man aus einer CSV Datei liest:


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

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Function GetFeld(a : String; Var z : Integer) : String;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var ProgPath ,a , Konto, SKD, BEschreibung, Land, USTID: String;
    Datei : Textfile;
    Kopf : Boolean;
    z : Integer;
begin
  Kopf := True;
  ProgPath:=ExtractFilePath(paramstr(0));
  opendialog1.InitialDir := ProgPath;
  Opendialog1.Execute;
  AssignFile(Datei, Opendialog1.FileName);
  try
    reset(Datei);
  except
    exit;
  end;
  If Kopf then readln(Datei,a); // Wenn Datei eine Kopfzeile hat, dann erst einmal lesen. (Feldnamenliste)
  While not EOF(Datei) do
    Begin
     z := 1;
     readln(Datei,a);
     Konto := GetFeld(a,z);
     SKD := GetFeld(a,z);
     Beschreibung := GetFeld(a,z);
     Land := GetFeld(a,z);
     USTID := GetFeld(a,z);
     Listbox1.items.add(Konto+ '   '+ SKD + '   '+ Beschreibung + '   '+ Land + '   '+ USTID);
    End;
end;



Function GetFeld(a : String; Var z : Integer) : String;
Begin
  Result := '';
  While z <> Length(a) do
    If a[z] <> ';' then
      Begin
        Result := Result + a[z];
        inc(z);
      End
    Else
      Begin
        inc(z);
        Exit;
      End;

End;


end.


Black_Fox - Mo 14.04.08 20:10

jo ok aber ich dachte ich soll das aus der db lesen? den pfad für die bilder und speichern auch da drin?

hab nochmal ne frage zu dem, wie man die gesamte db in ner csv speichert hattest mir ja schon mal was dazu gepostet:
bloß jetzt hab ich ein problem wenn ich die csv datei öffnen will mit excel 2007 kommt immer der fehler kann datensatz nicht lesen und in der csv datei ist dann nichts drin?

beim datum hatte ich erst .asdatetime aber das geht ni kannste mir da helfen? und muss das bild nun egentlih string der blob in der db sein?


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:
procedure TForm1.Button2Click(Sender: TObject);
var
  ProgPath, KopfZeile: string;
  DateiOut: Textfile;
  Kopf: Boolean;
begin
  Kopf := True;
  ProgPath := ExtractFilePath(ParamStr(0));
  KopfZeile := 'ID; Vorname; Nachname; Geburtsdatum; Strasse; Hausnummer; PLZ; Wohnort; E-Mail; Telefonnummer; Handy Nummer; Bild';
  AssignFile(DateiOut, ProgPath + 'Adressdaten.csv');
  try
    rewrite(DateiOut);

    if Kopf then WriteLn(DateiOut, KopfZeile);
    ADOQuery1.First;
    while not ADOQuery1.eof do
      begin
        Write(DateiOut,   ADOQuery1.FieldByName('ID').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('Vorname').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('Nachname').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('Geburtsdatum') + ';'); 
        Write(DateiOut,   ADOQuery1.FieldByName('Straße').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('Hausnummer').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('PLZ').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('Wohnort').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('E-Mail').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('Telefonnummer').AsString + ';');
        Write(DateiOut,   ADOQuery1.FieldByName('Handy Nummer').AsString + ';');
        WriteLn(DateiOut, ADOQuery1.FieldByName('Bild').AsString );
        ADOQuery1.Next;
      end;
  finally
    CloseFile(DateiOut);
  end;
end;


SmileySN - Mo 14.04.08 22:41

Das was Du da geschrieben hast ist in Ordnung soweit ich das sehe.

Bis auf Geburtsdatum, da muss auch noch ein .AsString dran.

Hast Du Dir die csv datei mal mit dem editor angesehen, was drin steht ?

Das Feld Bild sollte ein String sein und darin ist der vollständige Dateinamen des Bildes mit Pfad.


SmileySN - Mo 14.04.08 22:47

Um einen Fehler in Delphi zu finden gibt es eine Funktion die sich debuging nennt :)
Setze eine Haltemarke vor Query1.first und starte das Programm, dann mit der F7 Taste Schritt für Schritt weitergehen und schauen was das Programm so macht.
Die Variablen kann man sich auch ansehen, indem man die Mouse über eine Variable hält.
Warscheinlich wirst Du feststellen, dass die Do whilw schleife gar nicht oder nur ein mal durchlaufen wird.
Was will uns das sagen ???
Tip: Query1.SQL.Text


Black_Fox - Di 15.04.08 12:24

auf was willst du hinaus @SmileySN? komm jetzt ni ganz mit^^

Zitat:
Was will uns das sagen ???
Tip: Query1.SQL.Text


werd das wenn ich zu hause bin mal richtig machen mit der csv datei etc., bloß um das bild in der csv datei auszugeben, muss ich den pfad ja erstmal reinbekommen^^ und da scheitert es zurzeit.


SmileySN - Di 15.04.08 13:24

In dem Programmteil der hier zu sehen ist, ist das Select-Statement des Query nicht zu sehen, somit weiß man nicht was gerade angezeigt wird.
Ob überhaupt Datensätze vorhanden sind.
Bevor Du Button2click aufrufst muss im SQL.Text mindestens mal "Select * from Tabellenname" drin stehen, damit überhaupt Datensätze zur Verfügung stehen.

Dein Problem mit dem Bild kann ich nicht nachvollziehen, daher nochmal gaaaanz langsam zum mitlesen:

Auf Deinem Formular liegt neben den anderen DBEdit Feldern ein DBEditFeld mit namen "Bild" vom Typ String;
In dieses Feld kannst Du den Pfad und Namen Deines Bildes eingeben. (z.B. D:\Bilder\Bild1.jpg)
Außerdem ist auf dem Formular auch eine Image-Komponente, in der das Bild angezeigt werden kann.
Im FormShow des Formulares steht dann schon mal, nach dem öffnen der Datenbank, Image1.Picture.LoadFromFile(DBEditBild.Text);
Dasselbe muss auch im button Next und zurück stehen.
Im Verzeichnis d:\Bilder\ sollte das Bild Bild1.jpg liegen.

Das einlesen des Dateinamens kann man dann komfortabel mit einer OpenDialog-Komponente machen.
Falls das Image die .jpg datei nicht anzeigen will, dann lade im Objektispektor vom image einmal das Bild per Hand und nim es dann wieder raus.
Damit hat er die Fileendung dann angelegt.


Black_Fox - Di 15.04.08 16:25

erstmal zu der csv datei wenn ich die mit dem editor öffne wird jetzt was angezeigt, nun muss ich aber trotzdem noch was bei dem button ergänzen mit adoquery1.sql.text('Select * from Adressdaten')?


SmileySN - Di 15.04.08 19:56

Den Select-Befehl musst Du nicht in dem Buttonklick machen, Du musst nur sicherstellen, dass, wenn der Button geklickt wird, die richtigen Daten auch selektiert sind.
Wenn Du die Liste z.B. sortiert in die CSV-Datei schreiben willst, dann muss der Select Befehl dann "Select * from Adressdaten order by name" heißen.
Wenn Du Deine selektion nie änderst, kann das im Objektinspektor von der Query gemacht werden oder im FormShow.
Du kannst auch einige Buttons für die Sortierung machen.
Einen für name einen für Telefon einen für Ort usw.
Jeweils in den Buttonklick einfach das geänderte Select Statement reinschreiben, eben hinten dann mit "order by name" oder "order by telefon" oder "order by Ort".


Black_Fox - Di 15.04.08 20:13

k das mit den srtieren habsch jetzt, bloß nun hab ich noch das problem das ich die csvdatei mit xcel nicht öffnen kann nut mit nem editor?

achja und nochmal zu den bildern, hab ich das jetzt richtig verstanden das ich noch nen button mit opendialog machen soll, der den pfad des bildes in dem editfeld eintragen soll? und wenn ja dann so?:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.Button3Click(Sender: TObject);
begin
 try
  if OpenPicture.Execute then
     Image1.Picture.LoadFromFile(OpenPicture.FileName);
     ADOQuery1.Edit;
     OpenPicture.FileName := DBEDitBild.Text;
     ADOQuery1.Post;
 except
    ShowMessage('Bild konnte nicht geöffnet werden!');
end;
end;


Black_Fox - Fr 18.04.08 15:16

hab nochmal ne frage hab das jetzt mit in die buttons vor und zurück gemacht das das bild reingeladen wird zu dem der pfad angegeben wird nun bloß jetzt hab ich ne frage und zwar was wenn ich einen pfad angebe zu einem bild was gar nicht eistiert?

dann kommt ja ne exception aber kann ich das auch it einer messagebox umgehen? hab da schon einiges ausprobiert mit ner if schleife, aber hat gar nichts geklappt


zuma - Fr 18.04.08 15:58

bei einer Eingabe von Hand solltest du immer erst mit

Delphi-Quelltext
1:
if FileExists('DereingegebeneName') then                    

prüfen, ob's die Datei überhaupt gibt.
Das kannst du entweder dort machen, wo die Eingabe erfolgt
oder dort, wo du die Eingabe verwendest (...LoadFromFile).


Black_Fox - Fr 18.04.08 17:01

ah ok danke


SmileySN - So 20.04.08 16:37

Zu dem FileOpen Dialog meinte ich, dass Du es dem User beim Neuanlegen eines Datensatzes etwas einfacher machen kannst beim auswählen des Bildnamens.
Du kannst natürlich auch einfach nur eine DBEditBox nehmen und den Pfad+Dateinamen des Bildes per Hand reinschreiben.
Beim anzeigen des Bildes hat der Dialog nichts zu suchen.


Black_Fox - Mo 21.04.08 15:58

Hab das jetzt so mit den Bildern in formshow, meinem next button und meinem prior button:
bloß nun hab ich ein problem wenn ich den pfad eines bildes in das edit feld reingeschrieben habe und dann auf meinem button aktualisieren klicke der adoquery1.refresh enthält wird das bild nicht gleich angezeigt muss erst auf den button next oder so klicken


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.FormShow(Sender: TObject);
begin
Adoquery1.Open;
if Dbeditbild.Text = '' then
Image1.Picture.LoadFromFile('KeinBild.bmp')
else
if FileExists(Dbeditbild.Text) then
Image1.Picture.LoadFromFile(DBEditBild.Text)
else
form1.Show
end;


Dann hätte ich noch eine Frage und zwar kann ich den Pfad des Bildes automatisch irgendwie in das Edit Feld eintragen lassen mit hilfe eines Opendialoges oder so?


SmileySN - Di 22.04.08 14:39

>Dann hätte ich noch eine Frage und zwar kann ich den Pfad des Bildes automatisch irgendwie in das Edit Feld eintragen lassen mit hilfe eines Opendialoges oder so?

Nein *grins*

Aber mit ein paar Programmzeilen.

Delphi-Quelltext
1:
2:
OpenFileDialog.execute;
DBEdit1.Text:=OpenFileDialog.Filname;


Das macht man mit einenm Button hinter der DBEditBox.

Aber an Deinem Programmcode habe ich noch etwas zu bemängeln:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TForm1.FormShow(Sender: TObject);  
begin  

///////////// Hier eventuell noch das Standard Select Statement mit einbauen, der Übersichlichkeit halber und wenn man mal eine andere Selektion braucht, ist es hier im Quelltext am besten aufgehoben und damit auch gleich dokumentiert was man ausgewählt hat.
ADOQuery1.SQL.Text:='Select * From Adressen oder by Name';

Adoquery1.Open;  
if Dbeditbild.Text = '' then  
Image1.Picture.LoadFromFile('KeinBild.bmp')  
else  
if FileExists(Dbeditbild.Text) then  
Image1.Picture.LoadFromFile(DBEditBild.Text)  
else  

form1.Show  ///////////// Was soll das, versuchst Du hier eine Endlosschleife zu produzieren, du befindest dich bereits in Form1.Show, Wenn kein Dateiname da ist, dann eben Dein "KeinBild.bmp" anzeigen.

end;