AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Thema durchsuchen
Ansicht
Themen-Optionen

dynamisches Erstellen von Oberfläche und Speicherung in DB ?

Offene Frage von "IBExpert"
Ein Thema von Berndd · begonnen am 15. Jan 2004 · letzter Beitrag vom 8. Okt 2018
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
673 Beiträge
 
Delphi 10.4 Sydney
 
#11

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 3. Okt 2018, 18:20
Wir haben das damals über den Stream writer gemacht, mit TStream.ReadComponent und TStream.WriteComponent, bei ReadComponent aber drauf achten, dass er die komponenten neu erzeugt, falls du auf dem Formular schon was hast, was standardmässig da ist.
Den Stream dann als Blob in die DB schreiben.
Das setzt übrigends auch die events, wenn ich mich recht entsinne (schon 15 Jahre her)
  Mit Zitat antworten Zitat
rokli

Registriert seit: 21. Mär 2009
Ort: Rödinghausen
301 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 4. Okt 2018, 06:07
Der Vorteil, das über die Datenbankfelder zu machen liegt darin, das du die zum Speichern ggf eh brauchst und ich neue Felder in einer Tabelle ergänzen kann und die sofort beim nächsten Aufruf im Form sind.
Moin IBExpert!

Das kenn ich unter dem Schlagwort: data driven software.

Ich habe aber folgenden Frage dazu: Woher bekommst Du denn anschließend die Anwendung dazu? Das Du auf die Art und Weise Felder in die Anwendung bekommst, ist schon klar. Aber was machst Du mit dem Feld dann? Nehmen wir an Du erzeugst ein neues TEdit. Ok. Nun hat der Anwender ein neues Eingabefeld und schreibe da z. B. "Peter" rein. Und nun? Was macht die Software nun mit "Peter"? Wie legst Du diese Information nun beispielsweise in einer DB ab, ohne Dein Programm zu ändern und ohne es neu zu compilieren? Irgendwoher müsste ja nun ein INSERT oder ein UPDATE kommen, der den "Peter" in die DB schreibt - oder?

Gruß
Rolf
wenn nicht anders angegeben, schreibe ich zu D7, XE2 und MS SQL - ansonsten fragen Sie ihren Administrator oder einen Operator. Update 06/2020: Delphi 10.4 Sydney
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 4. Okt 2018, 06:55
Das sind 2 verschiedene Dinge. Das eine ist es die Oberflächenelemente aus einer Datenbank zu Streamen.
Datenbindung ist ja eine andere Baustelle.
Hier unterscheidet sich eine Oberfläche, welche sich aus einer DB erzeugt wurde nicht von einer, welche aus einer Ressource der Exe geladen wird.
Markus Kinzler
  Mit Zitat antworten Zitat
mbulm1

Registriert seit: 3. Okt 2018
24 Beiträge
 
#14

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 4. Okt 2018, 14:51
Hallo Jungs,

ich muss meine Fragen etwas aufteilen - sonst kann ich die Antworten nicht mehr zuordnen!

1. Ihr habt gute Ideen und danke für Eure Hinweise - aber ich habe noch keinen Plan - wie ich zum Beispiel ein "ONCLICK"-Ereignis in der DB abspeichere?
Eigentlich muss ich den Quellcode doch vorher schon in einer Procedure ablegen und dann dem Button diese Procedure zuweisen - aber ich muss vorher schon wissen - was der Button machen soll - oder?

2. Gibt es bei Lazarus auch ein TDataset oder was Vergleichbares - ich finde es nicht!

3.
Wir haben das damals über den Stream writer gemacht, mit TStream.ReadComponent und TStream.WriteComponent, bei ReadComponent aber drauf achten, dass er die komponenten neu erzeugt, falls du auf dem Formular schon was hast, was standardmässig da ist.
Den Stream dann als Blob in die DB schreiben.
Das setzt übrigends auch die events, wenn ich mich recht entsinne (schon 15 Jahre her)
Wie geht das genau?

Danke vorab!
Beste Grüße
mbulm1
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#15

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 4. Okt 2018, 14:56
Zitat:
ich muss meine Fragen etwas aufteilen - sonst kann ich die Antworten nicht mehr zuordnen!
Am Besten in einem neuen Thread.
Markus Kinzler
  Mit Zitat antworten Zitat
mbulm1

Registriert seit: 3. Okt 2018
24 Beiträge
 
#16

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 4. Okt 2018, 17:09
Die Punkte gehören aus meiner Sicht aber schon hier dazu - oder?

Außerdem sehe aktuell NICHTS - wo ich einen Thread erstellen kann!?
Warum ist das so?

Beste Grüße

mbulm1
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#17

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 4. Okt 2018, 17:23
Auf Delphi-Praxis klicken (zur Übersicht).

Auf "Sonstige Fragen zu Delphi" klicken.

Oben links auf "Neues Thema erstellen" klicken.
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
646 Beiträge
 
FreePascal / Lazarus
 
#18

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 5. Okt 2018, 17:49
[QUOTE=rokli;1414823]
Ich habe aber folgenden Frage dazu: Woher bekommst Du denn anschließend die Anwendung dazu? Das Du auf die Art und Weise Felder in die Anwendung bekommst, ist schon klar. Aber was machst Du mit dem Feld dann? Nehmen wir an Du erzeugst ein neues TEdit. Ok. Nun hat der Anwender ein neues Eingabefeld und schreibe da z. B. "Peter" rein. Und nun? Was macht die Software nun mit "Peter"? Wie legst Du diese Information nun beispielsweise in einer DB ab, ohne Dein Programm zu ändern und ohne es neu zu compilieren? Irgendwoher müsste ja nun ein INSERT oder ein UPDATE kommen, der den "Peter" in die DB schreibt - oder?
Gruß
Moin, ja, dafür ist jahreslanges Know How erforderlich ... (nein, blödsinn, eigentlich genau so einfach zu erklären , daher versuch ich das mal)

Stellen wir uns vor, wir haben eine einfache Tabelle Mitarbeiter, bestehend aus

create table mitarbeiter
(ID Int64,
Vorname Varchar(80),
Nachname Varchar(80),
geburtsdatum date)


Deine Basis Software, welches die db öffnet, beginnt also einfach mit dem dynamischen erstellen eines Menuitems im Mainmenu oder popupmenu mit der Caption Mitarbeiter, weil es in der DB eine solche Tabelle gibt (in firebird einfach rdb$relations durchsuchen nach Einträgen ohne $ im Namen). Den Menuitem nennst du so wie die Tabelle, nur mit einem prefix, zB mnuMITARBEITER.

Der Menuitem bekommt ein Click Event, das für alle anderen dynamisch erzeugten Menuitem dazu auch benutzt wird

Code:
var mnu:TMenuItem;
....
begin
...
qry.sql.text:='select distinct rdb$relation_name from rdb$relations where rdb$relation_name not containing ''$''';
qry.open;
while not qry.eof do
begin
  mnu:=TMenuItem.create(popupmenu1);
  popupmenu1.items.add(mnu);
  mnu.name:='mnu'+qry.fields[0].AsString;
  mnu.caption:=qry.fields[0].AsString;
  mnu.onclick:=mnuClick;                      //dafür kannst du ein bereits existierendes click event nehmen oder einfach neu erstellen in gleicher Syntax wie das automatisch erstellte aussehen würde
  qry.next;
end
qry.close;
end;

procedure TForm1.mnuClick(Sender: TObject);
var tn:String;
begin
  tn:=copy(TMenuitem(sender).name,4,31);
  qry.sql.text:='select * from '+tn;
  qry.open;
  while not qry.eof do
  begin
    //hier kannst du nun für jeden zeile einen eintrag in eine Listbox machen, bei Firebird könntest du dafür eine Computed Feld benutzen, das vorname udn Nachname kombiniert anzeigt
    //alternativ auch einfach ein datasource angebundenes dbgrid nehmen, das mach ich aber nicht
    dataObj:=TDataObj.create;
    dataObj.id:=fields[0].AsInteger;
    //hier kommt dann später noch mehr in der Erklärung weiter unten bei der Erklärung getDataFromQry
    dataObj.getDataFromQry;
    listbox1.items.addObject(dataObj.FullText,dataObj);
    qry.next;
  end
  qry.close;
end
Soweit sollte jeder mit grundlegenden Delphi/Lazarus Kenntnissen das eigentlich hinbekommen. Ich hab mir dabei erlaubt das einfach so runter zu tippen.

getDataFromQry macht nun folgendes bei mir (die instanzen der TStringlist werden im Constructor von TDataObj instanziiert)

-jedes TDataObj hat eine Eigenschaft fn (fieldnames, als einfach 0 ist ID, 1 ist VORNAME, 2 ist NACHNAME, 3 ist GEBURTSDATUM) und wird gefüllt aus qry.fields[i].Fieldname

-jedes TDataObj hat eine Eigenschaft cn (classnames, als einfach 0 ist TIntegerField, 1 ist TStringField, 2 ist TStringField, 3 ist TDateField) und wird gefüllt aus qry.fields[i].classname

-jedes TDataObj hat eine Eigenschaft val (values, als einfach 0 ist fields[0].AsString, 1 ist fields[1].AsString, 2 ist fields[2].AsString, 3 ist fields[3].AsString) und wird gefüllt aus qry.fields[i].AsString

Damit hast du schon mal unabhängig von den Feldern der Tabelle alles im Speicher und musst nicht mal das dataset offen halten.

Ein ListBox.Onlick kann nun folgendes machen

Code:
dataObj:=TDataObj(TListbox(sender).objects[TListbox(sender).itemindex]);
dataobj.ShowDataOnSbx(sbx:TScrollBox);
was macht nun ShowDataOnSbx?

Die Anzahl der Felder hast du in dataobj.fn.count, du kannst also in einer Routine ShowDataOnSbx
einfach durch alle Feldnamen durchgehen und passend zum Eintrag in cn[i] für das ID Feld ein Label erzeugen (nicht editierbar, weil aus db kommend, meist sogar unsichtbar, für alle TStringFields je ein TEdit und dessen Eigenschaft Text mit dem Inhalt aus val[i] füllen, den Namen zB aus dem prefix edt und dem feldnamen aus fn[i] erzeugen. Bei Geburtsdatum wäre das dann ein TDateEdit mit edt.date:=StrToDate(val[i]);
Außerdem erzeuge ich auch automatisch zu jedem Control noch ein TLabel mit der Caption aus FN[i]

Die Positionen gehen in Phase 1 einfach von oben nach unten, später dann kommt der beschrieben Designmode dazu und die Positionierung kommt dann eben optional aus
der db (siehe oben)

Damit hast du nun die Edit felder mit passenden daten gefüllt und nicht nur beim Listbox onclick sondern auch beim navigieren in der Listbox werden die
ggf vorhandene Objekte auf der Scrollbox entweder gelöscht und neu erzeugt oder mit sbx.findcomponent gesucht, weil der name ja immer identisch
ist innerhalb der gleichen tabellenfelder. Technisch macht eine datasource das nicht viel anders, ist aber auf offene Datasets angewiesen.

Nun aber der Haupt Aspekt deiner Frage: Ich änder was und wie geht der Kram wieder zurück in die db?

Bei mir bekommen alle editierbaren Controls ein zentrales onchange event, wodurch ich sofort beim editoren weiss, das ich speichern sollte, daher wird in dem moment
auch sofort ein Speichern Button enabled. Der Speichern vorgang selber erstellt aus dem Table name und den Feldnamen nur für jeden Tabelle ein sql zusammen, was
in etwa wie folgt aussieht

Code:
UPDATE OR INSERT INTO MITARBEITER(ID,VORNAME,NACHNAME,GEBURTSDATUM) VALUES (:ID,:VORNAME,:NACHNAME,:GEBURTSDATUM) matching (ID);
Wie du den String zusammenbaust sollte dir klar sein,wenn du noch mal FN[i] durchschaust. Damit nix verloren geht wird beim navigate immer gespeichert, wenn
der speichern button enabled ist.

für jede zeile in FN[] von 0 bis FN.count-1 suchst du nun auf dem sbx mit findcomponent nach dem edt und schreibst das was da drin steht wieder in val[i]

Anschliessend bekommt die query die parameter werte in qry.params[i].Value:=val[i] und mit qry.execsql schreibst du das in die DB.

für löschen kannst du einfach delete from ... where id=:ID machen und nur den VAL[0] benutzen

für neu Anlegen eines Datensatzes erzeugst du ein neues leeres TDataObj, holst dir über eine GetNeueID Methode einen neue unbenutzten
Generator Wert und mit dem anschliessenden speichern und erneutem lesen würden auch bereits in der Datenbank existierende Trigger
ausgeführt sein und vorgabewerte aus der DB bereits eingetragen sein.

Binary Blobs behandel ich sowieso immer anders, aber mit Textblobs geht genau das gleiche Verfahren. Ein Blob Subtype Text erstellen
die meisten Queries als TMemoField und beim TMemoField in cn[i] kannst du dann eben ein TMemo als Kompnente benutzen.

Das schöne an dem Konzept ist, das du nun mit

Code:
alter table mitarbeiter add beruf varchar(40);
in der Datenbank ein neues Feld anlegen kannst und das beim nächsten Klick auf den o.a. Menuitem schon angezeigt wird, ohne das
du an deiner exe irgendwas anpassen musst.

Auch eine neue Tabelle wäre mit dem o.a. Verfahren sofort nach dem Neustart der exe als neuer menuitem verfügbar.

Prozesse wie buchen von daten, umwandeln von lieferscheinen in rechnungen, etc. werden bei mir eh immer in der DB realisiert, weil
es immer viel schneller ist als im externen client.

Das es so einen Prozess gibt, kann man daran umsetzen, das man passende zum tabellen namen
einfach Stored procedures in der Datenbank mit entsprechenden Namenskonventionen erzeugt und denen immer nur die
ID vom aktuell geöffneten Datensatz als Parameter übergibt, den Rest kann sich die SP dann selber zusammensuchen. Ggf erforderliche
zusatzparameter können dynamisch abgefragte Inputparameter in der SP sein, und alle SP, zu denen der Anwender Rechte hat, scheinen
eben als Menuitem, oder als Button oder wie auch immer, aber auch alles dynamisch erzeugt.

Ein passender name um einen Lieferschein in eine Rechnung zu übernehmen, wäre dabei zum Beispiel der SP Name LIEFERSCHEIN_RECHNUNG
udn bei der Anzeige von Lieferscheinen werden für alle SP, die mit LIEFERSCHEIN beginnen, button dynamisch erzeugt. Ob der
Lieferschein schon berechnet wurde, ob es einzelrechnungen gibt, einen abweichenden Rechnungsempfänger, oder Sammelrechnungen
oder was auch immer, ist nicht Aufgabe vom Front End. Das macht die SP und niemand anders.

Das schöne an dem Konzept, mit dem ich seit mittlerweile 7 Jahren eine schon ziemlich komplexe kundenspezifsche Anwendung für
mehrere Fertigungsunternehmen, aber auch für den Eigenbedarf erstellt habe, ist, das es relativ egal ist, mit der Front End
umgesetzt wird.

Delphi egal in welcher Version eignet sich dafür genau so gut wie lazarus und bei den beiden kannst du dafür sogar noch den code
parallel benutzen. Mit TMS Webcore geht das auch als Webapplication, könnte aber auf Basis der DB Rules auch direkt mit php, javascript,
c# oder sonstwas umgesetzt werden.

Die Referenz dafür ist bei mir halt immer die DB und mit Tools wie IEBxpert und Firebird kannst du in der DB auch sehr komplexe
Aufgaben lösen und das ganze steht dir trotzdem nicht nur als ein monolithischer Quellcode für alle Kunden zur Verfügung.
Jeder Kunde darf selber entscheiden, was er haben möchte und nach entsprechender Einweisung in die DB kann er auch selber
Reports erstellen oder anpassen, oder sogar Tabellenfelder ergänzen oder sogar ganz neue Tabellen erstellen, ohne mich dafür
fragen zu müssen. und ich muss nicht überlegen, wie ich den ein Formular für alle aufbaue mit dutzende seiten auf Page
Controls, damit alle Kunden ihre Wünsche erfüllt bekommen. Komplizierte Events im Front End versuch in zu evrmeiden,
aber technisch lassen die sich auch aus der DB mit Hilfe einer der oben genannten Scripting engine realisieren.

Customizing Beispiel:

Wenn ein Kunde bei jedem Lieferschein spezielle Barcode Etiketten auf ganz bestimmten Druckern in bestimmten Mengen
haben möchte, muss ich dafür nicht mal den Quellcode des Frontsends anpassen, sondern erstellen zum Beispiel nur
für diesen Kunden in der DB eine Definitionstabelle seine Parameter, einen Trigger, der daraus bei neuen Lieferscheinen
einen Job in eigene Jobtabellen erstellt und ein Script zB auf Basis von IBExpert, das dann aus den Jobs in den
Tabellen serverseitig die definiterten Printqueus füllt, so das ich mich im Front end auch nicht damit
herumärgern muss, ob der nun einen funktionierenden Druckertreiber auch für win7 oder win10 oder sonst was hat ...

So, feddich, mal wieder länger geworden, aber ich hoffe das hilft ein wenig zum Verständnis.

Wenn Interesse an der Technik besteht, können wir dazu auch gerne Firmenschulungen oder bei ausreichend
Interesse auch öffentliche Schulungen anbieten (Meldet euch dafür ggf einfach bei mir hklemt@ibexpert.com)

Evtl. mach ich aus dem Front End nach einem Code Cleanup nächstes Jahr auch mal ein Open Source Projekt
mit einigen Beispieldatenbanken. Kunden, die bei uns Schulungen machen, können das ggf dann schon ab
der Schulung zur weiteren Analyse bekommen. Der Front End ist in Lazarus programmiert, es ist aber eigentlich
nichts drin, was nicht auch in Delphi ähnlich umsetzbar ist.
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
IBExpert and Firebird Power Workshops jederzeit auch als Firmenschulung
  Mit Zitat antworten Zitat
mbulm1

Registriert seit: 3. Okt 2018
24 Beiträge
 
#19

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 8. Okt 2018, 15:08
[QUOTE=IBExpert;1415044][QUOTE=rokli;1414823]
Evtl. mach ich aus dem Front End nach einem Code Cleanup nächstes Jahr auch mal ein Open Source Projekt
mit einigen Beispieldatenbanken. Kunden, die bei uns Schulungen machen, können das ggf dann schon ab
der Schulung zur weiteren Analyse bekommen. Der Front End ist in Lazarus programmiert, es ist aber eigentlich
nichts drin, was nicht auch in Delphi ähnlich umsetzbar ist.
Das wäre mehr als GENIAL und an einer Schulung wäre ich auch interessiert!
DANKE und Beste Grüße
mbulm1
  Mit Zitat antworten Zitat
mbulm1

Registriert seit: 3. Okt 2018
24 Beiträge
 
#20

AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?

  Alt 8. Okt 2018, 16:38
1. Ihr habt gute Ideen und danke für Eure Hinweise - aber ich habe noch keinen Plan - wie ich zum Beispiel ein "ONCLICK"-Ereignis in der DB abspeichere?
Eigentlich muss ich den Quellcode doch vorher schon in einer Procedure ablegen und dann dem Button diese Procedure zuweisen - aber ich muss vorher schon wissen - was der Button machen soll - oder?
Hallo nochmal - gibt es dafür auch eine Lösung oder habe ich was überlesen?
Danke!
BG MB
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:15 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz