Discussion:
DBGrid - bitte Kristallkugel herrichten
(zu alt für eine Antwort)
Nicole Wagner
2011-03-21 12:14:12 UTC
Permalink
Hallo User,

mein Projekt entwickelt sich praechtig.
Danke allen, die mir mit Rat zur Seite gestanden haben.

Ich habe jetzt mein DBGrid, das intensiv bearbeitet wird.
Dort wird mehrfach gefiltert, dort werden Spalten gerechnet und es
werden die Zeilen bunt markiert.

Alles, was schon onCreate gefiltert, berechnet und gezeichnet wird,
passt sofort. D.h. das Grid sieht aus, wie ich will.

Was hingegen zur "spaeteren" Laufzeit also auf Menu-Trigger veranlasst
wird, wird nicht sofort dargestellt. Ich klicke z.B. "Zeilen
ausblenden" oder "dieses fuer jenes berechnen". Ersteres soll im
Filter-Ereignis bearbeitet werden, letzteres im Calc Ereignis.

Alle Ereignisse arbeiten auch "zur späteren Laufzeit" wunschgemaess.
Allerdings SEHE ich das erst nach einigen Mausklicks.

Die Anzeige wird dann richtig, wenn ich mit dem Scrollbar einmal mein
DBGrid rauf- und runterscrolle. Danach erst stehen erst die Einträge in
den Spalten und danach erst sind (weitere) Zeilen ausgeblendet.

Und jetzt kommt die Kristallkugel ins Spiel: Ich weiss nicht, welchem
Event ich mit diesen Scroll-Mausklicks nachhelfe. Bzw. wie ich dieses
ausloesen kann.

Probiert habe ich bis jetzt: Form.Refresh, Autocalc auf true zu setzen,
das CalcEvent oder das FilterEvent explizit aufzurufen. Nix.

Mein DB Grid aktualisiert sich nach wie vor nur nachdem es gescrollt
wurde. Einmal aus dem Bildschirm raus und wieder rein - passt perfekt.

Wie erreiche ich den Effekt auch ohne Scrollen?

(bitte kein DisableControls, das muss aktiv bleiben)

Liebe Gruesse,
Nicole
Joe Galinke
2011-03-21 14:33:14 UTC
Permalink
Hallo Nicole,

vorab eine ernst gemeinte Bitte zur Wahl des Betreffs. Suche bitte eine
einigermaßen passende Kurzbeschreibung aus. Deine (zumindest früher) gerne
verwendeten Formulierung "für Experten" u.ä. nützen weder Dir noch den
denjenigen die antworten wollen, aber "Kristallkugel" ist nicht besser.

Du stellt doch Fragen auf die Du eine Antwort erhoffst. Warum machst Du es
dann möglichen Antwortenden nicht so leicht wie nur irgend möglich?

"DbGrid, Ansicht aktualiseren" wäre z.B. ein Kandidat.

Weiter unten wirst Du lesen, dass es mit dem Grid aber nichts zu tun hat.
:-)
Post by Nicole Wagner
Was hingegen zur "spaeteren" Laufzeit also auf Menu-Trigger veranlasst
wird, wird nicht sofort dargestellt. Ich klicke z.B. "Zeilen
ausblenden" oder "dieses fuer jenes berechnen". Ersteres soll im
Filter-Ereignis bearbeitet werden, letzteres im Calc Ereignis.
Du meinst OnFilterRecord?

Ich vermute, Du schaltest DataSet.Filtered nicht mal auf False und wieder
auf True. Die Umschaltung braucht es aber.

Bzgl. OnCalcFields schaue Dir bitte nochmal die OH dazu an. Den Teil hatten
wir auch bereits.

---
OnCalcFields is triggered when:
A dataset is opened.
A dataset is put into dsEdit state.
A record is retrieved from a database
---

Das passiert in Deinem Szenario aber nicht. Abhilfe schafft u.a.
DataSet.Refresh. Wenn Du, wie ich vermute, TIBDataSet verwendest, dann
musst Du die Property RefrshSQL entsprechend füllen. TIbDataSet kann Dir
dabei über das Eigenschaftsmenü (rechte Maustaste / Dataset Editor /
Generate SQL) helfen.
Post by Nicole Wagner
(bitte kein DisableControls, das muss aktiv bleiben)
Ich wage zu unterstellen, dass Du nicht weiß worum es sich dabei handelt.

Warum soll das nicht empfohlen werden? Es würde eh nichts nützen.

Was heißt, es soll so bleiben? Wenn diese Funktion zum Einsatz kommt, dann
sicherlich (fast) immer mit kurzfristig später erfolgter Wiederaktivierung.

DisableControls soll lediglich verhindern, dass während bestimmter Vorgänge
die den Datensatzzeiger verändern datenanzeigende Controls, wie z.B. das
DbGrid, nicht wild die Ansicht ändern. Deshlab erfolgt die Verwendung
eigentlich immer nach folgendem Muster;

DataSet.DisableControls;
try
//Beispiel
DataSet.First;
while not DataSet.Eof do begin
//Was auch immer
DataSet.Next;
end;
finally
DataSet.EnableControls;
end;


So, wenn man nun aber anschließend auf dem gleichen Datensatz stehen möchte
wie vorher verwendet man Bookmarks oder merkt sich den Wert des PKs und
versucht mit einem DataSet.Locate vor dem FINALLY dorthin zu navigieren.

Fazit:
a) DisableControls/EnableControls würde Dir im konkreten Fall also gar
nicht helfen, hätte andererseits aber auch keine negativen Auswirkungen.

b) Du siehst, das ist wieder ein Fall in dem das Grid selbst gar keine
Rolle spielt. Dieses schlichte Db-Grid hat nichts mit den Zeilen zu tun die
angezeigt werden, nur mit der Art der Darstellung (Schrift, Farbe,
Hintergrund etc.).

Sollte es notwendig sein sich den aktuellen Datensatz zu merken und
anschließend dorthin zu navigieren betrachte ich diesen "Mehraufwand" an
Arbeit als so minimal, dass er keinerlei Entscheidungsüberlegung bedarf.


Gruß, Joe
--
Nicole Wagner
2011-03-23 12:09:46 UTC
Permalink
Joe Galinke wrote:



Danke fuer Deine Antwort.
Post by Joe Galinke
"DbGrid, Ansicht aktualiseren" wäre z.B. ein Kandidat.
Weiter unten wirst Du lesen, dass es mit dem Grid aber nichts zu tun
hat. :-)
Das hatte ich schon geahnt, deshalb habe ich dieses betreff genau nicht
gewaehlt, ;-)
Post by Joe Galinke
---
A dataset is opened.
A dataset is put into dsEdit state.
A record is retrieved from a database
---
Das passiert in Deinem Szenario aber nicht. Abhilfe schafft u.a.
DataSet.Refresh. Wenn Du, wie ich vermute, TIBDataSet verwendest, dann
musst Du die Property RefrshSQL entsprechend füllen. TIbDataSet kann
Dir dabei über das Eigenschaftsmenü (rechte Maustaste / Dataset
Editor / Generate SQL) helfen.
ich haenge schon hier.

1)
Ich habe leider nicht TIBDate Set, sondern Dataset aus der Gruppe
"Zugriff."

2) Ein Refresh loest eine Exception aus:
"EIDClientError: Zeile kann nicht aktualisiert werden (keine
Aktualisierungs-Abfrage)".

Du schreibst aber etwas von RefreshSQL, das ich nicht gemacht habe.
Ich glaube naemlich nicht, dass ich das brauche fuer meinen speziellen
Zweck. Denn ich will nur die berechneten Felder aktualisieren, nicht
die via Query abgefragten.

Meine Aufgabe ist die:
Mein DBGrid ist gefuellt und listet mir viele Angaben, abgefragte und
berechnete. Calc hat getan, was es sollte und Filter und Draw auch.

Jetzt klicke ich auf ein Menue.
Dieser Click bewirkt, dass eine "nicht-Visuelle Query" (also gehoert
nicht zum Formular oder Thema...) von ein paar dutzend Unit verarbeitet
wird. Alles fuelle ich in ein Array.

Ich habe also 2 Mengen als Ergebnis:
Ein gefuelltes record-Array und mein DBGrid. Eine bestimmte Spalte
meines Records entspricht einer bestimmten Spalte meines DBGrids. Calc
wird wieder aktiv und traegt das Rechenergebnis aus dem Record in die
korrekte Spalte des DBGrids (erste Aktualisierung, die nur nach
Scrollen stattfindet).

Jetzt haben manche DBGrid-Zeilen ein Rechenergebnis und manche nicht.
Jene, die keines haben, will ich ausblenden. Das tut Filter.
(zweite Aktualisierung, die nur nach Scrollen stattfindet).

Wann ich Filter ein und ausschalten soll, weiss ich nicht so genau.
Wo ICH es gemacht habe, war es falsch, denn es hat seine Aufgabe des
Ausblendens nicht mehr erfuellt.


Nicole


PS: Wenn dieser Hinweis, die Sache nur verwirrt, bitte einfach
ignorieren:
Ich habe die Verarbeitung der "nicht-visuellen Unit" so gesteuert, dass
stets ein Array an Calc uebergeben wird. Calc verarbeitet das array von
Low bis High. Dieses Array hat grundsaetzlich die Laenge Null und in
Calc passiert nichts (bzw. nur eine Restaufgabe), weil Low to High Null
bleibt.
Mein Menue-Click tut im Grunde wenig anderes, als das Array zu fuellen,
das Calc zur Verarbeitung schickt.
Joe Galinke
2011-03-23 14:26:47 UTC
Permalink
Hallo Nicole,
Post by Nicole Wagner
Post by Joe Galinke
"DbGrid, Ansicht aktualiseren" wäre z.B. ein Kandidat.
Weiter unten wirst Du lesen, dass es mit dem Grid aber nichts zu tun
hat. :-)
Das hatte ich schon geahnt, deshalb habe ich dieses betreff genau nicht
gewaehlt, ;-)
Es wäre immer noch treffender und hilfreicher gewesen als der aktuelle
Betreff.
Post by Nicole Wagner
1)
Ich habe leider nicht TIBDate Set, sondern Dataset aus der Gruppe
"Zugriff."
Eine Komponente die Du aufs Form oder Datamodule ziehst mit Klassenname
"DataSet"? Ich denke, Du irrst.

Der Klassenname, den Dir der OI ja auch anzeigt, wird sicherlich mit T
beginnen.
Post by Nicole Wagner
"EIDClientError: Zeile kann nicht aktualisiert werden (keine
Aktualisierungs-Abfrage)".
Ich vermute, es handelt sich um einen EIBClientError (B statt D). Wenn ja,
dann tippe ich wieder auf TIBDataSet oder einen Verwandten davon.
"keine Aktualisierungs-Abfrage" klingt auch passend zu einer nicht
gesetzten RefreshSQL-Property der Komponente.
Post by Nicole Wagner
Du schreibst aber etwas von RefreshSQL, das ich nicht gemacht habe.
Ich glaube naemlich nicht, dass ich das brauche fuer meinen speziellen
Zweck. Denn ich will nur die berechneten Felder aktualisieren, nicht
die via Query abgefragten.
Du kannst glauben oder es einfach mal probieren. Was hälst Du davon? Es
geht schneller als ein neues Posting zu schreiben und hier abzusetzen _und_
Du lernst etwas dabei. Wenn ich Unrecht habe bleibt Dir der Lerneffekt. :-)
Post by Nicole Wagner
Jetzt klicke ich auf ein Menue.
Dieser Click bewirkt, dass eine "nicht-Visuelle Query" (also gehoert
nicht zum Formular oder Thema...) von ein paar dutzend Unit verarbeitet
wird. Alles fuelle ich in ein Array.
Wenn ich Dich richtig verstehe wird dieses Array in einem (vielleicht sogar
etwas längerem) Aufwasch gefüllt. Genau jetzt wäre es ein passender Moment
Die Refresh-Methode Deines DataSets aufzurufen. Du siehst, bis Du klarer
beschreibst was Du hast bleibe ich dabei.

Dadurch, dass die Datenmenge neu abgefragt wird erübrigt sich
wahrscheinlich sogar der umschaltende Aufruf von
.Filtered:=False/Filtered:=True des DataSets. Probiere es einfach erst
einmal ohne diesen aus.
Post by Nicole Wagner
stets ein Array an Calc uebergeben wird.
Was für ein CALC? Du meinst nicht das OnCalcFields-Event, sondern eine
eigene Methode/Funktion/Prozedur?


Gruß, Joe
--
Nicole Wagner
2011-03-24 14:35:45 UTC
Permalink
Post by Joe Galinke
Post by Nicole Wagner
1)
Ich habe leider nicht TIBDate Set, sondern Dataset aus der Gruppe
"Zugriff."
Eine Komponente die Du aufs Form oder Datamodule ziehst mit
Klassenname "DataSet"? Ich denke, Du irrst.
Der Klassenname, den Dir der OI ja auch anzeigt, wird sicherlich mit T
beginnen.
Dann wissen wir beide, dass wir von TDataSet sprechen, ;-)

"das normale" halt.
Wenn man ein Anfaenger-Tutorial liest, steht dort: "Sie brauchen ein
Form und ziehen dorthin....TDataSet...."

(es mit IBDataSet zu ersetzen wuerde einen Giganto-Aufwand darstellen
schaetze ich)
Post by Joe Galinke
Post by Nicole Wagner
"EIDClientError: Zeile kann nicht aktualisiert werden (keine
Aktualisierungs-Abfrage)".
Ich vermute, es handelt sich um einen EIBClientError (B statt D).
Wenn ja, dann tippe ich wieder auf TIBDataSet oder einen Verwandten
davon. "keine Aktualisierungs-Abfrage" klingt auch passend zu einer
nicht gesetzten RefreshSQL-Property der Komponente.
Das finde ich auch.
Ich habe nur ein Problem. Ich finde so ein Property nicht im
Objekt-Inspektor. Und weiss auch nicht, wie ich es verarbeite.

Ein
Form.IBQuery.DataSource.DataSet.Refresh;
(meine Var-Namen habe ich mal weggelassen)
wird von der Syntax her akzeptiert, loest aber zur Laufzeit eine
Schutzverletzung aus.

Form.IBQuery.SQL.*
kennt kein Refresh
Post by Joe Galinke
Du kannst glauben oder es einfach mal probieren. Was hälst Du davon?
Theoretisch viel.
Praktisch siehe oben.
Das Property habe ich naemlich schon gestern nicht gefunden.
Post by Joe Galinke
Wenn ich Dich richtig verstehe wird dieses Array in einem (vielleicht
sogar etwas längerem) Aufwasch gefüllt. Genau jetzt wäre es ein
passender Moment Die Refresh-Methode Deines DataSets aufzurufen. Du
siehst, bis Du klarer beschreibst was Du hast bleibe ich dabei.
ja klar.
In diese MenueClick-Methode hatte ich es auch geschrieben.
Aber wie gesagt, alle Refresh', die auf die Query zugreifen, loesen mir
eine Schutzverletzung aus.
(*sich am Kopf krazt* Warum eigentlich?)

Das Setzten von active true/false
hingegen blieb ohne den gewuenschten Erfolg.
Post by Joe Galinke
Dadurch, dass die Datenmenge neu abgefragt wird erübrigt sich
wahrscheinlich sogar der umschaltende Aufruf von
.Filtered:=False/Filtered:=True des DataSets. Probiere es einfach erst
einmal ohne diesen aus.
Bitte nicht!
Das waere ganz schlimm.
Denn bevor die Zeilen gefiltert werden, muessen sie noch als
Lookup-Quelle fuers naechste DBGrid herhalten.
Post by Joe Galinke
Post by Nicole Wagner
stets ein Array an Calc uebergeben wird.
Was für ein CALC? Du meinst nicht das OnCalcFields-Event, sondern eine
eigene Methode/Funktion/Prozedur?
ich meine mit "Calc" das OnCalcFieldsEvent.
Je mehr ich erahne, wozu es dient, desto nuetzlicher erscheint es mir
und desto mehr Aufgaben gebe ich dorthin.



Liebe Gruesse,
Nicole
Joe Galinke
2011-03-25 12:27:50 UTC
Permalink
Hallo Nicole,
Post by Nicole Wagner
Post by Joe Galinke
Der Klassenname, den Dir der OI ja auch anzeigt, wird sicherlich mit T
beginnen.
Dann wissen wir beide, dass wir von TDataSet sprechen, ;-)
Nein. Ich weiß, dass ich ganz sicher nicht davon spreche und vermute recht
stark, dass Du Dich irrst.

Vorab möchte ich einige Vermutungen und Annahmen formulieren:

- Du verwendest Delphi 2010 (wobei die Unterschiede für das aktuelle
Problem wohl vernachlässigbar sind)

- Du arbeitest mit den Interbase-Komponenten wie TIBDatabase und TIBSQL.

- Du hast Deine Dataset-Komponente per Maus auf ein Formular oder
Datenmodul gezogen.

Bitte korrigiere mich in allen Punkten in denen ich falsch liege.

Ich habe z.B. noch nie ein Delphi gesehen welches in der Komponentenliste
ein schlichtes TDataset anbot, aber dafür waren fast alle Komponenten wie
TxxxDataset, TxxxTable und ähnliche _Abkömmlinge_ von TDataset. Das
bedeutet, dass es sich jeweils um TDatasets handelt (so wie auch Dein
Dataset ein TDataset sein wird) und sie damit alles können und anbieten was
eben TDataset im Programm hat. Darüber hinaus aber bieten sie natürlich
weitere Möglichkeiten.

Sollte ich also mit meinen Grundannahmen nicht vollständig daneben liegen,
dann bitte ich Dich noch einmal, Deine Dataset-Komponente im Designmodus zu
markieren und Dir anzuschauen welchen Klassennamen der OI anzeigt. Ganz
oben steht der Name Deiner Komponente (MyQuery oder so) und rechts daneben
der Klassenname. Bitte, schau mal nach.
Post by Nicole Wagner
"das normale" halt.
Wenn man ein Anfaenger-Tutorial liest, steht dort: "Sie brauchen ein
Form und ziehen dorthin....TDataSet...."
Ja, das ist dann irgendein TDataset-Nachfahre.
Post by Nicole Wagner
Form.IBQuery.DataSource.DataSet.Refresh;
(meine Var-Namen habe ich mal weggelassen)
wird von der Syntax her akzeptiert, loest aber zur Laufzeit eine
Schutzverletzung aus.
IBQuery: TIBQuery --> TIBCustomDataSet --> TWideDataSet --> TDataSet

Dein IBQuery ist ein Nachfahre von TDataSet, hat aber wirklich kein
RefreshSQL.

Mir kommt nur Dein Aufruf sehr seltsam vor. Worauf zeigt denn
IBQuery.DataSource.DataSet? Ich denke mal, es zeigt ins Leere. Das würde
dann auch die AV erklären.

Das DataSet von dem Du redest, ist das nicht eben jene IBQuery selbst? Wenn
ja, welches Dataset willst Du über IBQuery.DataSource.DataSet ansprechen?

Anders gefragt:
Hat diese IBQuery überhaupt eine Datasource zugeordnet oder gibt es nicht
eher eine Datasource der eben jene IBQuery zugeordnet wird?

IBQuery kennt übrigens auch ein Refresh.

Also, nicht weil ich rechthaberisch sein möchte, sondern zur Verdeutlichung
wie vernebelnd Du oft beschreibst, weise ich nochmal darauf hin, dass Du
nicht einfach ein TDataset hast. Im Moment gehe ich von einer TIBQuery aus.
Aber eben weil Du immer von Dataset sprachst, vermutete ich, eben wegen des
angenommenen Einsatzes der Interbase-Komponenten, ein TIBDataset. Das gibt
es nämlich. Es kennt RefreshSQL und trägt halt Dataset im Namen.
Post by Nicole Wagner
Post by Joe Galinke
Dadurch, dass die Datenmenge neu abgefragt wird erübrigt sich
wahrscheinlich sogar der umschaltende Aufruf von
.Filtered:=False/Filtered:=True des DataSets. Probiere es einfach erst
einmal ohne diesen aus.
Bitte nicht!
Das waere ganz schlimm.
Denn bevor die Zeilen gefiltert werden, muessen sie noch als
Lookup-Quelle fuers naechste DBGrid herhalten.
Das hört sich alles verdammt chaotisch an, ich kann mir im Moment kein Bild
davon machen.

Aber an einem gewissen Punkt im Ablauf sollen sie gefiltert werden. Das
wäre der Moment des Umschaltens.
Post by Nicole Wagner
Post by Joe Galinke
Post by Nicole Wagner
stets ein Array an Calc uebergeben wird.
Was für ein CALC? Du meinst nicht das OnCalcFields-Event, sondern eine
eigene Methode/Funktion/Prozedur?
ich meine mit "Calc" das OnCalcFieldsEvent.
Wie übergibst Du ein Array an OnCalcField()? Du meinst, Du greifst in der
Eventmethode auf eben jenes global oder als Bestandteil des Formulars
verfügbare Array zu?



Gruß, Joe
--
Nicole Wagner
2011-03-26 13:22:54 UTC
Permalink
Joe Galinke wrote:


danke fuer Deine Antwort.
Ich habe Deine Fragen beantwortet.
Doch bevor Du darauf eingehst, lies bitte das Posting zu Ende.
Denn moeglicherweise liegt das Problem woanders.
Post by Joe Galinke
- Du verwendest Delphi 2010 (wobei die Unterschiede für das aktuelle
Problem wohl vernachlässigbar sind)
ja und ja
Post by Joe Galinke
- Du arbeitest mit den Interbase-Komponenten wie TIBDatabase und TIBSQL.
ja und jein.
Ich arbeite auch mit TIBQuery, weil TIBSQL manchen Schnittpunkt nicht
zur Verfuegung stellt, wie etwa zu TDBChart.
Post by Joe Galinke
- Du hast Deine Dataset-Komponente per Maus auf ein Formular oder
Datenmodul gezogen.
Ich habe z.B. noch nie ein Delphi gesehen welches in der
Komponentenliste ein schlichtes TDataset anbot,
Sollte ich also mit meinen Grundannahmen nicht vollständig daneben
liegen, dann bitte ich Dich noch einmal, Deine Dataset-Komponente im
Designmodus zu markieren und Dir anzuschauen welchen Klassennamen der
OI anzeigt. Ganz oben steht der Name Deiner Komponente (MyQuery oder
so) und rechts daneben der Klassenname. Bitte, schau mal nach.
Noch mal Nachsehen ist immer gut *erroet*:
Entschuldige meine Verwechslung. Ich lese das Dataset ununterbrochen in
der Programmierzeilenvervollstaendigung. Es ist mir das Wort so
vertraut, dass ich davon ueberzeugt war, es muesste da sein.

Doch habe habe gerade mein Formular angesehen: Ich habe gar kein
TDataset, nur ein TDataSource.
Post by Joe Galinke
Post by Nicole Wagner
Form.IBQuery.DataSource.DataSet.Refresh;
(meine Var-Namen habe ich mal weggelassen)
wird von der Syntax her akzeptiert, loest aber zur Laufzeit eine
Schutzverletzung aus.
IBQuery: TIBQuery --> TIBCustomDataSet --> TWideDataSet --> TDataSet
"Custom", damit bin ich sicher nicht hingekommen.
Ich habe es einmal in die "probieren"-Datei kopiert.

Zur Zeit irritiert mich jedoch "der 1ser", siehe unten.
Post by Joe Galinke
Dein IBQuery ist ein Nachfahre von TDataSet, hat aber wirklich kein
RefreshSQL.
Mir kommt nur Dein Aufruf sehr seltsam vor.
das wird er wohl auch sein.
Denn er fliegt mir nur um die Ohren.
Post by Joe Galinke
Das DataSet von dem Du redest, ist das nicht eben jene IBQuery
selbst? Wenn ja, welches Dataset willst Du über
IBQuery.DataSource.DataSet ansprechen?
Hat diese IBQuery überhaupt eine Datasource zugeordnet oder gibt es
nicht eher eine Datasource der eben jene IBQuery zugeordnet wird?
Genau, jetzt wird es mystisch, siehe dazu die Ausfuehrungen am Ende.
Denn es hat im OI KEINE Datasource zugeordnet.
Und die Auswahl, die im Property angeboten wird, zeigt nicht auf jene,
die ich brauchen wurde. Ein direktes Eingeben bewirkt die Fehlermeldung
"zirkulaere Referenz".

Das DBGrid wird aber gefuellt.
D.h. die Verbindung muss woanders ein.

als Kandidat ist denkbar:
Der Datasource ist ein Dataset zugeordnet, in dem der Name meiner
IBQuery-steht.
(dieses Dataset haette wieder ein Datasource, doch siehe unten, mir
wird hier schwindlig)

Allerdings auch ein "Update Object".
Ist das fuer mich brauchbar?
Post by Joe Galinke
IBQuery kennt übrigens auch ein Refresh.
das hat mir schon gestern ebenfalls eine Schutzverletzung ausgeloest.
Post by Joe Galinke
Also, nicht weil ich rechthaberisch sein möchte, sondern zur
Verdeutlichung wie vernebelnd Du oft beschreibst,
Du hast ja recht.
Was Du liest, ist der Nebel in meinem Kopf. Dort fehlt das routinierte
Verstehen, wie all die Komponenten eigentlich aufgebaut sind und
miteinander arbeiten. Es ist meine allerste Anwendung mit diesen
Komponenten.
Klar fehlt bei einem ersten Versuch noch viel an Wissen.
Wenn man nicht wirklich versteht, was DataSet und DataSource genau
sind, verwechselt man sie natuerlich viel eher.
Post by Joe Galinke
Post by Nicole Wagner
Bitte nicht!
Das waere ganz schlimm.
Denn bevor die Zeilen gefiltert werden, muessen sie noch als
Lookup-Quelle fuers naechste DBGrid herhalten.
Das hört sich alles verdammt chaotisch an, ich kann mir im Moment
kein Bild davon machen.
Es sieht recht schnuckelig aus.
Und wuerde es funktionieren, dann waere es das auch.

Ich habe ein PageControl: Ein Tab liest mir die aktuellen Tageskurse
ein und zeigt sie mir in einem DBGrid.
Ein anderes Tab listet mir mein Konto und die offenen Positionen in
einem anderen DBGrid.
Was interessiert bei den offenen Positionen? - die Buchgewinne.

Daher muss mein DBGrid des Kontos per Lookup aus dem ersten DBGrid die
eingelesenen Kurse holen und den momentanen Kontostand ausgeben.
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Was für ein CALC? Du meinst nicht das OnCalcFields-Event, sondern
eine >> eigene Methode/Funktion/Prozedur?
Post by Nicole Wagner
ich meine mit "Calc" das OnCalcFieldsEvent.
Wie übergibst Du ein Array an OnCalcField()? Du meinst, Du greifst in
der Eventmethode auf eben jenes global oder als Bestandteil des
Formulars verfügbare Array zu?
ja



Doch jetzt zum angekuendigten Problem, das vielleicht ganz woanders
liegt.

Seit einigen Tagen irritiert mich ein Phaenomen in einer anderen Unit.
Vielleicht kommt das Uebel von dort her.

Die Unit ist zwar sehr lang, doch nicht komplex.
Sie enthaelt die meisten SQL-Queries.
Die Unit-Basis ist ein Modul, das enthaelt:
IBDatabase1, TBTransaction1 und IBSQL1.
Sonst nichts.

Seit einigen Tage stolpere ich ueber ein Phaenomen, das mir vorher
nicht auffiel.
In meinen Query-Methoden, die mir voellig gleich aufgebaut erscheinen,
werden 2 verschiedene Befehle vom Compiler akzeptiert:
Bitte achte auf den (fehlenden) "1" hinter dem Wort Transaction
(wobei '2 verschiedene' ein AUSSCHLUSS ist. D.h. es wird nur das eine
ODER das andere akzeptiert.)


eine Formulierung:

If Not IBTransaction1.InTransaction then
IBTransaction1.StartTransaction;
......

try
IBSQL1.ExecQuery;
IBSQL1.Transaction.Commit; //// !!!!!!!!!!!!!!
except
Showmessage('....');
IBTransaction1.Rollback;
end;


oder aber diese Formulierung:
If Not IBTransaction1.InTransaction then
IBTransaction1.StartTransaction;
......
try
IBSQL1.ExecQuery;
IBTransaction1.Commit; //// !!!!!!!!!!!!!!
except
Showmessage('....');
IBTransaction1.Rollback;
end;

Lasse ich den 1ser weg oder schreibe ihn dazu, sehe ich je die
Fehlermeldung
"unbekannte Var". Einmal so und einmal anders.



Die Deklaration springt mir hierhin fuer "IBTransaction1" in meine
eigene Unit:

TSQL_ = class(TDataModule)
IBDatabase1: TIBDatabase;
IBSQL1: TIBSQL;
IBTransaction1: TIBTransaction;
........


ODER aber hierher in die Delphi-Unit IBSQL fuer "IBTransaction":
TIBSQL = class(TComponent)
........
published
property Database: TIBDatabase read GetDatabase write SetDatabase;
property GoToFirstRecordOnExecute: Boolean read
FGoToFirstRecordOnExecute
write
FGoToFirstRecordOnExecute
default True;
property ParamCheck: Boolean read FParamCheck write FParamCheck
default true;
property SQL: TStrings read FSQL write SetSQL;
property Transaction: TIBTransaction read GetTransaction write
SetTransaction;
property OnSQLChanging: TNotifyEvent read FOnSQLChanging write
FOnSQLChanging;
end;
....



Liebe Gruesse,
Nicole
Joe Galinke
2011-03-26 16:24:45 UTC
Permalink
Hallo Nicole,
Post by Nicole Wagner
Post by Joe Galinke
- Du arbeitest mit den Interbase-Komponenten wie TIBDatabase und TIBSQL.
ja und jein.
Ich arbeite auch mit TIBQuery, weil TIBSQL manchen Schnittpunkt nicht
zur Verfuegung stellt, wie etwa zu TDBChart.
Es ging mir zuerst um die Sammlung selbst.
Post by Nicole Wagner
Doch habe habe gerade mein Formular angesehen: Ich habe gar kein
TDataset, nur ein TDataSource.
Klar, die Datasource benötigst Du für Deine visuellen Komponenten.
Post by Nicole Wagner
Post by Joe Galinke
IBQuery: TIBQuery --> TIBCustomDataSet --> TWideDataSet --> TDataSet
"Custom", damit bin ich sicher nicht hingekommen.
Ich habe es einmal in die "probieren"-Datei kopiert.
Damit wollte ich nur die Herkunft verdeutlichen. Deine IBQuery ist eine
TINQuery und stammt von TIBCustomDatSet ab. Dieses stammt von TWideDataSet
ab usw.

T xxx Custom yyyy sind im Allgemeinen auch nicht zur direkten Verwendung
gedacht, sondern als Ausgangspunkt für eigene Ableitungen. Ein einfaches
Beispiel stellt TPanel dar, welches von TCustomPanel abstammt. TCustomPanel
bietet public nur
property ParentBackground stored FParentBackgroundSet;
constructor Create(AOwner: TComponent); override;
function GetControlsAlignment: TAlignment; override;
an, aber keine published Properties.

TPanel macht nun nichts neues oder eigens, außer dass verschiedene
Properties nun statt protected published deklariert sind.

So kann man eine eigene Komponenten von TCustomPanel ableiten, die aber
eben nicht so viel veröffentlicht wie TPanel, eben weil bestimmte
Properties nicht von außen gesetzt werden sollen. Dadurch bleibt die
Schnittstelle schlank. Mit TPanel wäre das nicht zu machen, da man im
Nachfahren die Sichtbarkeitstufe nicht wieder niedriger ansetzen kann. Man
kann nicht eine im Vorfahren als Public deklarierte Property im Nachfahren
auf Private oder Protected setzen.
Post by Nicole Wagner
Zur Zeit irritiert mich jedoch "der 1ser", siehe unten.
Später, wenn ich es denn verstehe. :-)
Post by Nicole Wagner
Genau, jetzt wird es mystisch, siehe dazu die Ausfuehrungen am Ende.
Denn es hat im OI KEINE Datasource zugeordnet.
Und die Auswahl, die im Property angeboten wird, zeigt nicht auf jene,
die ich brauchen wurde. Ein direktes Eingeben bewirkt die Fehlermeldung
"zirkulaere Referenz".
Die Eigenschaft Datasource Deiner IBQuery ist also leer? Was soll
IBQuery.DataSource.DataSet dann adressieren? Nix! Ist doch eigentlich
logisch, oder? Wenn nicht, sags einfach.

Es ist aber auch ein wenig verwirrend mit Datasource, das stimmt
allerdings.

Zur Eigenschaft Datasource, Deiner IBQuery (eingeführt wird sie vom
Vorfahren TDataset) sagt die D7-OH:

---
Die Eigenschaft DataSource gibt die Datenquelle einer anderen Datenmenge
an, die der aktuellen Datenmenge Werte bereitstellt.

Delphi-Syntax:

property DataSource: TDataSource;

...

Beschreibung

Mit DataSource können Sie auf die Datenquelle einer anderen Datenmenge
zugreifen, die der aktuellen Datenmenge Werte bereitstellt.
---

Auch wenn das nichts besagen will, diese Property habe ich selbst noch nie
benötigt und ich vermute, Du kommst bei Deinem Problem auch ohne aus. Lasse
sie bitte erst einmal unbeachtet.

Die übliche Verbindung zwischen TDateSource und eine TDataSet (oder halt
einem der Nachfahren) sieht so aus, dass man der Eigenschaft DataSet der
DataSource eben ein TDataSet oder einen Nachkommen davon zuweist.

DataSource := MyIBQuery; (oder MyDataSet oder MyIBDataSet oder MyIBTable)
Post by Nicole Wagner
Das DBGrid wird aber gefuellt.
D.h. die Verbindung muss woanders ein.
Ja, so wie ein paar Zeilen drüber beschrieben.
Post by Nicole Wagner
Der Datasource ist ein Dataset zugeordnet, in dem der Name meiner
IBQuery-steht.
(dieses Dataset haette wieder ein Datasource, doch siehe unten, mir
wird hier schwindlig)
Genau das wäre nicht der fall.

DataSource.DataSet --- hier kommt Deine IBQuery hin.

IBQuery.DataSource bleibt leer.
Post by Nicole Wagner
Allerdings auch ein "Update Object".
Ist das fuer mich brauchbar?
Das ist wieder etwas ganz anderes und hat mit der aktuellen
Aufgabenstellung nichts zu tun.

Das Updateobjekt brauchst Du wenn Du mit IBQuery.Post auch Änderungen
schreiben möchtest.

Das Updateobjekt verweist auf eine Instanz von TUpdateSQL, welches über
eigene SQL-Properties verfügt, jeweils zum Löschen eines Datensatzes,
Einfügen eines neuen Dattensatzes und eben zum Ändern.

Stelle Dir eine Datenmenge vor, die sich aus einem etwas komplexeren
SQL-Statement mit JOINS ergibt. Die Datenmenge enthält also Felder aus
mehreren Tabellen. In TUpdateSQL.ModifySQL (IBQuery.UpdateObject.ModifySQL)
kann man nun eine Stamenet schreiben, bzw. sich generieren lassen, welches
nur Felder schreibt die auch in der betreffenden Tabelle existieren, nicht
aber irgendwelche per JOIN oder anderer SQL-Möglichkeiten hinzugefügten
Felder.

Wie gesagt, das brauchst Du im Moment nicht, langfristig aber bestimmt.
Ganz besonders wenn Du mit datensensitiven Edit-Controls arbeitest und
"darunter" eben nicht einfache Tabellen liegen.
Post by Nicole Wagner
Post by Joe Galinke
IBQuery kennt übrigens auch ein Refresh.
das hat mir schon gestern ebenfalls eine Schutzverletzung ausgeloest.
Ich gehe immer noch davon aus, dass Du es gar nicht aufgerufen hast.

| Form.IBQuery.DataSource.DataSet.Refresh

Wenn Form.IBQuery.DataSource schon leer (nil) war, siehe oben, dann bist Du
nie bis zu einem IBQuery vorgestoßen. Es hätte ja auch nur IBQuery.Refrsh
heißen müssen. Ich glaube auch, dass das Form davor eine Hinweis auf einen
ganz bösen Designfehler hinweist. Warum eigentlich Form? Ist das eine
simple Prozedur/Funktion, die nicht zum Formular gehört aber eben in der
Unit enthalten ist?

Ach ja, Du schriebst auch mal:
| Form.IBQuery.SQL.*
| kennt kein Refresh

Es war auch nie die Rede von einer Methode Refresh der Property SQL. Die
ist vom Typ TStrings und kennt sowas nicht.
Post by Nicole Wagner
Klar fehlt bei einem ersten Versuch noch viel an Wissen.
Wenn man nicht wirklich versteht, was DataSet und DataSource genau
sind, verwechselt man sie natuerlich viel eher.
DataSet ist die Datenmenge, also einfach der Tabelleninhalt oder das
Ergebnis eines komplexeren SQL-Statements.

Ein Grid hat nun eine Eigenschaft DataSource (Quelle), an der ein DataSet
hängt. Über diese Verbindung holt sich das Grid die Daten.
Post by Nicole Wagner
If Not IBTransaction1.InTransaction then
IBTransaction1.StartTransaction;
......
try
IBSQL1.ExecQuery;
IBSQL1.Transaction.Commit; //// !!!!!!!!!!!!!!
except
Showmessage('....');
IBTransaction1.Rollback;
end;
If Not IBTransaction1.InTransaction then
IBTransaction1.StartTransaction;
......
try
IBSQL1.ExecQuery;
IBTransaction1.Commit; //// !!!!!!!!!!!!!!
except
Showmessage('....');
IBTransaction1.Rollback;
end;
Nun, mal rufst Du .Commit der IBTransaction1 auf, dabei handelt es sich
wohl um eine in Deinem Formular existierende Instanz von TIBTransaction.

Im anderen Fall rufst Du .Commit der Transaction auf die IBQuery zugewisen
ist. Dass kann die gleiche sein, aber Du kannst aus der Property
IBQuery.Transaction ja nicht IBQuery.Transaction1 machen.

Du siehst, dass der Unterschied nicht nur in der "1" besteht, sondern auch
in dem "IB" davor?

Das eigentliche Transaktionsobjekt kann dabei in beiden Fällen das Gleiche
sein; ich denke auch, dass es so ist.

Aber das hat alles nichts mit Deinen anderen Problem zu tun. Kein Phänomen.


Nimm nochmal das Beispiel TDataSource/TDataSet.

Du hast auf Deinem Formular ein MyDataSource: TDataSource und IBQuery:
TIBQuery.
Im OI wird nun MyDataSource.DataSet die IBQuery zugewiesen.

Innerhalb igendeiner Methode Deines Formulars könnte nun stehen:

var
LocalDataSet: TDataSet;
s: string;
begin
LocalDataSet := IBQuery;

S := LocalDataSet.FieldByName(xxx).AsString;
S := IBQuery.FieldByName(xxx).AsString;
S := MyDatasource.DataSet.FieldByName(xxx).AsString;
end;

S würde in allen drei Fällen der gleiche String zugewiesen.
In dem Falle würden LocalDataSet, IBQuery und MyDatasource.DataSet auf die
gleiche Datenmenge zeigen. ZEIGEN. Es sind lediglich Zeiger auf Objekte.
Post by Nicole Wagner
"unbekannte Var". Einmal so und einmal anders.
unbekannter Bezeichner

Ja, das wirkt kleinlich. Aber gerade da Du aus Unkenntnis manchmal sehr
seltsame Umschreibungen und Begriffe wählst, bleibe bitte dort wo möglich
bei den passenden Formulierungen.




Gruß, Joe
--
Nicole Wagner
2011-03-28 13:25:31 UTC
Permalink
[Erklaerungen]
sorgsam gelesen
Zur Eigenschaft Datasource, Deiner IBQuery (eingeführt wird sie vom
---
Die Eigenschaft DataSource gibt die Datenquelle einer anderen
Datenmenge an, die der aktuellen Datenmenge Werte bereitstellt.
und das verstehst Du? (aber nur, weil Du denn Sinn schon vorher weisst)
Ich jedenfalls nicht.

DataSource uebersetze ich mit Datenquelle und das ist ein Hauptwort.
Wenn ich jetzt lese: Die Eigenschaft Datenquelle gibt die
Datenquelle...? haeh? Wovon ist da die Rede?
Sollte "Eigenschaft" vielleicht "property" sein?

Und was fuer eine "andere" Datenmenge? Was ist die aktuelle Datenmenge?
Daselbe wie "Eigenschaft" (Hauptwort oder Eigenschaft?) Datenquelle?
Ist Menge und Quelle jetzt dasselbe? Wenn nicht, was ist der
Unterschied?

Diese Kritik ist keineswegs gegen Dich gerichtet.
Sondern erklaert den Nebel in meinem Kopf. Ich lese dieses kryptische
Denglische Gestammel und lese es stundenlang und ich weiss danach nur
selten, was mir der Autor damit eigentlich sagen will. Moeglicherweise
ein Uebersetzungscomputer.
property DataSource: TDataSource;
...
unter "property" kann ich mir schon mehr vorstellen.
Beschreibung
Mit DataSource können Sie auf die Datenquelle einer anderen Datenmenge
zugreifen, die der aktuellen Datenmenge Werte bereitstellt.
---
Auch wenn das nichts besagen will, diese Property habe ich selbst
noch nie benötigt und ich vermute, Du kommst bei Deinem Problem auch
ohne aus. Lasse sie bitte erst einmal unbeachtet.
Ich bin mir da nicht so sicher.
Ich verknuepfe in meinem Formular Informationen aus verschiedenen
Tabellen miteinander und schreibe sie dann in eine andere Tabelle
meiner DB zurueck.
Die übliche Verbindung zwischen TDateSource und eine TDataSet (oder
halt einem der Nachfahren) sieht so aus, dass man der Eigenschaft
DataSet der DataSource eben ein TDataSet oder einen Nachkommen davon
zuweist.
DataSource := MyIBQuery; (oder MyDataSet oder MyIBDataSet oder
MyIBTable)
Was bedeutet TDataSource?
Ich uebersetze es mit Datenquelle und stelle mir jetzt die Quelle vor,
die nach starkem Regen manchmal aus der Wiese sprudelt.
Liege ich mit diesem Bild richtig?
Post by Nicole Wagner
Allerdings auch ein "Update Object".
Ist das fuer mich brauchbar?
Das ist wieder etwas ganz anderes und hat mit der aktuellen
Aufgabenstellung nichts zu tun.
es loest ohnehin eine Schutzverletzung aus.
Das Updateobjekt brauchst Du wenn Du mit IBQuery.Post auch Änderungen
schreiben möchtest.
Das Updateobjekt verweist auf eine Instanz von TUpdateSQL, welches
über eigene SQL-Properties verfügt, jeweils zum Löschen eines
Datensatzes, Einfügen eines neuen Dattensatzes und eben zum Ändern.
Klar will ich das!
Ich habe es nur bis jetzt nicht implementiert.

Ich wollte das urspruenglich ueber meinen SQL-Werkzeugkasten machen.
Ist das via UpdateSQL probater?
Stelle Dir eine Datenmenge vor, die sich aus einem etwas komplexeren
SQL-Statement mit JOINS ergibt. Die Datenmenge enthält also Felder aus
mehreren Tabellen. In TUpdateSQL.ModifySQL
(IBQuery.UpdateObject.ModifySQL) kann man nun eine Stamenet
schreiben, bzw. sich generieren lassen, welches nur Felder schreibt
die auch in der betreffenden Tabelle existieren, nicht aber
irgendwelche per JOIN oder anderer SQL-Möglichkeiten hinzugefügten
Felder.
oh!
Wie interessant.
Wie gesagt, das brauchst Du im Moment nicht, langfristig aber
bestimmt. Ganz besonders wenn Du mit datensensitiven Edit-Controls
arbeitest und "darunter" eben nicht einfache Tabellen liegen.
Ich brauche es schon heute, wenn ich meine Aufgabenliste ansehe, die
ich mir fuer diese Woche bereit gelegt habe.

Ich frage mich, ob ich das nicht schon vor 2 Wochen gebraucht haette.
Ich arbeite naemlich so:

Der Benutzer hat eine Checklistbox. Je nachdem, was er dort anklickt,
wird in verschiedene Tabellen geschrieben. Ich habe das bis jetzt
geloest, indem ich im OnClick-Event *.SQL.Active auf false gesetzt
habe, die *.SQL.text-Zuweisung neu geschrieben und danach die Query
wieder auf true.

Ist das de lege artis?



Apropos de lege artis:
Ein ganz schlechtes Gefuehl habe ich dabei, dass ich im Feldeditor die
IBQuery bearbeite, aufgrund der SQL-Formulierung Felder und Spalten
anlege und danach locker vom Hocker SQL.Text zur Laufzeit neu zuweise.
Sowas "macht man nicht". So grundsaetzlich.
Post by Nicole Wagner
Form.IBQuery.DataSource.DataSet.Refresh
Wenn Form.IBQuery.DataSource schon leer (nil) war, siehe oben, dann
bist Du nie bis zu einem IBQuery vorgestoßen. Es hätte ja auch nur
IBQuery.Refrsh heißen müssen. Ich glaube auch, dass das Form davor
eine Hinweis auf einen ganz bösen Designfehler hinweist. Warum
eigentlich Form? Ist das eine simple Prozedur/Funktion, die nicht zum
Formular gehört aber eben in der Unit enthalten ist?
Doch, sie gehoert zum Formular.
Ich habe das nie so ganz durchschaut, wann ich Form explizit angeben
muss und wann ich es nicht darf.

In 90 Prozent aller Faelle, wenn vom Compiler eine Syntax ohne Form
akzeptiert wurde, hatte ich in Wahrheit einen Pointer nach nil, der zur
Laufzeit eine Schutzverletzung ausloeste.
Das passierte etwa haeufig in Zusammenhang mit TChart. Ich habe mir
daher angewoehnt, im Zweifel Form explizit hinzuschreiben. Zudem ich
mit meine hunderte Variablennamen nicht merken kann und die
Programmierhilfe quasi verwenden muss.

Doch Methoden, die nicht zum Formular gehoeren: Wie loest man das? Legt
man dafuer eine eigene Klasse an? Wenn ja, wie bezeichnet man die
Klasse am besten, damit man die Methode wiederfindet?
Post by Nicole Wagner
Klar fehlt bei einem ersten Versuch noch viel an Wissen.
Wenn man nicht wirklich versteht, was DataSet und DataSource genau
sind, verwechselt man sie natuerlich viel eher.
DataSet ist die Datenmenge, also einfach der Tabelleninhalt oder das
Ergebnis eines komplexeren SQL-Statements.
ach so!!!!!!!!!!!!
Jetzt habe ich es verstanden.
Ein Grid hat nun eine Eigenschaft DataSource (Quelle), an der ein
DataSet hängt. Über diese Verbindung holt sich das Grid die Daten.
Das habe ich zum ersten mal auch verstanden, zumindest teilweise.

Dieser Teil ist mir unklar:
Wozu braucht das Grid eine DataSource?
Wenn DataSet eine Datenmenge ist, dann muesste doch das Grid nur ein
property DataSet haben?
Das Grid braucht doch nur die Datenmenge, die es darstellt und keine
Datenquelle?

Urspruenglich wollte ich meinem DBGrid eine Query zuweisen und dachte,
es wuerde darstellen, was das Query abfragt. Doch das ging nicht im OI.

und cit:
"Über diese Verbindung".... Ich dachte, "Query" waere die Verbindung
mit einer DB? Oder Transaction?
Du siehst, dass der Unterschied nicht nur in der "1" besteht, sondern
auch in dem "IB" davor?
noe, das ist mir auch beim dutzenden mal Lesen entgangen.

Das ist der Preis: Auch etwa mein Mann denkt sehr systematisch. Ihm
waere das auch aufgefallen.
Wort- und Silbenspiele gegen mich hasst er. Denn ich gewinne mit einen
Vorsprung zwischen dem Faktor 2 bis 10. Weil ich Buchstaben derart
radikal ausblende, dass ich sie NIE sehe. In meinem Kopf kommen nur
Woerter an.
Danke fuer den Hinweis!
Das eigentliche Transaktionsobjekt kann dabei in beiden Fällen das
Gleiche sein; ich denke auch, dass es so ist.
darum ist es mir auch lange nicht aufgefallen.
Weil meine Methoden gleichermassen funktionierten.
Nimm nochmal das Beispiel TDataSource/TDataSet.
TIBQuery.
Im OI wird nun MyDataSource.DataSet die IBQuery zugewiesen.
var
LocalDataSet: TDataSet;
s: string;
begin
LocalDataSet := IBQuery;
S := LocalDataSet.FieldByName(xxx).AsString;
S := IBQuery.FieldByName(xxx).AsString;
S := MyDatasource.DataSet.FieldByName(xxx).AsString;
end;
S würde in allen drei Fällen der gleiche String zugewiesen.
In dem Falle würden LocalDataSet, IBQuery und MyDatasource.DataSet
auf die gleiche Datenmenge zeigen. ZEIGEN. Es sind lediglich Zeiger
auf Objekte.
DARAN LIEGT ES!
Ich habe hier ratlos und endlos die Programmierhilfe meine Sachen
suchen lassen. Mir war voellig schleierhaft, wie und warum meine
ZEILEN-LANGEN Ausdruecke aufgebaut waren. Ich habe einen Weg gefunden,
dorthin zu kommen, der NOCH umstaendlicher ist. Von dort habe ich es
dann stets kopiert.
Bitte frage mich jetzt nicht wie, merken kann ich mir das nicht. Ich
weiss nur, dass ich manche lokale Vars nur deshalb fuehre, weil ich mit
den Zuweisungsmonstern nicht arbeiten kann.

Meine augenblickliche Idee waere, in Zukunft stets "IBQuery." zu
verwenden, weil es das kuerzeste ist.
Post by Nicole Wagner
"unbekannte Var". Einmal so und einmal anders.
unbekannter Bezeichner
Ja, das wirkt kleinlich. Aber gerade da Du aus Unkenntnis manchmal
sehr seltsame Umschreibungen und Begriffe wählst, bleibe bitte dort
wo möglich bei den passenden Formulierungen.
Von meiner Ueberzeugung bin ich ganz bei Dir.
Genaue Wortwahl fuehrt zu genauem und damit richtigerem und schnelleren
Denken.

Was ist der Unterschied von Bezeichner und Variable?
Ist Bezeichner ein Oberbegriff, unter den Var zu subsummieren ist?
D.h. Die Fehlermeldung in Delphi bedeutet, es koennte etwa auch eine
Methode sein, die dem Compiler nicht zuordernbar ist?



Nicole
Joe Galinke
2011-03-28 15:29:41 UTC
Permalink
Hallo Nicole,
Post by Nicole Wagner
Post by Joe Galinke
Die Eigenschaft DataSource gibt die Datenquelle einer anderen
Datenmenge an, die der aktuellen Datenmenge Werte bereitstellt.
DataSource uebersetze ich mit Datenquelle und das ist ein Hauptwort.
Wenn ich jetzt lese: Die Eigenschaft Datenquelle gibt die
Datenquelle...? haeh? Wovon ist da die Rede?
Sollte "Eigenschaft" vielleicht "property" sein?
Ja natürlich.
Post by Nicole Wagner
Und was fuer eine "andere" Datenmenge? Was ist die aktuelle Datenmenge?
Na, die IBQuery (oder IBDataset oder IBTable oder irgendein DataSet) deren
Eigenschaft DataSource wir gerade betrachten.
Post by Nicole Wagner
Daselbe wie "Eigenschaft" (Hauptwort oder Eigenschaft?) Datenquelle?
Ist Menge und Quelle jetzt dasselbe? Wenn nicht, was ist der
Unterschied?
Datasource ist die Quelle, die Datenmenge irgendein TDataSet, bzw. ein
Nachkomme wie TIBQuery, TIBTable, TIBDataSet oder natürlich auch
TAdoDataSet und andere.
Post by Nicole Wagner
Sondern erklaert den Nebel in meinem Kopf. Ich lese dieses kryptische
Denglische Gestammel und lese es stundenlang und ich weiss danach nur
selten, was mir der Autor damit eigentlich sagen will. Moeglicherweise
ein Uebersetzungscomputer.
Das ist kein Denglish. Die Property heißt nun einmal DataSource und kann ja
nicht an dieser Stelle anders benannt werden. "Die Proptery DataSource
eines DataSets gibt die Datenquelle....".
Post by Nicole Wagner
Ich bin mir da nicht so sicher.
Ich verknuepfe in meinem Formular Informationen aus verschiedenen
Tabellen miteinander und schreibe sie dann in eine andere Tabelle
meiner DB zurueck.
Tu Dir und mir einen Gefallen und beachte diese Property vorläufig nicht.
Wenn hier jemand kommt und Dir _konkret_ zeigt wie Du sie für _genau_ Dein
aktuelles Problem einsetzen kannst, von mir aus. Bis dahin werde ich mich
nicht mehr um die Eigenschaft DataSource eines DataSets kümmern. Ich bin
mir zu sicher, dass Du Dich verzetteln wirst. So viel Zeit und Muße habe
ich nicht.
Post by Nicole Wagner
Post by Joe Galinke
Die übliche Verbindung zwischen TDateSource und eine TDataSet (oder
halt einem der Nachfahren) sieht so aus, dass man der Eigenschaft
DataSet der DataSource eben ein TDataSet oder einen Nachkommen davon
zuweist.
DataSource := MyIBQuery; (oder MyDataSet oder MyIBDataSet oder MyIBTable)
Was bedeutet TDataSource?
Ich uebersetze es mit Datenquelle und stelle mir jetzt die Quelle vor,
Hier kommen wir nun wieder zu der anders gelagerten Verbindung. Eine
DataSource der ein DataSet zugewiesen wird.

Ja, die Datenquelle für ein Control wie ein TDbGrid der TDbEdit etc.. Ich
habe früher bei dem Begriff Quelle auch eher an die Datenmenge gedacht,
d.h., ich habe mich verwirren lassen.

Stelle Dir es eher wie eine Verbindung oder Datenleitung vor. Du hast die
Datenmenge (TDataSet, TIBQuery, etc) und datensensitive Controls wie die
bereits genannten TDbGrid oder TDbEdit. Die Controls kommen über die
Dataquelle an die Datenmenge heran.
Post by Nicole Wagner
Post by Joe Galinke
Post by Nicole Wagner
Allerdings auch ein "Update Object".
Ist das fuer mich brauchbar?
Das ist wieder etwas ganz anderes und hat mit der aktuellen
Aufgabenstellung nichts zu tun.
es loest ohnehin eine Schutzverletzung aus.
War denn der Property UpdateObject etwas zugewiesen? Wenn nicht, was sonst
außer einer AV soll da kommen?
Post by Nicole Wagner
Klar will ich das!
Ich habe es nur bis jetzt nicht implementiert.
Ich wollte das urspruenglich ueber meinen SQL-Werkzeugkasten machen.
Ist das via UpdateSQL probater?
Das kommt darauf an. :-)

Wenn Du direkt in Deiner Datenmenge mit IBQuery.FieldByName().As.. := ...
ändern und dann mit IBQuery.Post arbeiten möchtest, dann wirst Du
UpdateObject brauchen.

Willst Du stattdessen mit irgendeiner anderen IBQuery (SchreibQuery) und
'UPDATE TABLE Y SET Y=Z WHERE ID=N' (oder so) etwas direkt in die Tabelle
schreiben möchtest, dann geht es ohne UpdateObject. Deine ursprüngliche
IBQuery sieht diese Daten aber erst nach einem Refresh.

Was hälst Du davon, diesen Teil zu verschieben, bis der Rest klappt? Ja,
ich befürchte auch hier die Gefahr des Verzettelns.
Post by Nicole Wagner
Der Benutzer hat eine Checklistbox. Je nachdem, was er dort anklickt,
wird in verschiedene Tabellen geschrieben. Ich habe das bis jetzt
geloest, indem ich im OnClick-Event *.SQL.Active auf false gesetzt
habe, die *.SQL.text-Zuweisung neu geschrieben und danach die Query
wieder auf true.
Warum hast Du das Statement neu zugewiesen? Oder meinst Du die Zuweisung
verschiedener schreibender Statements für die verschiedenen Tabellen?
Post by Nicole Wagner
Ist das de lege artis?
Bei mehreren Tabellen ja.
Post by Nicole Wagner
Ein ganz schlechtes Gefuehl habe ich dabei, dass ich im Feldeditor die
IBQuery bearbeite, aufgrund der SQL-Formulierung Felder und Spalten
anlege und danach locker vom Hocker SQL.Text zur Laufzeit neu zuweise.
Sowas "macht man nicht". So grundsaetzlich.
Nun, es ist zumindest seltsam. Ich selbst schreibe niemals nie die Felder
in die DataSet-Komponente, d.h., ich lege diese persistenten Felder nicht
zur Designzeit an, nur zur Laufzeit. Enthält die Datenmenge nämlich
irgendwann ein weiteres Feld (egal ob durch Erweiterung der zugrunde
liegenden Tabelle oder durch Erweiterung der Abfrage), dann darf ich nicht
vergessen eben auch den Feldeditor zu verwenden um jenes Feld hinzuzufügen.
Mir fehlt es sonst in der Datenmenge. Trotzdem kannst Du natürlich so
verfahren.
Was spricht dagegen, anstatt die SQL-Statements neu zuzuweisen, für jeden
Zweck eine eigene Komponente zu nehmen? Oder sind es so viele, evtl.
dynamisch erzeugte Statements?
Post by Nicole Wagner
Doch, sie gehoert zum Formular.
Ich habe das nie so ganz durchschaut, wann ich Form explizit angeben
muss und wann ich es nicht darf.
Das ist wirklich nicht so kompliziert. In einer Methode einer Klasse, und
ein Formular ist ja nur die Instanz einer Klasse, hast Du ein implizites
with Self, wobei Self auf eben diese Klasse verweist.

procedure TMyForm.TuWas;
begin
with Self do begin //das siehst Du nicht, musst es Dir denken

Caption := 'Ein Text'; //Durch das WITH SELF wird die Property Caption
//Deines Formulars angesprochen.

end; //das siehst Du nicht, musst es Dir denken
end;

procedure TMyForm.TuWas(Caption: string);
begin
with Self do begin //das siehst Du nicht, musst es Dir denken

//Mist, Du willst Caption an Caption zuweisen.
//Welches Caption ist denn nun gemeint?

//Durch Self wird nun klar, dass Du links der Zuweisung die Property
//Caption des Formulars meinst. Rechts davon ist es der Parameter.
Self.Caption := Caption;

end; //das siehst Du nicht, musst es Dir denken
end;

Solche Sachen können besonders gut auftreten wenn Du selbst mit with
arbeitest.

with MyObject do begin
Caption := //hier ist nun Caption des Objekts gemeint, auch wenn sich
//sich dieser Code in der Methode eines Formulars befindet.
end;

Du siehst, dass ich nirgends meine Formularvariable verwendet habe? Das tue
ich auch niemals. NIEMALS. Sehr viele Formulare benötigen gar keine
Variable, da niemand von außen darauf zugreift. Auf jeden Fall hat die
Variable für ein Objekt nichts im Code der Klasse dieses Objekts zu suchen.
Ich sage NIE. Nun mag besondere Beispiele geben, die mir in meiner
Schlichtheit nicht in den Sinn kommen, aber evtl. von anderen genannt
werden. Aber auch dann werde ich davon ausgehen, dass diese Fälle
ausreichend besonders sind, dass der eher unerfahrene Entwickler weiterhin
vom NIE ausgehen sollte.

Wenn irgendwann eine weitere Instanz der Klasse erzeugt wird, oder eine
andere Variabel dafür verwendet wird, dann zeigt die ursprüngliche Variable
entweder schlicht auf die erste Instanz oder einfach nur ins Leere.

Wenn ich mal in eine, Formular eine Funktion oder Prozedur deklarieren muss
die nicht Bestandteil des Formulars ist, aber darauf zugreifen muss, dann
bekommt diese Funktion einen passenden Parameter.

function GetValue(aForm: TMyForm): Integer;
begin
aForm....
end;
Post by Nicole Wagner
In 90 Prozent aller Faelle, wenn vom Compiler eine Syntax ohne Form
akzeptiert wurde, hatte ich in Wahrheit einen Pointer nach nil, der zur
Laufzeit eine Schutzverletzung ausloeste.
Hast Du mal passende Beispiele, gerne auch in Form eines überschau- und
übersetzbaren Projekts (siehe Emailadresse, bitte nicht alles hier
reinposten), dann wird man anhand diese Codes sicherlich so manches
erklären können.
Post by Nicole Wagner
Das passierte etwa haeufig in Zusammenhang mit TChart. Ich habe mir
daher angewoehnt, im Zweifel Form explizit hinzuschreiben. Zudem ich
mit meine hunderte Variablennamen nicht merken kann und die
Programmierhilfe quasi verwenden muss.
Ok, da habe ich nur die mitgelieferte Version.
Post by Nicole Wagner
Doch Methoden, die nicht zum Formular gehoeren: Wie loest man das? Legt
man dafuer eine eigene Klasse an?
Wenn es nur eine kleine Hilfsfunktion ist, kommt sie einfach in die
Firmularunit. Spo benötigt man als Fallback-Funktion für Sortieraufgaben
eine einfache Funktion und eben keine Methode.

Schlichte Funktionen bleiben bei mir auch meist einfache Funktionen, werden
halt in einer Unit ausgelagert.
Post by Nicole Wagner
Wenn ja, wie bezeichnet man die
Klasse am besten, damit man die Methode wiederfindet?
Das ist ein ganz anderes Thema. Ich kann nur sagen, dass man sich durchaus
Zeit zur Namensfindung nehmen sollte. Eben um solche Unterstrichsuffixe wie
Du sie gerne verwendest zu vermeiden.

Aber ich werde nur sehr langsam schlau und nehme mir auch heute noch zu
selten genug Zeit dafür. Oder ich bin einfach zu phantasielos.
Post by Nicole Wagner
Bitte frage mich jetzt nicht wie, merken kann ich mir das nicht. Ich
weiss nur, dass ich manche lokale Vars nur deshalb fuehre, weil ich mit
den Zuweisungsmonstern nicht arbeiten kann.
Das ist oft auch besser, als zur Vermeidung fröhlich mit WITH zu arbeiten,
vielleicht sogar noch geschachtelten WITHs. Nicht, dass ich sie gar nicht
verwende, aber eher sparsam udn ganz bestimmt nicht über vile Zeilen. Wenn
ich Anfang und Ende des Blockes nicht mehr gleichzeitig sehen kann, dann
ist sowas auf jeden Fall zu vermeiden. Eigentlich schon früher. Dann sind
kurze Variablennamen sehr hilfreich. Geschachtelte WITHs kommen mir nicht
in meinen Code, die schafft mein Hirn nicht ausreichend gut.

Wo ich gerne WITH verwende ist bei manchen modalen Dialogen.

fcuntion TMyForm.GetDialogValue: TModalResult;
begin
with TMyDialogForm.Create(Application) do begin
try
Result := ShowModal;
finally
Free; //Das Free des erzeugten Formulars
end;
end;
end;

Dieses TMyDialogForm kommt ganz sicher ohne jegliche Formularvariable aus,
die automatisch erzeugte wird sowieso, wenn ich es nicht vergesse, gleich
beseitigt.
Post by Nicole Wagner
Meine augenblickliche Idee waere, in Zukunft stets "IBQuery." zu
verwenden, weil es das kuerzeste ist.
Warum gibst Du dem Kind nicht gleich einen passenden Namen? Ebenso hoffe
ich, dass IBTransaction1 nur der Name aus einem Testcode ist.
Post by Nicole Wagner
Was ist der Unterschied von Bezeichner und Variable?
Ist Bezeichner ein Oberbegriff, unter den Var zu subsummieren ist?
D.h. Die Fehlermeldung in Delphi bedeutet, es koennte etwa auch eine
Methode sein, die dem Compiler nicht zuordernbar ist?
Ja.

Gruß, Joe
--
Nicole Wagner
2011-03-29 10:26:04 UTC
Permalink
Post by Joe Galinke
Das ist kein Denglish. Die Property heißt nun einmal DataSource und
kann ja nicht an dieser Stelle anders benannt werden. "Die Proptery
DataSource eines DataSets gibt die Datenquelle....".
Denglish ist fuer mich, wenn jemand mit seltsamen Vokalbeln herumlallt,
etwa "schoppen geht" (hat der eine Ente zum Fuettern?). Und dann, wenn
jemand termini technici eindeutscht. Etwa "Eigenschaft" statt
"property" sagt. Fuer mich ist das nur ein Vokabel zusaetzlich.

Wobei ein Usenet-Beitrag sicher etwas anderes ist, als eine
Hilfefunktion.

Wie ungluecklich die Uebersetzung per se und dann noch mit dem Wort
"Eigenschaft" ist, wird klar, wenn man sich vorstellt, man will nach
dem Wort suchen, nachdem man etwa "property read" gefunden hat.
Post by Joe Galinke
Post by Nicole Wagner
Ich bin mir da nicht so sicher.
Ich verknuepfe in meinem Formular Informationen aus verschiedenen
Tabellen miteinander und schreibe sie dann in eine andere Tabelle
meiner DB zurueck.
Tu Dir und mir einen Gefallen und beachte diese Property vorläufig
nicht. Wenn hier jemand kommt und Dir konkret zeigt wie Du sie für
genau Dein aktuelles Problem einsetzen kannst, von mir aus. Bis dahin
werde ich mich nicht mehr um die Eigenschaft DataSource eines
DataSets kümmern. Ich bin mir zu sicher, dass Du Dich verzetteln
wirst. So viel Zeit und Muße habe ich nicht.
Danke, dass Du Dir die Zeit nimmst, die Du Dir nimmst!
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Die übliche Verbindung zwischen TDateSource und eine TDataSet (oder
halt einem der Nachfahren)
... dieser Satz hat mich gerade 2 Stunden beschaeftigt.
Ich habe wieder einen mir verstaendlichen Teil in der Hilfe gefunden.
Und einige Links, die nicht ins Leere zeigten, sondern auf Romane.




sieht so aus, dass man der Eigenschaft
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
DataSet der DataSource eben ein TDataSet oder einen Nachkommen
davon >> zuweist.
Post by Nicole Wagner
Post by Joe Galinke
DataSource := MyIBQuery; (oder MyDataSet oder MyIBDataSet oder MyIBTable)
Was bedeutet TDataSource?
Ich uebersetze es mit Datenquelle und stelle mir jetzt die Quelle vor,
Hier kommen wir nun wieder zu der anders gelagerten Verbindung. Eine
DataSource der ein DataSet zugewiesen wird.
Ja, die Datenquelle für ein Control wie ein TDbGrid der TDbEdit etc..
Ich habe früher bei dem Begriff Quelle auch eher an die Datenmenge
gedacht, d.h., ich habe mich verwirren lassen.
Stelle Dir es eher wie eine Verbindung oder Datenleitung vor. Du hast
die Datenmenge (TDataSet, TIBQuery, etc) und datensensitive Controls
wie die bereits genannten TDbGrid oder TDbEdit. Die Controls kommen
über die Dataquelle an die Datenmenge heran.
Ich probiere mit den neuen Woertern einmal, ob der Nebel im Kopf sich
lichtet.

Angenommen, ich habe Wasser, das sich in einem Berg sammelt.
Es fliesst aus dem Felsen ueber ein kleines Rohr in ein Becken.
Aus dem Becken kann Wasser geschoepft werden.
Dann waere:

TDataBase: Das Wasser im Berg
TConnection: die Oeffnung im Felsen
TDataSource: das kleine Rohr? Und nicht das Becken?
TDataSet / TIBQuery:
Wasserschoepfen im Primaerbecken inkl. Wasserteilmenge und
Schoepfvorgang

Die Controls sind die Nutzniesser der Einrichtungen?
Und was ist die Gesamtheit des Beckens?
Post by Joe Galinke
Post by Nicole Wagner
Klar will ich das!
Ich habe es nur bis jetzt nicht implementiert.
Ich wollte das urspruenglich ueber meinen SQL-Werkzeugkasten machen.
Ist das via UpdateSQL probater?
Das kommt darauf an. :-)
Wenn Du direkt in Deiner Datenmenge mit IBQuery.FieldByName().As.. :=
... ändern und dann mit IBQuery.Post arbeiten möchtest, dann wirst Du
UpdateObject brauchen.
Willst Du stattdessen mit irgendeiner anderen IBQuery (SchreibQuery)
und 'UPDATE TABLE Y SET Y=Z WHERE ID=N' (oder so) etwas direkt in die
Tabelle schreiben möchtest, dann geht es ohne UpdateObject. Deine
ursprüngliche IBQuery sieht diese Daten aber erst nach einem Refresh.
Was hälst Du davon, diesen Teil zu verschieben, bis der Rest klappt?
Ja, ich befürchte auch hier die Gefahr des Verzettelns.
ja und nein.
Ich meinem DBGrid-testen komme ich auf viel hundert Klicks pro Tag.
Und neu Starten der Anwendung, weil sich meine DBGrids wieder mal
ungewollt geleert haben. So gehen die Stunden auch dahin.

Ich weiss nur noch immer nicht, was ich "Refresh" muss.
Post by Joe Galinke
Post by Nicole Wagner
Der Benutzer hat eine Checklistbox. Je nachdem, was er dort
anklickt, wird in verschiedene Tabellen geschrieben. Ich habe das
bis jetzt geloest, indem ich im OnClick-Event *.SQL.Active auf
false gesetzt habe, die *.SQL.text-Zuweisung neu geschrieben und
danach die Query wieder auf true.
Warum hast Du das Statement neu zugewiesen? Oder meinst Du die
Zuweisung verschiedener schreibender Statements für die verschiedenen
Tabellen?
Post by Nicole Wagner
Ist das de lege artis?
Bei mehreren Tabellen ja.
ja, es sind mehrere Tabelle.
Der Benutzer kann seine Geschaefte verschiedenen Konten zuweisen.
Post by Joe Galinke
Post by Nicole Wagner
Ein ganz schlechtes Gefuehl habe ich dabei, dass ich im Feldeditor
die IBQuery bearbeite, aufgrund der SQL-Formulierung Felder und
Spalten anlege und danach locker vom Hocker SQL.Text zur Laufzeit
neu zuweise. Sowas "macht man nicht". So grundsaetzlich.
Nun, es ist zumindest seltsam. Ich selbst schreibe niemals nie die
Felder in die DataSet-Komponente, d.h., ich lege diese persistenten
Felder nicht zur Designzeit an, nur zur Laufzeit. Enthält die
Datenmenge nämlich irgendwann ein weiteres Feld (egal ob durch
Erweiterung der zugrunde liegenden Tabelle oder durch Erweiterung der
Abfrage), dann darf ich nicht vergessen eben auch den Feldeditor zu
verwenden um jenes Feld hinzuzufügen. Mir fehlt es sonst in der
Datenmenge. Trotzdem kannst Du natürlich so verfahren.
Was spricht dagegen, anstatt die SQL-Statements neu zuzuweisen, für
jeden Zweck eine eigene Komponente zu nehmen? Oder sind es so viele,
evtl. dynamisch erzeugte Statements?
Ich habe Mischformen davon.
Wenn ich etwa nur das Konto austausche, dann sind alle Tabellen gleich
aufgebaut und ich brauche nur einen einzigen Buchstaben aendern.
also etwas so:
procedure sql_Abfrage(Buchstabe: string);
SQL.Text:='select ... from Konto_' + Buchstabe + ';';

Wenn die Aufgabe ganz verschieden ist, dann flog mir die Sache ohnehin
um die Ohren mit dem Feldeditor.

Unter dem Strich habe ich zur Zeit drei eigene Komponenten. Also
ueberschaubar.

Mit denen hakt es aber auf jeden Fall. Ich kann leider nicht mal die
Frage formulieren, wo es hakt. Rufe ich sie einzeln nach Programmstart
auf, dann klappt alles wunderbar. Klicke ich schnell zwischen ihnen hin
und her, dann warte ich bis zu einer Minute. Auch hier denke ich, dass
es etwas mit dem Refresh-Thema haben muss. Eine Pruefung der
OnCalc-Events ergab ein Mitverschulden, doch es kann es nicht alleine
sein.
Post by Joe Galinke
Post by Nicole Wagner
Doch, sie gehoert zum Formular.
Ich habe das nie so ganz durchschaut, wann ich Form explizit angeben
muss und wann ich es nicht darf.
Das ist wirklich nicht so kompliziert. In einer Methode einer Klasse,
und ein Formular ist ja nur die Instanz einer Klasse, hast Du ein
implizites with Self, wobei Self auf eben diese Klasse verweist.
procedure TMyForm.TuWas;
begin
with Self do begin //das siehst Du nicht, musst es Dir denken
Caption := 'Ein Text'; //Durch das WITH SELF wird die Property
Caption //Deines Formulars angesprochen.
end; //das siehst Du nicht, musst es Dir denken
end;
procedure TMyForm.TuWas(Caption: string);
begin
with Self do begin //das siehst Du nicht, musst es Dir denken
//Mist, Du willst Caption an Caption zuweisen.
//Welches Caption ist denn nun gemeint?
//Durch Self wird nun klar, dass Du links der Zuweisung die
Property //Caption des Formulars meinst. Rechts davon ist es der
Parameter. Self.Caption := Caption;
end; //das siehst Du nicht, musst es Dir denken
end;
Wenn Self auf das Formular zeigt und ich mir das Wort dazudenken
kann,... kann ich dann nicht auch den Formularnamen explizit anweisen?

also:

procedure TMyForm.TuWas;
MyForm.Caption := 'Ein Text';

?
Post by Joe Galinke
Solche Sachen können besonders gut auftreten wenn Du selbst mit with
arbeitest.
with MyObject do begin
Caption := //hier ist nun Caption des Objekts gemeint, auch wenn
sich //sich dieser Code in der Methode eines Formulars
befindet. end;
Marian sagte
"with verheisst Unheil".
Da sich diese Prophezeiung bewahrheitet hat (man hat ja auch bei
Var-Namen seine Lieblingsausdruecke und Gleichheiten bringen VIEL
Unheil) vermeide ich with, solange ich die Zeile noch irgendwie
handlich tippen kann.

With habe ich nur noch bei Owner-Draw Teilen, wo man den Codeteil
bequem unter jedes "With Formularnamen" kopieren kann.
Post by Joe Galinke
Du siehst, dass ich nirgends meine Formularvariable verwendet habe?
Das tue ich auch niemals. NIEMALS.
interessant
Post by Joe Galinke
Sehr viele Formulare benötigen gar
keine Variable, da niemand von außen darauf zugreift. Auf jeden Fall
hat die Variable für ein Objekt nichts im Code der Klasse dieses
Objekts zu suchen.
ui, das habe ich nicht vestanden.
Was ist "die Variable fuer ein Objekt"?
Post by Joe Galinke
Post by Nicole Wagner
In 90 Prozent aller Faelle, wenn vom Compiler eine Syntax ohne Form
akzeptiert wurde, hatte ich in Wahrheit einen Pointer nach nil, der
zur Laufzeit eine Schutzverletzung ausloeste.
Hast Du mal passende Beispiele, gerne auch in Form eines überschau-
und übersetzbaren Projekts (siehe Emailadresse, bitte nicht alles hier
reinposten), dann wird man anhand diese Codes sicherlich so manches
erklären können.
es wird mir sicher wieder unterkommen.
Ich hatte es damals an der mir heute nicht mehr gelaeufigen Stelle
sogar kommentiert, dass ich die E gesehen hatte aus diesem Grund.
Post by Joe Galinke
Post by Nicole Wagner
Das passierte etwa haeufig in Zusammenhang mit TChart. Ich habe mir
daher angewoehnt, im Zweifel Form explizit hinzuschreiben. Zudem ich
mit meine hunderte Variablennamen nicht merken kann und die
Programmierhilfe quasi verwenden muss.
Ok, da habe ich nur die mitgelieferte Version.
Probiere einmal Pro.
Ich bin von der schlichtweg begeistert.
Sie hat nur eine Nag-Screen als Demo und ist uneingeschraenkt
funktionsfaehig.
Post by Joe Galinke
Post by Nicole Wagner
Doch Methoden, die nicht zum Formular gehoeren: Wie loest man das?
Legt man dafuer eine eigene Klasse an?
Wenn es nur eine kleine Hilfsfunktion ist, kommt sie einfach in die
Firmularunit. Spo benötigt man als Fallback-Funktion für
Sortieraufgaben eine einfache Funktion und eben keine Methode.
huch?
Ich habe mein Leben lang gedacht, Methode waere der Oberbegriff von
Funktionen und Prozeduren?
Post by Joe Galinke
Schlichte Funktionen bleiben bei mir auch meist einfache Funktionen,
werden halt in einer Unit ausgelagert.
Post by Nicole Wagner
Wenn ja, wie bezeichnet man die
Klasse am besten, damit man die Methode wiederfindet?
Das ist ein ganz anderes Thema. Ich kann nur sagen, dass man sich
durchaus Zeit zur Namensfindung nehmen sollte. Eben um solche
Unterstrichsuffixe wie Du sie gerne verwendest zu vermeiden.
Aber ich werde nur sehr langsam schlau und nehme mir auch heute noch
zu selten genug Zeit dafür. Oder ich bin einfach zu phantasielos.
Ich habe mir Bibliotheken angelegt.
Etwa eine namens Zeit.
Dort sammelt sich im Laufe der Jahre der Schrott.
Wie ich vor 5 Jahren ein Datum formatiert habe, das mache ich heute
nicht mehr. Ebenso wie ich verschiedene Formatumwandlungen nicht mehr
brauchem weil ich das Format wahrscheinlich(!) nicht mehr verwende.
Wenn ich aber etwas loesche, ist es notorisch jenes, das ich noch
gebraucht haette.

Keine Unterstrichsuffixe?
Ohne die bin ich verloren. Ich kann nur mit Woertern.
Ich ueberlege zur Zeit, ob ich Unix nicht links liegen lasse mit all
den Kuerzeln.
Post by Joe Galinke
Post by Nicole Wagner
Bitte frage mich jetzt nicht wie, merken kann ich mir das nicht. Ich
weiss nur, dass ich manche lokale Vars nur deshalb fuehre, weil ich
mit den Zuweisungsmonstern nicht arbeiten kann.
Das ist oft auch besser, als zur Vermeidung fröhlich mit WITH zu
arbeiten, vielleicht sogar noch geschachtelten WITHs. Nicht, dass ich
sie gar nicht verwende, aber eher sparsam udn ganz bestimmt nicht
über vile Zeilen. Wenn ich Anfang und Ende des Blockes nicht mehr
gleichzeitig sehen kann, dann ist sowas auf jeden Fall zu vermeiden.
ich vermeide es auch, wo geht.
Doch je laenger ein Block, desto mehr erspart das with
Zu Blockanfang und Ende habe ich einen Trick:
D 2010 hat recht gute Autofunktionen:
Schreibe ich ein begin und die Eingabetaste, dann schreibt mir Delphi
ein end; genau drunter.
D.h. ich habe meine begin-end-Block formatiert, bevor ich die erste
Zeile schreibe. Und bevor ich die Zeile schreibe, kopiere ich die
Befehlszeile als Kommentar hinter das end.

Also for i:=0 to 100 do
begin
end; // zu for i:=0 to 100

Dann erst beginne ich meinen Code zu tippen.

Natuerlich nur fuer laengere und ineinandergeschachtelte Schleifen.
Etwa fuer Boolean-bedingte while-Schleifen, die ineinanderzahnen, ist
mir das nach einiger Zeit eine Arbeitsersparnis beim Wiederbearbeiten,
zu sehen, welches end welche Schleife begrenzt.
Post by Joe Galinke
Eigentlich schon früher. Dann sind kurze Variablennamen sehr
hilfreich. Geschachtelte WITHs kommen mir nicht in meinen Code, die
schafft mein Hirn nicht ausreichend gut.
und das Ueberwachungsfenster im Compiler noch weniger
Leider habe ich geschachtelte withs als Fremdcode. Grauslich ist das,
mit denen zu arbeiten.
Post by Joe Galinke
Wo ich gerne WITH verwende ist bei manchen modalen Dialogen.
fcuntion TMyForm.GetDialogValue: TModalResult;
begin
with TMyDialogForm.Create(Application) do begin
try
Result := ShowModal;
finally
Free; //Das Free des erzeugten Formulars
end;
end;
end;
Dieses TMyDialogForm kommt ganz sicher ohne jegliche Formularvariable
aus, die automatisch erzeugte wird sowieso, wenn ich es nicht
vergesse, gleich beseitigt.
Was ist denn DAS?
Das sieht viel griffiger aus als meine Dialoge mit der Message Box.
* kopier *

Abgesehen davon, dass ich modale Dialoge vermeide. Zu oft kam ich an
ein Fenster nicht mehr ran und musste das Programm abschiessen. Nicht
in einenen Anwendungen. Ich vermeide modal ja wo geht, ;-)
Post by Joe Galinke
Post by Nicole Wagner
Meine augenblickliche Idee waere, in Zukunft stets "IBQuery." zu
verwenden, weil es das kuerzeste ist.
Warum gibst Du dem Kind nicht gleich einen passenden Namen? Ebenso
hoffe ich, dass IBTransaction1 nur der Name aus einem Testcode ist.
Meine Queries heissen alle so, wie ihre DBGrid-PageContolTab-Eltern.

Meine Transaction hingegen heisst wirklich nur 1.
Diese Transaction1 ist in irgendeinem Zusammenhang als "default"
gelistet (weiss nicht mehr wo, im OI?). Sobald ich eine andere
Transaction verwenden wollte, fand ich den Eintrag nicht mehr in der
DB. Bzw. sprang dieser default-Eintrag im OI hin und her und es
passierten seltsame Dinge.

Ich ging dann den Weg des geringsten Widerstandes und verwendete stets
nur die eine Transaction1, die funktionierte.


Liebe Gruesse,
Nicole
Joe Galinke
2011-03-29 13:40:42 UTC
Permalink
Hallo Nicole,
Post by Nicole Wagner
Post by Joe Galinke
Das ist kein Denglish. Die Property heißt nun einmal DataSource und
kann ja nicht an dieser Stelle anders benannt werden. "Die Proptery
DataSource eines DataSets gibt die Datenquelle....".
Denglish ist fuer mich, wenn jemand mit seltsamen Vokalbeln herumlallt,
etwa "schoppen geht" (hat der eine Ente zum Fuettern?). Und dann, wenn
jemand termini technici eindeutscht. Etwa "Eigenschaft" statt
"property" sagt. Fuer mich ist das nur ein Vokabel zusaetzlich.
Ach so, Du stößt Dich an der deutschen Bezeichnung Eigenschaft. Nun, die
finde ich aber vorrangig so in der deutschen Literatur verwendet. Ich
schreibe in deutschem Fließtext auch Prozedur und nicht Procedere. Das
halte ich für durchaus angemessen und habe diesbzüglich an dem betreffenden
Text nichts auszusetzen.
Post by Nicole Wagner
Wie ungluecklich die Uebersetzung per se und dann noch mit dem Wort
"Eigenschaft" ist, wird klar, wenn man sich vorstellt, man will nach
dem Wort suchen, nachdem man etwa "property read" gefunden hat.
In einem deutschen Hilfstext hätte ich durchaus "Eigenschaft" gewählt, in
Code eben "property".

War Dir der deutsche Begriff dafür wirklich so unbekannt?
Post by Nicole Wagner
Post by Joe Galinke
Stelle Dir es eher wie eine Verbindung oder Datenleitung vor. Du hast
die Datenmenge (TDataSet, TIBQuery, etc) und datensensitive Controls
wie die bereits genannten TDbGrid oder TDbEdit. Die Controls kommen
über die Dataquelle an die Datenmenge heran.
Ich probiere mit den neuen Woertern einmal, ob der Nebel im Kopf sich
lichtet.
Angenommen, ich habe Wasser, das sich in einem Berg sammelt.
Es fliesst aus dem Felsen ueber ein kleines Rohr in ein Becken.
Aus dem Becken kann Wasser geschoepft werden.
TDataBase: Das Wasser im Berg
TConnection: die Oeffnung im Felsen
TDataSource: das kleine Rohr? Und nicht das Becken?
Wasserschoepfen im Primaerbecken inkl. Wasserteilmenge und
Schoepfvorgang
Die Controls sind die Nutzniesser der Einrichtungen?
Und was ist die Gesamtheit des Beckens?
Ich glaube wirklich nicht, dass Dir solche Abbildungen weiterhelfen werden.
Zum Einen werden die Ähnlichkeiten an verschiedenen Stellen zu schwammig
werden, zum Anderen bist Du schon viel zu lange im Metier um es so
anzufangen. So kannst Du es Kindern klarmachen. Das ist nicht böse gemeint,
aber Du solltest Dir die Beispiele auf etwas höherem Niveau suchen.

Und wenn Du es schon versuchen willst, dann nimm doch Deine IB-Komponenten.
Da gibt es kein TConnection, sondern nur TIBDatabase.

Diese selbst enthält aber doch gar keine Daten. Diese liegen in Deine
Firebird-Datenbank; diese Datei ist Dein Berg. Die einzelnen Tabellen wäre
verschiedene Wasseransammlungen. Aber schon hier hört es auf sinnvoll zu
bleiben.

Du hast Deine Datenbankdatei mit vielen Tabellen und darin enthaltenen
Daten. Deine TIBDatabase-Komponente stellt nun lediglich eine
Schnittstelle/Verbindung zu diesen Daten dar. Diese Verbindung wird von
TDataset-Nachfahren wie TIBQuery genutzt, eine bestimmte Datenmenge
abzufragen und Dir zur Verfügung zu stellen.

Im Code kannst Du direkt auf die Eigenschaften des Datasets, wie z.B. die
einzelnen Felder und deren Inhalte zugreifen. FieldByName() liefert Dir ja
schließlich nur einen Zeige auf eine Instanz von TField, deren Eigenschaft
AsXXX Du zum lesen oder schreiben verwendest.

Visuelle Komponenten, wie Dein TDbGrid oder ein TDbEdit bekommen eine
TDataSource zugewiesen, die man auch als Verteiler bezeichnen kann. Dieser
Verteiler, dem ja ein DataSet zugewiesen wird, kann nun von vielen
visuellen Komponenten genutzt werden.

Warum man nicht direkt das DataSet an die visuellen Komponenten zuweist?
Als Grund kenne ich selbst nur das Ziel der Entkoppelung.

So kann man nur durch Zuweisung eines eine neuen DataSets an die Datasource
direkt alle visuellen Komponenten auf eine andere Datenmenge umschalten.

Außerdem geht man vielfach auch so vor, die Dataset-Komponenten auf einem
Datenmodul zu sammeln, die Datasource aber auf dem jeweiligen Formular.

Diese Entkoppelung nutzt TDataSource auf der UI-Ebene und TDataSet in der
Datenzugriffsebene.
Post by Nicole Wagner
Ich meinem DBGrid-testen komme ich auf viel hundert Klicks pro Tag.
Und neu Starten der Anwendung, weil sich meine DBGrids wieder mal
ungewollt geleert haben. So gehen die Stunden auch dahin.
Ich weiss nur noch immer nicht, was ich "Refresh" muss.
Die IBQuery-Instanz in der Deine Daten liegen
Wenn die Probleme so groß sind und Du so viel Zeit darin investieren musst,
dann kannst Du auf jeden Fall auch eine kleine Testanwendung bauen, so dass
Du gerade die Problematik ausprobieren kannst.

Dafür brauchst Du auch keine großen Datenstrukturen, immerhin versuchst Du
Dich in den Basics. Wenn Du da eine kleine Anwendung, die auch woanders
kompilierbar ist, d.h. ohne Verwendung irgendwelchen Codes aus Deinen
Toolunits (ja, es geht ohne) samt einer kleine Test-Datenbank bereitstellen
kannst, dann schaue ich da auch mal rein.
Post by Nicole Wagner
Wenn Self auf das Formular zeigt und ich mir das Wort dazudenken
kann,... kann ich dann nicht auch den Formularnamen explizit anweisen?
procedure TMyForm.TuWas;
MyForm.Caption := 'Ein Text';
?
Ja, das könntest Du, aber Du solltest es auf gar keinen Fall tun.

Im einfachsten Testprojekt wäre das automatische Codeerzeugung

TForm1.TuWas;
begin
Form1.Caption := ...
end;

Ok, Form1 zeigt auf die einzige Instanz von TForm1 und alles ist schön.
Diese Formular zeigt z.B. Detaildaten zu einem Kunden an und Du kommst
irgendwann auf die Idee, nicht nur die Daten des gerade im Grid
fokussierten Kunden anzuzeigen, sondern mehrere Fenster gleichzeitig
darzustellen. Was machst Du dann?

Wenn Du die einzelnen Formulare von außen ansprechen musst, dann hälst Du
irgendwo Zeiger auf Instanzen von TForm1 z.B. in einem dynamischen Array.
FormArray[x] := TForm.Create(Application);
FormArray[x].ShowData(Pk-Wert_eines_bestimmten_Kundenrecords);

Oder es reicht
with TForm1.Create(Application) do begin
ShowData(Pk-Wert_eines_bestimmten_Kundenrecords);
end;

Durch Action := caFree im OnFormClose-Event des Formulars musst Du Dich
nicht weiter darum kümmern. Wenn es geschlossen wird, wird es zerstört.

Aber da ist ja immer noch

TForm1.TuWas;
begin
Form1.Caption := ...
end;

Worauf zeigt denn nun Form1? Ja, vielleicht auf das irgendwann mal erzeugte
und noch immer nicht zerstörte Formular, aber eben nicht unbedingt auf sich
selbst, weil die Instanz deren Code gerade ausgeführt entweder gar keine
Zeiger hat der auf es zeigt, oder es ist FormArray[x].

Nun sage nicht, Du weißt, dass Du das Formular nur einmal brauchst. Ich
glaube Dir, auch wenn eine solche Aussage zu den berühmten letzten Worten
gehört. Du benötigst diese Verwendung nicht, wirklich nicht. Sie macht auch
nichts einfacher. Nichts. Ginge es nur um guten Stil und würde die
Verwendung etwas vereinfachen, dann könnte man auch auf den guten Stil
pfeifen. Aber zu so etwas will ich gar nicht raten. Guter Stil ist nicht
einfach eine Frage überkommener Gepflogenheiten, er macht Code auch
wartbarer und sicherer.

Fazit: Du sparst Dir die Verwendung der Variablen.
Post by Nicole Wagner
Post by Joe Galinke
Du siehst, dass ich nirgends meine Formularvariable verwendet habe?
Das tue ich auch niemals. NIEMALS.
interessant
D.h. ich verwende diese Formularvariable nicht im Code der Formularklasse,
evtl. habe ich nicht einmal eine.
Post by Nicole Wagner
Post by Joe Galinke
Sehr viele Formulare benötigen gar
keine Variable, da niemand von außen darauf zugreift. Auf jeden Fall
hat die Variable für ein Objekt nichts im Code der Klasse dieses
Objekts zu suchen.
ui, das habe ich nicht vestanden.
Was ist "die Variable fuer ein Objekt"?
Du hast eine Klasse TMyClass, Dein TMyForm ist nichts anderes. Diese Klasse
ist aber mehr nur eine Vorlage (Klassenmethode etc. lasse ich bewusst außen
vor), da lebt noch nichts.

Das geschieht erst mit dem Constructor Create(), dessen Rückgabewert einer
Variablen vom Typ dieser Klasse zugewiesen werden kann. Kann, nicht muss.

Mit dieser Erzeugung hast Du nun ein Objekt, eine Instanz der Klasse.
Natürlich kannst Du mehrere Instanzen erzeugen.

var
MyObject: TMyClass;

...
MyObject := TMyClass.Create;

TMyClass.Create;

Du hast nun 2 Instanzen von TMyClass, wobei Du nur auf die erste über
MyObject zugreifen kannst, auf die andere Instanz fehlt Dir der Zeiger.
Das muss aber nicht schlimm sein, wenn diese Instanz ihre Aufgabe auch so
erfüllen kann.
Post by Nicole Wagner
Post by Joe Galinke
Post by Nicole Wagner
Das passierte etwa haeufig in Zusammenhang mit TChart. Ich habe mir
daher angewoehnt, im Zweifel Form explizit hinzuschreiben. Zudem ich
mit meine hunderte Variablennamen nicht merken kann und die
Programmierhilfe quasi verwenden muss.
Ok, da habe ich nur die mitgelieferte Version.
Probiere einmal Pro.
Ich bin von der schlichtweg begeistert.
Sie hat nur eine Nag-Screen als Demo und ist uneingeschraenkt
funktionsfaehig.
Wenn ich sie brauche, werde ich sie verwenden, vorher nicht. :-)
Post by Nicole Wagner
Post by Joe Galinke
Post by Nicole Wagner
Doch Methoden, die nicht zum Formular gehoeren: Wie loest man das?
Legt man dafuer eine eigene Klasse an?
Wenn es nur eine kleine Hilfsfunktion ist, kommt sie einfach in die
Firmularunit. Spo benötigt man als Fallback-Funktion für
Sortieraufgaben eine einfache Funktion und eben keine Methode.
huch?
Ich habe mein Leben lang gedacht, Methode waere der Oberbegriff von
Funktionen und Prozeduren?
Ich "übersetze" es mir mit: "Methoden sind die Prozeduren und Funktionen
einer Klasse.".
Post by Nicole Wagner
Keine Unterstrichsuffixe?
Ohne die bin ich verloren. Ich kann nur mit Woertern.
Ich ueberlege zur Zeit, ob ich Unix nicht links liegen lasse mit all
den Kuerzeln.
Was hat das Eine mit dem Anderen zu tun? Auch ohne Unterstrichsuffixe kann
man sprechende Namen wählen. Besser sogar. IMHO.
Post by Nicole Wagner
ich vermeide es auch, wo geht.
Doch je laenger ein Block, desto mehr erspart das with
Schreibe ich ein begin und die Eingabetaste, dann schreibt mir Delphi
ein end; genau drunter.
D.h. ich habe meine begin-end-Block formatiert, bevor ich die erste
Zeile schreibe. Und bevor ich die Zeile schreibe, kopiere ich die
Befehlszeile als Kommentar hinter das end.
Also for i:=0 to 100 do
begin
end; // zu for i:=0 to 100
Dann erst beginne ich meinen Code zu tippen.
Klar macht man das so oder sollte es zumindest. Aber was hat das mit WITH
zu tun? Das Risiko, in einem With-Block versehentlich die falsche
Eigenschaft oder Methode zu verwenden steigt halt mit der Anzahl der
Zeilen.
Post by Nicole Wagner
Meine Transaction hingegen heisst wirklich nur 1.
Diese Transaction1 ist in irgendeinem Zusammenhang als "default"
gelistet (weiss nicht mehr wo, im OI?). Sobald ich eine andere
Transaction verwenden wollte, fand ich den Eintrag nicht mehr in der
DB. Bzw. sprang dieser default-Eintrag im OI hin und her und es
passierten seltsame Dinge.
Nicole! Du hast eine TIBTransaction auf Dein Formular/Datenmodul gezogen
und die IDE hat halt standardgemäß den Namen ohne führendes T, aber mit
abschließender Nummerierung vergeben. Hier eben die 1. Das IST der Default.

Benenne sie einfach um.


Gruß, Joe
--
Nicole Wagner
2011-03-30 11:13:48 UTC
Permalink
Post by Joe Galinke
Post by Nicole Wagner
Ich probiere mit den neuen Woertern einmal, ob der Nebel im Kopf
sich lichtet.
Angenommen, ich habe Wasser, das sich in einem Berg sammelt.
Es fliesst aus dem Felsen ueber ein kleines Rohr in ein Becken.
Aus dem Becken kann Wasser geschoepft werden.
TDataBase: Das Wasser im Berg
TConnection: die Oeffnung im Felsen
TDataSource: das kleine Rohr? Und nicht das Becken?
Wasserschoepfen im Primaerbecken inkl. Wasserteilmenge und
Schoepfvorgang
Die Controls sind die Nutzniesser der Einrichtungen?
Und was ist die Gesamtheit des Beckens?
Ich glaube wirklich nicht, dass Dir solche Abbildungen weiterhelfen
werden. Zum Einen werden die Ähnlichkeiten an verschiedenen Stellen
zu schwammig werden, zum Anderen bist Du schon viel zu lange im
Metier um es so anzufangen. So kannst Du es Kindern klarmachen. Das
ist nicht böse gemeint, aber Du solltest Dir die Beispiele auf etwas
höherem Niveau suchen.
Und wenn Du es schon versuchen willst, dann nimm doch Deine
IB-Komponenten. Da gibt es kein TConnection, sondern nur TIBDatabase.
Diese selbst enthält aber doch gar keine Daten. Diese liegen in Deine
Firebird-Datenbank; diese Datei ist Dein Berg. Die einzelnen Tabellen
wäre verschiedene Wasseransammlungen. Aber schon hier hört es auf
sinnvoll zu bleiben.
Die DB ist nicht mein Problem.
Das habe ich alles selbst modelliert und lange vorbereitet, WIE ich es
mache. SQL ist eine schlanke, gerade Sache.
Meine SQL Abfragen sind durch das "Verbot" der Redundanz beim
Informationsspeichern vielleicht mit den joins etwas kompliziert, aber
sie erscheinen mir (also subjektiv) keinesweg verworren, wie manche
Komponenten-Properties.


...
[Erklaerungen aufmerksam gelesen]
Post by Joe Galinke
Warum man nicht direkt das DataSet an die visuellen Komponenten
zuweist? Als Grund kenne ich selbst nur das Ziel der Entkoppelung.
So kann man nur durch Zuweisung eines eine neuen DataSets an die
Datasource direkt alle visuellen Komponenten auf eine andere
Datenmenge umschalten.
Das klingt aber interessant!
Post by Joe Galinke
Außerdem geht man vielfach auch so vor, die Dataset-Komponenten auf
einem Datenmodul zu sammeln, die Datasource aber auf dem jeweiligen
Formular.
Ich wuenschte, ich haette das auch getan.
Mein Formular ist recht unuebersichtlich geworden.
Post by Joe Galinke
Diese Entkoppelung nutzt TDataSource auf der UI-Ebene und TDataSet in
der Datenzugriffsebene.
Der Satz war mir zu hoch.
Die Abkuerzung UI ist mir nicht gelaeufig.
Post by Joe Galinke
Post by Nicole Wagner
Ich meinem DBGrid-testen komme ich auf viel hundert Klicks pro Tag.
Und neu Starten der Anwendung, weil sich meine DBGrids wieder mal
ungewollt geleert haben. So gehen die Stunden auch dahin.
Ich weiss nur noch immer nicht, was ich "Refresh" muss.
Die IBQuery-Instanz in der Deine Daten liegen
Wenn die Probleme so groß sind und Du so viel Zeit darin investieren
musst, dann kannst Du auf jeden Fall auch eine kleine Testanwendung
bauen, so dass Du gerade die Problematik ausprobieren kannst.
Dafür brauchst Du auch keine großen Datenstrukturen, immerhin
versuchst Du Dich in den Basics. Wenn Du da eine kleine Anwendung,
die auch woanders kompilierbar ist, d.h. ohne Verwendung
irgendwelchen Codes aus Deinen Toolunits (ja, es geht ohne) samt
einer kleine Test-Datenbank bereitstellen kannst, dann schaue ich da
auch mal rein.
ich fuerchte, das geht nicht.
Es ist alles derart komplex vernetzt. Hinter jedem Funktionsteil
haengen miteinander verbundene Units. Alleine die Liste der Units ist
einige Din A4 Seiten lang. Und alles ist auch noch vernetzt und greift
weitere fremd-DBs auf meiner HD und einige Dateien zu.

Doch ganz lieben Danke fuer Dein Angebot!
Post by Joe Galinke
Post by Nicole Wagner
Wenn Self auf das Formular zeigt und ich mir das Wort dazudenken
kann,... kann ich dann nicht auch den Formularnamen explizit
anweisen?
procedure TMyForm.TuWas;
MyForm.Caption := 'Ein Text';
?
Ja, das könntest Du, aber Du solltest es auf gar keinen Fall tun.
Im einfachsten Testprojekt wäre das automatische Codeerzeugung
TForm1.TuWas;
begin
Form1.Caption := ...
end;
Ok, Form1 zeigt auf die einzige Instanz von TForm1 und alles ist
schön. Diese Formular zeigt z.B. Detaildaten zu einem Kunden an und
Du kommst irgendwann auf die Idee, nicht nur die Daten des gerade im
Grid fokussierten Kunden anzuzeigen, sondern mehrere Fenster
gleichzeitig darzustellen. Was machst Du dann?
Wenn Du die einzelnen Formulare von außen ansprechen musst, dann
hälst Du irgendwo Zeiger auf Instanzen von TForm1 z.B. in einem
dynamischen Array. FormArray[x] := TForm.Create(Application);
FormArray[x].ShowData(Pk-Wert_eines_bestimmten_Kundenrecords);
Oder es reicht
with TForm1.Create(Application) do begin
ShowData(Pk-Wert_eines_bestimmten_Kundenrecords);
end;
Durch Action := caFree im OnFormClose-Event des Formulars musst Du
Dich nicht weiter darum kümmern. Wenn es geschlossen wird, wird es
zerstört.
Aber da ist ja immer noch
TForm1.TuWas;
begin
Form1.Caption := ...
end;
Worauf zeigt denn nun Form1? Ja, vielleicht auf das irgendwann mal
erzeugte und noch immer nicht zerstörte Formular, aber eben nicht
unbedingt auf sich selbst, weil die Instanz deren Code gerade
ausgeführt entweder gar keine Zeiger hat der auf es zeigt, oder es
ist FormArray[x].
Nun sage nicht, Du weißt, dass Du das Formular nur einmal brauchst.
Ich glaube Dir, auch wenn eine solche Aussage zu den berühmten
letzten Worten gehört.
* Sitze vor dem Schirm und lache laut *
Post by Joe Galinke
Du benötigst diese Verwendung nicht, wirklich
nicht. Sie macht auch nichts einfacher. Nichts. Ginge es nur um guten
Stil und würde die Verwendung etwas vereinfachen, dann könnte man
auch auf den guten Stil pfeifen. Aber zu so etwas will ich gar nicht
raten. Guter Stil ist nicht einfach eine Frage überkommener
Gepflogenheiten, er macht Code auch wartbarer und sicherer.
Fazit: Du sparst Dir die Verwendung der Variablen.
Jetzt weiss ich, warum mir meine Formulare noch nie um die Ohren
geflogen sind: Ich habe sie bis jetzt wirklich nur einmal verwendet.

Ich muss nach der Kommentarzeile suchen, wo "es nicht ging mit TChart".
Diese Probleme waren es, warum ich dazu ueberging, es immer explizit
anzufuehren.

Doch ich kenne die Regel: Was schief gehen kann, geht auch eines Tages
schief. Und wie bei mir kein Pfannengriff in den Gehbereich der Kueche
ragt, so versuche ich, robusten Code zu schreiben.
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Du siehst, dass ich nirgends meine Formularvariable verwendet habe?
Das tue ich auch niemals. NIEMALS.
interessant
D.h. ich verwende diese Formularvariable nicht im Code der
Formularklasse, evtl. habe ich nicht einmal eine.
Auch den Satz habe ich nicht verstanden.
Formularvariable ist:
Var Form1: TForm1; ?

und Code der Formularklasse waere:
Procedure TForm1.Tu_was;
begin
end;
?

Und was hast Du nicht mal?


Und wie ist das mit "self."?
"Muss" man das auch weglassen oder wuerde das kein Problem verursachen
koennen?
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Sehr viele Formulare benötigen gar
keine Variable, da niemand von außen darauf zugreift. Auf jeden
Fall >> hat die Variable für ein Objekt nichts im Code der Klasse
dieses >> Objekts zu suchen.
Post by Nicole Wagner
ui, das habe ich nicht vestanden.
Was ist "die Variable fuer ein Objekt"?
Du hast eine Klasse TMyClass, Dein TMyForm ist nichts anderes. Diese
Klasse ist aber mehr nur eine Vorlage (Klassenmethode etc. lasse ich
bewusst außen vor), da lebt noch nichts.
Das geschieht erst mit dem Constructor Create(), dessen Rückgabewert
einer Variablen vom Typ dieser Klasse zugewiesen werden kann. Kann,
nicht muss.
Mit dieser Erzeugung hast Du nun ein Objekt, eine Instanz der Klasse.
Natürlich kannst Du mehrere Instanzen erzeugen.
var
MyObject: TMyClass;
...
MyObject := TMyClass.Create;
TMyClass.Create;
Du hast nun 2 Instanzen von TMyClass, wobei Du nur auf die erste über
MyObject zugreifen kannst, auf die andere Instanz fehlt Dir der
Zeiger. Das muss aber nicht schlimm sein, wenn diese Instanz ihre
Aufgabe auch so erfüllen kann.
* Hirn rattert *
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Post by Nicole Wagner
Das passierte etwa haeufig in Zusammenhang mit TChart. Ich habe
mir >>> daher angewoehnt, im Zweifel Form explizit hinzuschreiben.
Zudem ich >>> mit meine hunderte Variablennamen nicht merken kann und
die >>> Programmierhilfe quasi verwenden muss.
Post by Nicole Wagner
Post by Joe Galinke
Ok, da habe ich nur die mitgelieferte Version.
Probiere einmal Pro.
Ich bin von der schlichtweg begeistert.
Sie hat nur eine Nag-Screen als Demo und ist uneingeschraenkt
funktionsfaehig.
Wenn ich sie brauche, werde ich sie verwenden, vorher nicht. :-)
All die tollen Dinge die es gibt, stehlen einem die Zeit zum Leben,
wenn man sie alle probieren wollte.
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Post by Nicole Wagner
Doch Methoden, die nicht zum Formular gehoeren: Wie loest man das?
Legt man dafuer eine eigene Klasse an?
Wenn es nur eine kleine Hilfsfunktion ist, kommt sie einfach in die
Firmularunit. Spo benötigt man als Fallback-Funktion für
Sortieraufgaben eine einfache Funktion und eben keine Methode.
huch?
Ich habe mein Leben lang gedacht, Methode waere der Oberbegriff von
Funktionen und Prozeduren?
Ich "übersetze" es mir mit: "Methoden sind die Prozeduren und
Funktionen einer Klasse.".
ah, das ist genauer gesagt.
Post by Joe Galinke
Post by Nicole Wagner
Keine Unterstrichsuffixe?
Ohne die bin ich verloren. Ich kann nur mit Woertern.
Ich ueberlege zur Zeit, ob ich Unix nicht links liegen lasse mit all
den Kuerzeln.
Was hat das Eine mit dem Anderen zu tun? Auch ohne Unterstrichsuffixe
kann man sprechende Namen wählen. Besser sogar. IMHO.
Dann brauchst Du eine Alternative schaetze ich, wie CamelCase?

Ich moechte meine Klassen / Methoden so benannt haben, dass ich im
Source Code in Stammelsprache lesen kann, was sie tun.

z.B.
myArrayClass.Lies_Array_in_DB(myArray);
myDBClass.tbKalender_read(datum, 'Feiertagsname');

Wenn der Code mal nicht laeuft, muss ich oft in jahralte Units
hineinsehen. Wenn ich die Schnittstellen nicht schnell finde, sitze ich
daran viel laenger als noetig.
In obigem Beispiel setze ich dann etwa den Breakpoint auf
"Lies_Array_in_DB" um festzustellen, wo die falsche Zahl herkommt.
Denn genau in solchen Zeile werden meine Objekte geschleust und dort
kann ich sie vergleichen und pruefen.

Wie machst Du das, wenn Du den Weg einer Zahl durch 50.000 Zeilen
finden musst?
Wie verwaltest Du die Informationen, was ein Codeteil tut?

Auch Kommentare werden mit der Masse lang zu lesen. Ich habe
mittlerweile in einer Unit schon stehen, wo ich zu lesen anfangen soll.
Post by Joe Galinke
Post by Nicole Wagner
Meine Transaction hingegen heisst wirklich nur 1.
Diese Transaction1 ist in irgendeinem Zusammenhang als "default"
gelistet (weiss nicht mehr wo, im OI?). Sobald ich eine andere
Transaction verwenden wollte, fand ich den Eintrag nicht mehr in der
DB. Bzw. sprang dieser default-Eintrag im OI hin und her und es
passierten seltsame Dinge.
Nicole! Du hast eine TIBTransaction auf Dein Formular/Datenmodul
gezogen und die IDE hat halt standardgemäß den Namen ohne führendes
T, aber mit abschließender Nummerierung vergeben. Hier eben die 1.
Das IST der Default.
Benenne sie einfach um.
Auf den Namen kommt es nicht an, sondern, dass es mir nicht gelungen
ist, mehr als eine Transaction zum Kooperieren mit meiner DB zu bringen.




Liebe Gruesse,
Nicole
Joe Galinke
2011-03-30 12:36:15 UTC
Permalink
Hallo Nicole,
Post by Nicole Wagner
Post by Joe Galinke
Außerdem geht man vielfach auch so vor, die Dataset-Komponenten auf
einem Datenmodul zu sammeln, die Datasource aber auf dem jeweiligen
Formular.
Ich wuenschte, ich haette das auch getan.
Mein Formular ist recht unuebersichtlich geworden.
Dieses noch umzubauen ist nun wirklich ein recht schmerzarmer Prozess.
Post by Nicole Wagner
Post by Joe Galinke
Diese Entkoppelung nutzt TDataSource auf der UI-Ebene und TDataSet in
der Datenzugriffsebene.
Der Satz war mir zu hoch.
Die Abkuerzung UI ist mir nicht gelaeufig.
User-Interface. Benutzerschnittstelle. Hier sind es die Formulare, Buttons,
Edits etc.
Post by Nicole Wagner
Post by Joe Galinke
Dafür brauchst Du auch keine großen Datenstrukturen, immerhin
versuchst Du Dich in den Basics. Wenn Du da eine kleine Anwendung,
die auch woanders kompilierbar ist, d.h. ohne Verwendung
irgendwelchen Codes aus Deinen Toolunits (ja, es geht ohne) samt
einer kleine Test-Datenbank bereitstellen kannst, dann schaue ich da
auch mal rein.
ich fuerchte, das geht nicht.
Es ist alles derart komplex vernetzt. Hinter jedem Funktionsteil
haengen miteinander verbundene Units. Alleine die Liste der Units ist
einige Din A4 Seiten lang. Und alles ist auch noch vernetzt und greift
weitere fremd-DBs auf meiner HD und einige Dateien zu.
Es geht um Deine Refresh-Problem. Ich bin bereit zu wetten, dass der
Aufwand vertretbar ist. Gerade durch die Verschlankung machst Du es Dir
selbst leichter, die Zusammenhänge überhaupt zu verstehen. Wenn Du es im
Testprogramm hinbekommen hast. Vergiss Deine originale Datenbank und baue
Dir eine kleine, die gerade so viel beinhaltet (also wenige Tabellen,
wenige Daten) um dein Problem nachzustellen. In einer separaten Anwendung
verwendest Du ebenfalls gerade so viel, dass Du das Problem mit dem Refresh
nachstellen kannst. Wenn Du es in dieser Anwendung hinbekommst, ist die
Übertragung in Deine Hauptanwendung nicht mehr das große Problem.

Wie gesagt, geht nicht darum, Deine Hauptanwendung auf ein Minimum
zusammenzustreichen. Eher kannst Du schon Deine Originaltabelle nehmen.

Es geht auch nicht darum, ob Du die Anwendung jemand anderem zum anschauen
gibst. Das Ziel ist es, nur das eigentliche Problem vor Augen zu haben. So
lässt sich das Problem,. wenn man es schon nicht jemand anderem zeigen
kann, so doch immerhin besser beschreiben. Bedenke, dass Dich die Antworten
auf Deine bisherigen Beschreibungen nicht weitergebracht haben.

Du meinst, das kostet Zeit? Klar. Aber wie lange kämpfst Du schon damit
herum?
Post by Nicole Wagner
Post by Joe Galinke
Fazit: Du sparst Dir die Verwendung der Variablen.
Jetzt weiss ich, warum mir meine Formulare noch nie um die Ohren
geflogen sind: Ich habe sie bis jetzt wirklich nur einmal verwendet.
Ich muss nach der Kommentarzeile suchen, wo "es nicht ging mit TChart".
Diese Probleme waren es, warum ich dazu ueberging, es immer explizit
anzufuehren.
Aber das eigentliche Problem war wahrscheinlich ein ganz anderes, bzw. auch
anders sauber zu lösen. Such mal, zeig mal.
Post by Nicole Wagner
Post by Joe Galinke
D.h. ich verwende diese Formularvariable nicht im Code der
Formularklasse, evtl. habe ich nicht einmal eine.
Auch den Satz habe ich nicht verstanden.
Var Form1: TForm1; ?
Ja.
Post by Nicole Wagner
Procedure TForm1.Tu_was;
begin
end;
?
Auch ja.
Post by Nicole Wagner
Und was hast Du nicht mal?
Zu meinem TForm1 gibt es evtl. keine Variable die darauf zeigt. Diese
Variablen sind ja im Grunde nur Zeiger, anders als z.B. eine
Integervariable.


Du erinnerst Du an meinen modalen Dialog?

with TMyDialog.Create(Application) do begin usw.?

In der Unit des Dialogs, der Unit mit der Klasse TMyDialog hat Delphi ja
automatisch eine Variable in Form von "MyDialog: TMyDialog" angelegt. Im
konkreten Fall brauche ich sie gar nicht, auf jeden fall findet sie
innerhalb der Formularunit keine Verwendung. Doch, es gibt schon Fälle,
aber selbst dann wird da noch umgebaut und die Variable ist im
Implementation-Teil, nicht im Interface. Aber das ist Stoff für eine
spätere Lektion.
Post by Nicole Wagner
Und wie ist das mit "self."?
"Muss" man das auch weglassen oder wuerde das kein Problem verursachen
koennen?
Das kann man gerne verwenden.

Wenn Du x Instanzen von TForm1 hast udn verwendest darin Self, dann zeigt
diese Self ja jedes Mal nur auf die eine eigene Instanz.
Post by Nicole Wagner
Post by Joe Galinke
Post by Nicole Wagner
ui, das habe ich nicht vestanden.
Was ist "die Variable fuer ein Objekt"?
Das ist wie mit dem Formular. Aber Variable trifft es nicht so richtig, es
ist ja eigentlich ein Zeiger.

Du hast irgendwo stehen:

y: TIrgendEineKlasseWelcheNatuerlichAuchEineFormularklasseSeinKann

Dann meinte ich mit Objektvariable eben jenes y.
Post by Nicole Wagner
Post by Joe Galinke
var
MyObject: TMyClass;
...
MyObject := TMyClass.Create;
TMyClass.Create;
Du hast nun 2 Instanzen von TMyClass, wobei Du nur auf die erste über
MyObject zugreifen kannst, auf die andere Instanz fehlt Dir der
Zeiger. Das muss aber nicht schlimm sein, wenn diese Instanz ihre
Aufgabe auch so erfüllen kann.
* Hirn rattert *
Lege doch mal einen Breakpoint ins Create einer Deiner Klassen und teste
es. Du wirst 2 mal daran vorbeikommen.
Post by Nicole Wagner
Dann brauchst Du eine Alternative schaetze ich, wie CamelCase?
Ja. Ich meinte auch wirklich Suffixe, also _ am Ende. So wie Du sie
verwendest um sprechende Bezeichner zu haben ist es ja vollkommen in
Ordnung. Ich persönlich setze sie nur eher selten ein, da mir eben
CamelCase lieber ist.
Post by Nicole Wagner
Wie machst Du das, wenn Du den Weg einer Zahl durch 50.000 Zeilen
finden musst?
Wie verwaltest Du die Informationen, was ein Codeteil tut?
Auch Kommentare werden mit der Masse lang zu lesen. Ich habe
mittlerweile in einer Unit schon stehen, wo ich zu lesen anfangen soll.
Ich bin sogar der Meinung, dass man wirklich zu viel kommentieren kann.
Sprechende Bezeichner und die Vermeidung supertoller, cleverer
Codekonstruktionen könne da auch schön helfen.
Code sollte möglichst schön langweilig sein, einfach und schlicht.

Bei LsNr := LsNr +1 brauche ich nicht den Kommentar, dass dort eine
Lieferscheinnummer inkrementiert wird. Für ganz fremde vielleicht noch der
Hinweis, dass es sich um eine Lieferscheinummer handelt bei der
Deklaration.

Allerdings muss ich gestehen, dass ich oft genug zu wenig dokumentiere.
Post by Nicole Wagner
Post by Joe Galinke
Benenne sie einfach um.
Auf den Namen kommt es nicht an, sondern, dass es mir nicht gelungen
ist, mehr als eine Transaction zum Kooperieren mit meiner DB zu bringen.
Brauchst Du mehrere?


Gruß, Joe
--
Nicole Wagner
2011-03-31 10:18:30 UTC
Permalink
Post by Joe Galinke
Es geht um Deine Refresh-Problem. Ich bin bereit zu wetten, dass der
Aufwand vertretbar ist. Gerade durch die Verschlankung machst Du es
Dir selbst leichter, die Zusammenhänge überhaupt zu verstehen. Wenn
Du es im Testprogramm hinbekommen hast. Vergiss Deine originale
Datenbank und baue Dir eine kleine, die gerade so viel beinhaltet
(also wenige Tabellen, wenige Daten) um dein Problem nachzustellen.
In einer separaten Anwendung verwendest Du ebenfalls gerade so viel,
dass Du das Problem mit dem Refresh nachstellen kannst. Wenn Du es in
dieser Anwendung hinbekommst, ist die Übertragung in Deine
Hauptanwendung nicht mehr das große Problem.
Ich finde jetzt das Link nicht, doch gestern habe ich gelesen, dass
Refresh fuer IBQuery-Komponenten zumeist nicht implementiert ist. Man
soll stattdessen die Query schalten.

Das Link war auf jeden Fall ein Klick von diesem Ausgangspunkt:
http://docwiki.embarcadero.com/RADStudio/de/Nachkommen_der_Klasse_TDataS
et_verwenden

Fuer heute werde ich mir alle Schaltungen in eine ActionList schreiben
und sie einmal haendisch klicken. Denn zuweilen sind meine DBGrids leer
und dann warte ich manchmal ungleich laenger als es in IBExperts dauern
wuerde, bis sie sich wieder fuellen.

Ich vermute den Fehler gerade in der Vernetzung. Etwa, dass irgendetwas
mein onCalc-Event in eine zu lange Schleife draengt. Ich ueberlege,
statt der Lookup-Zuordnungen im DBGrid Suchen-mit-DisableControls. In
der Hilfe habe ich dazu eine Idee gefunden. Ob sie gut ist, wird sich
weisen.
Post by Joe Galinke
Du meinst, das kostet Zeit? Klar. Aber wie lange kämpfst Du schon
damit herum?
Viel, viel, viel zu lange!
Jeden Tag bin ich mir boese dafuer.

Trotzdem vermute ich den Fisch in der Interaktion der DBGrids.
Ich werde heute einmal alle Schaltungen auf Klick laufen lassen.

Ich fuerchte, drei Tage ueber der Erstellung eines vereinfachten Modell
zu sitzen und nachher nicht auch nicht klueger zu sein.
Post by Joe Galinke
Post by Nicole Wagner
Und was hast Du nicht mal?
Zu meinem TForm1 gibt es evtl. keine Variable die darauf zeigt. Diese
Variablen sind ja im Grunde nur Zeiger, anders als z.B. eine
Integervariable.
Wo mein Formular seine Var in alle Units zerstreut, ist etwa der
Progress Bar.
Da habe ich in einer voellig anderen nicht-visuellen Unit ploetzlich
einen StepIt-Aufruf. Das will mir gar nicht gefallen.
Post by Joe Galinke
Du erinnerst Du an meinen modalen Dialog?
teilweise, zudem weiss ich, wo ich ihn gesichert habe ;-)
Post by Joe Galinke
with TMyDialog.Create(Application) do begin usw.?
In der Unit des Dialogs, der Unit mit der Klasse TMyDialog hat Delphi
ja automatisch eine Variable in Form von "MyDialog: TMyDialog"
angelegt. Im konkreten Fall brauche ich sie gar nicht, auf jeden fall
findet sie innerhalb der Formularunit keine Verwendung. Doch, es gibt
schon Fälle, aber selbst dann wird da noch umgebaut und die Variable
ist im Implementation-Teil, nicht im Interface. Aber das ist Stoff
für eine spätere Lektion.
Grundsatzfrage:
Laesst Du Deine Forms automatisch erstellen?
Ich habe das alles abgedreht, weil ich mich noch weniger heraussah, was
jetzt "da" war und was nicht.
Post by Joe Galinke
Post by Nicole Wagner
Und wie ist das mit "self."?
"Muss" man das auch weglassen oder wuerde das kein Problem
verursachen koennen?
Das kann man gerne verwenden.
Wenn Du x Instanzen von TForm1 hast udn verwendest darin Self, dann
zeigt diese Self ja jedes Mal nur auf die eine eigene Instanz.
Dann werde ich mal "self" probieren, sobald ich meinen
TChart-nil-Zugriff wieder finde.
Post by Joe Galinke
Ich bin sogar der Meinung, dass man wirklich zu viel kommentieren
kann. Sprechende Bezeichner und die Vermeidung supertoller, cleverer
Codekonstruktionen könne da auch schön helfen.
Code sollte möglichst schön langweilig sein, einfach und schlicht.
Genau: "Wenn Du viele Moeglichkeiten zur Wahl hast, waehle die
einfachste."

(Das ist fuer mich persoenlich mehr Thema, als Du vermutlich ahnst. Die
Boerse wahrscheinlichkeitstheoretisch durchzurechnen, ist alles andere
als einfach. Und die Idee ist so bestechend, dass "jeder" es will: Denn
im Simpeli-Denken Vieler ist so ein Programm eine Geldmaschine.

Beginnen sie mal mit dem Projekt, dann zeigt ihnen das bald, dass die
Sache eben so einfach nicht ist. Was tun sie? Sie verwirren ihre Idee
bis zum Exzess und behaupten anschliessend, sie waere nicht
programmierbar.

Was ich anders mache? - Ich gehe nicht davon aus, dass es eine
Boersenberechnung ieS geben kann. Vielmehr muss man die
Wahrscheinlichkeiten davon mathematisch verwalten. Riskmanagement
nennen es die Insider.)
Post by Joe Galinke
Bei LsNr := LsNr +1 brauche ich nicht den Kommentar, dass dort eine
Lieferscheinnummer inkrementiert wird. Für ganz fremde vielleicht
noch der Hinweis, dass es sich um eine Lieferscheinummer handelt bei
der Deklaration.
Allerdings muss ich gestehen, dass ich oft genug zu wenig
dokumentiere.
;-)
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Benenne sie einfach um.
Auf den Namen kommt es nicht an, sondern, dass es mir nicht gelungen
ist, mehr als eine Transaction zum Kooperieren mit meiner DB zu bringen.
Brauchst Du mehrere?
Das weiss ich nicht!
Die Interaktion meiner IBQeries liegt im Argen.

Aber nachdem, was ich gestern ueber Transaktionen gelesen habe, sollte
meine Loesung woanders sein.



Liebe Gruesse,
Nicole
Joe Galinke
2011-03-31 13:21:09 UTC
Permalink
Hallo Nicole Wagner,
Post by Nicole Wagner
Ich finde jetzt das Link nicht, doch gestern habe ich gelesen, dass
Refresh fuer IBQuery-Komponenten zumeist nicht implementiert ist. Man
soll stattdessen die Query schalten.
Zumeist nicht implementiert? Entweder ist es das oder eben nicht. Klar,
wenn es nicht implementiert ist, musst Du Dir anders helfen.

"Query schalten"?
Du meinst schließen und wieder öffnen? Klar, damit wird ja alles neu
gelesen. Erwähnte ich die Möglichkeit nicht in einem meiner Postings? Ich
weiß es nicht mehr.
Post by Nicole Wagner
Ich vermute den Fehler gerade in der Vernetzung. Etwa, dass irgendetwas
mein onCalc-Event in eine zu lange Schleife draengt. Ich ueberlege,
statt der Lookup-Zuordnungen im DBGrid Suchen-mit-DisableControls. In
der Hilfe habe ich dazu eine Idee gefunden. Ob sie gut ist, wird sich
weisen.
Ich habe das Gefühl, Du suchst nach Strohhalmen.
Post by Nicole Wagner
Post by Joe Galinke
Du meinst, das kostet Zeit? Klar. Aber wie lange kämpfst Du schon
damit herum?
Viel, viel, viel zu lange!
Jeden Tag bin ich mir boese dafuer.
Trotzdem vermute ich den Fisch in der Interaktion der DBGrids.
Ich werde heute einmal alle Schaltungen auf Klick laufen lassen.
Noch ein Strohhalm. :-)
Post by Nicole Wagner
Ich fuerchte, drei Tage ueber der Erstellung eines vereinfachten Modell
zu sitzen und nachher nicht auch nicht klueger zu sein.
Erstens dauert das keine 3 Tage. Du willst ja nur das prinzipielle Handling
nachstellen. Auch die Inhalte von OnCalcFields() und Konsorten können da
einfacher sein, ebenso die Abfragen selbst. Hol Dir auch nicht alles mit
Copy/Paste aus dem alten Code. Genau das wäre kontraproduktiv.

Zweitens, auch wenn Du nicht klüger sein solltest, Du wirst das Problem
deutlich und klarer beschreiben können, das macht es anderen leichter, oder
gar erst möglich, Dir zu helfen.

Drittens stehen sogar die Chancen recht gut, dass Du von alleine darauf
kommst. Gerade dadurch, dass man nicht im alten Code rumwühlt, sondern neu
herangeht wird oft vieles klarer.

Viertens sind Dir doch genügend Basics noch gar nicht klar; diese
Unklarheiten könntest Du so schon reduzieren.

Kennst Du es nicht von schlichten Matheaufgaben her, dass man ewig nach
einem Fehler sucht und den nicht findet? Schreibt man die Rechnung komplett
neu (nicht einfach nur ab), kommt man manchmal auch von alleine darauf.

Dein Aufnehmen von Strohhalmen und herumbasteln kann natürlich auch zum
Erfolg führen, mit Glück sogar schnell. Meist ist es jedoch ganz anders und
dauert wesentlich länger. Der vermeintlich aufwändigere Weg stellt sich
längerfristig im Mittel oft als der schnellere Weg.

Ich weiß das deshalb, weil ich natürlich auch zu oft in diese Falle laufe.
"Das probiere ich noch aus...."
Es gibt ja Leute, die behaupten, jeden Fehler nur ein mal zu machen. Leider
darf ich das von mir nicht in allen Fällen behaupten.
Post by Nicole Wagner
Wo mein Formular seine Var in alle Units zerstreut, ist etwa der
Progress Bar.
Da habe ich in einer voellig anderen nicht-visuellen Unit ploetzlich
einen StepIt-Aufruf. Das will mir gar nicht gefallen.
Dein Formular verstreut Variablen in verschiedene Units? Was bedeutet das?
Post by Nicole Wagner
Laesst Du Deine Forms automatisch erstellen?
Ich habe das alles abgedreht, weil ich mich noch weniger heraussah, was
jetzt "da" war und was nicht.
Nein, außer dem MainForm eigentlich niemals. Evtl. lass ich ein
Datenformular vorher noch automatisch erzeugen, alle anderen auch nur bei
Bedarf.

Aber ich mache das nicht, weil ich dann nicht wüsste was da ist und was
nicht. Festgeschrieben steht es in der DPR und aufpassen müsste ich dann
nur im FormCreate der anderen Formulare, dass ich da nicht auf noch nicht
existente Formulare zugreife. Na ja, blöd udn steif wäre es trotzdem.

Ich mache es deshalb nicht, weil ich die Dinger erst erzeuge wenn ich sie
brauche und wenn die Verwendung auch ein klares Ende hat, werden sie dann
auch gleich entsorgt.

Also entweder durch ein
...Create..
try
//
finally
...Free;
end;

oder ein Action := caFree im FormClose des Formulars.
Post by Nicole Wagner
Dann werde ich mal "self" probieren, sobald ich meinen
TChart-nil-Zugriff wieder finde.
Zeig lieber mal die Stelle.


Gruß, Joe
--
Nicole Wagner
2011-04-01 10:48:17 UTC
Permalink
Post by Joe Galinke
"Query schalten"?
Du meinst schließen und wieder öffnen?
IBQUery.Active:=false;
...
IBQUery.Active:=true;
Post by Joe Galinke
Klar, damit wird ja alles neu
gelesen.
eben nicht!
Es fehlen mir Zahlen in meinen berechneten Feldern.
Ich weiss nicht, wie ich meine Events OnCalcFields und OnFilterRecords
(hiessen die so?) aufrufen kann.
Ein direkter Aufruf der Methoden tut einfach nichts.
Auch Filtered zu schalten tut nichts oder nicht das Gewuenschte.

Diese Events haben nur funktioniert, als ich die Maschine es machen
liess, bzw. als ich sie mit dem Scrollen ausloeste.



Apropos: Weisst Du, ob es eine Moeglichkeit gibt, "Disable Controls" zu
schalten und trotzdem zu scrollen?
Mit anderen Worten: Ich brauechte einen Zustand, der den Inhalt meines
DBGrids kennt und mir als Text anzeigt, aber nicht neu berechnet. Kann
man Controls teilweise abschalten?
Post by Joe Galinke
Post by Nicole Wagner
Ich vermute den Fehler gerade in der Vernetzung. Etwa, dass
irgendetwas mein onCalc-Event in eine zu lange Schleife draengt.
Ich ueberlege, statt der Lookup-Zuordnungen im DBGrid
Suchen-mit-DisableControls. In der Hilfe habe ich dazu eine Idee
gefunden. Ob sie gut ist, wird sich weisen.
Ich habe das Gefühl, Du suchst nach Strohhalmen.
Spock lag mit seinen Gefuehlen stets richtig, wenn er sie zuliess.
:-)
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Du meinst, das kostet Zeit? Klar. Aber wie lange kämpfst Du schon
damit herum?
Viel, viel, viel zu lange!
Jeden Tag bin ich mir boese dafuer.
Trotzdem vermute ich den Fisch in der Interaktion der DBGrids.
Ich werde heute einmal alle Schaltungen auf Klick laufen lassen.
Noch ein Strohhalm. :-)
Schilf, nicht Stroh.
Hat sich nett gebogen: Die Zugriffsverzoegerung zwischen meinen
PageControl-Tabs-Wechsel ist weg. Ich kann jetzt "normal" hin- und
herschalten, ohne dazwischen eine Minute Wartezeit.

Dass mein Calc und Filter nicht mehr arbeitet, steht leider auf einem
anderen Blatt und haengt damit zusammen. Doch wenigstens weiss ich
jetzt, dass ich dort meine Problemquelle habe.
Post by Joe Galinke
Post by Nicole Wagner
Ich fuerchte, drei Tage ueber der Erstellung eines vereinfachten
Modell zu sitzen und nachher nicht auch nicht klueger zu sein.
Erstens dauert das keine 3 Tage. Du willst ja nur das prinzipielle
Handling nachstellen.
Ich kann recht gut abschaetzen, wie lange das dauert.
Denn ich fuerchte, ich habe immer wieder mal "ganz von vorne
angefangen".
Post by Joe Galinke
Auch die Inhalte von OnCalcFields() und
Konsorten können da einfacher sein, ebenso die Abfragen selbst. Hol
Dir auch nicht alles mit Copy/Paste aus dem alten Code. Genau das
wäre kontraproduktiv.
Meine OnCalcField Procedure hatte ich zwischenzeitlich schon gekuerzst
auf:

begin
exit;
end;





[....]
Deine Argumente sind gut und auch richtig.
Doch ob man neu aufsetzt bei einer Schwierigkeit oder nicht, ist immer
im Einzelfall zu beurteilen.
Oft schon habe ich mich fuer "neu" entschieden.
Diesmal hoffe ich, dass es anders schneller geht.
Die Hoffnung stirbt bekanntlich zuletzt ;-)
Post by Joe Galinke
Dein Aufnehmen von Strohhalmen und herumbasteln kann natürlich auch
zum Erfolg führen, mit Glück sogar schnell. Meist ist es jedoch ganz
anders und dauert wesentlich länger. Der vermeintlich aufwändigere
Weg stellt sich längerfristig im Mittel oft als der schnellere Weg.
Ich weiß das deshalb, weil ich natürlich auch zu oft in diese Falle
laufe. "Das probiere ich noch aus...."
Es gibt ja Leute, die behaupten, jeden Fehler nur ein mal zu machen.
Leider darf ich das von mir nicht in allen Fällen behaupten.
ach, ich mache meine Fehler immer wieder.
Die Leute, die von sich anders denken, haben oft nur ein schlechtes
Gedaechtnis oder Illusionen.

Zuweilen habe ich mir auch Fehlerkontrollschemata gemacht, wie bei
Flugzeugabstuerzen. Dabei kam ich drauf, dass auch ich mir ziemliche
Illusionen mache. Erst das Kontrollschema zeigte mir, wie fehler- und
illsuionsbehaftet ich wirklich bin.
Spannend ist es, sich Dinge schriftlich zu notieren, "bei denen man
sich ganz sicher ist". Hat man sich geirrt, denkt man sich "ich habe es
ja gleich gewusst" - in der eigenen Handschrift steht aber was Anderes.

Wer sich davor gefeilt fuehlt, teste sich selbst - schriftlich ;-)
Post by Joe Galinke
Post by Nicole Wagner
Wo mein Formular seine Var in alle Units zerstreut, ist etwa der
Progress Bar.
Da habe ich in einer voellig anderen nicht-visuellen Unit ploetzlich
einen StepIt-Aufruf. Das will mir gar nicht gefallen.
Dein Formular verstreut Variablen in verschiedene Units? Was bedeutet das?
ich fabuliere mal ein Beispiel:

Unit Dos-Konsolen-Rechnung;
....
Prozedure Nicht-Visuelle-Array-Iteration(DB-Info);
....
for i:=Low(DB-Info) to high(DB-Info) do
begin
MathematischeKomplexanweisung (DB[i]);
If i = 50 then
===> Form1.ProgressBar1.StepIt(5);
end;


Das ist doch keine elegante Kapselung.
Post by Joe Galinke
Post by Nicole Wagner
Laesst Du Deine Forms automatisch erstellen?
Ich habe das alles abgedreht, weil ich mich noch weniger heraussah,
was jetzt "da" war und was nicht.
Nein, außer dem MainForm eigentlich niemals.
ich nicht mal das. Denn oft brauche ich das gar nicht.
Post by Joe Galinke
Ich mache es deshalb nicht, weil ich die Dinger erst erzeuge wenn ich
sie brauche und wenn die Verwendung auch ein klares Ende hat, werden
sie dann auch gleich entsorgt.
mache ich auch.
Post by Joe Galinke
Post by Nicole Wagner
Dann werde ich mal "self" probieren, sobald ich meinen
TChart-nil-Zugriff wieder finde.
Zeig lieber mal die Stelle.
Habe keine Zeit zum Suchen. Erst muss mein DBGrid tun, was es soll.
Leider muckt jetzt die Fremd-DB und verbindet sich nicht, wie sie soll.
Das werde ich mir heute vornehmen. *Haare rauf*

Doch Thema self:
Ich habe gestern schon mal probiert, statt
"FormName."
zu schreiben
"self."

Und schon hatte es einen Nachteil:
"Refactor"-Variablen-umbenennen funktionierte nicht mehr.
Erst als ich voll zitierte, inkl. "FormName." wurde meine Methode
wieder korrekt in alle Zusammenhaengen umbenannt.



Liebe Gruesse,
Nicole
Burkhard Schneider
2011-04-01 10:55:44 UTC
Permalink
Post by Nicole Wagner
Apropos: Weisst Du, ob es eine Moeglichkeit gibt, "Disable Controls" zu
schalten und trotzdem zu scrollen?
Mit anderen Worten: Ich brauechte einen Zustand, der den Inhalt meines
DBGrids kennt und mir als Text anzeigt, aber nicht neu berechnet. Kann
man Controls teilweise abschalten?
Langsam beschleicht mich der Gedanke, dass du besser ein "normales"
StringGrid genommen hättest anstatt eines DBGrids. Editierst Du die Daten
eigentlich in dem DBGrid?
Ansonsten wäre ein StringGrid vielleicht die bessere Lösung: Einfach in
einer While not Query.eof - Schleife den Inhalt der Query samt den
berechneten Werten ins StringGrid packen. Wenn dann irgendetwas neu
berechnet wird, kannst du es direkt in die entsprechenden Zellen Schreiben.

Nur so ne Idee...

Gruß
Burkhard Schneider
Nicole Wagner
2011-04-01 11:06:16 UTC
Permalink
Post by Burkhard Schneider
Post by Nicole Wagner
Apropos: Weisst Du, ob es eine Moeglichkeit gibt, "Disable
Controls" zu schalten und trotzdem zu scrollen?
Mit anderen Worten: Ich brauechte einen Zustand, der den Inhalt
meines DBGrids kennt und mir als Text anzeigt, aber nicht neu
berechnet. Kann man Controls teilweise abschalten?
Langsam beschleicht mich der Gedanke, dass du besser ein "normales"
StringGrid genommen hättest anstatt eines DBGrids. Editierst Du die
Daten eigentlich in dem DBGrid? Ansonsten wäre ein StringGrid
vielleicht die bessere Lösung: Einfach in einer While not Query.eof -
Schleife den Inhalt der Query samt den berechneten Werten ins
StringGrid packen. Wenn dann irgendetwas neu berechnet wird, kannst
du es direkt in die entsprechenden Zellen Schreiben.
... die Idee ist nicht von der Hand zu weisen.
Ich habe sie schon die laengste Zeit im Hinterkopf.

StringGrid kenne ich gut und kann damit auch "alles" machen, was es
kann.

Leider von dieserm Wissen her: Ich brauche eher DBGrid.


Nicole
Joe Galinke
2011-04-01 14:00:22 UTC
Permalink
Hallo Nicole,
Post by Nicole Wagner
IBQUery.Active:=false;
...
IBQUery.Active:=true;
Post by Joe Galinke
Klar, damit wird ja alles neu
gelesen.
eben nicht!
Wenn die IB-Komponenten nicht seltsam gestrickt sind, dann sollte das
.Close/.Open entsprechen. Dann möchte ich darauf wetten, dass die Daten
jener Query neu gelesen werden. Setze mal einen Haltepunkt auf das
IBQUery.Active:=true und ändere parallel mit IBExpert mal einen Wert in der
Tabelle, der zu einem anderen Ergebnis führen müsste. Dann gehe in Deiner
Anwendung weiter; die Änderung wird auch in der Datenmenge sein.

Oder ist es nicht so, dass Du das Neueinlesen nur aufgrund eines
Anzeigeproblems nicht siehst?
Post by Nicole Wagner
Es fehlen mir Zahlen in meinen berechneten Feldern.
Ich weiss nicht, wie ich meine Events OnCalcFields und OnFilterRecords
(hiessen die so?) aufrufen kann.
Du rufst die nicht auf, das sind Ereignisse. Die _werden_ aufgerufen.
Post by Nicole Wagner
Ein direkter Aufruf der Methoden tut einfach nichts.
Dafür sind die auch nicht gedacht.
Post by Nicole Wagner
Apropos: Weisst Du, ob es eine Moeglichkeit gibt, "Disable Controls" zu
schalten und trotzdem zu scrollen?
Mit anderen Worten: Ich brauechte einen Zustand, der den Inhalt meines
DBGrids kennt und mir als Text anzeigt, aber nicht neu berechnet. Kann
man Controls teilweise abschalten?
Nochmal: Das Grid hat keinen Inhalt, es stellt den Inhalt einer Datenmenge
dar. Bitte bedenke das.

Wenn Du den Inhalt Deiner Datenmenge separat kontrollieren möchtest,
schreibe ihn doch mit einer einfachen Routine auf die Platte.

http://www.galinke.de/downloads/SaveDataSetToFile.pas
Post by Nicole Wagner
Schilf, nicht Stroh.
Hat sich nett gebogen: Die Zugriffsverzoegerung zwischen meinen
PageControl-Tabs-Wechsel ist weg. Ich kann jetzt "normal" hin- und
herschalten, ohne dazwischen eine Minute Wartezeit.
Dass mein Calc und Filter nicht mehr arbeitet, steht leider auf einem
anderen Blatt und haengt damit zusammen. Doch wenigstens weiss ich
jetzt, dass ich dort meine Problemquelle habe.
"Der Motor meines Wagens ist jetzt endlich ganz leise. Er startet nicht
mehr." SCNR.
Post by Nicole Wagner
Post by Joe Galinke
Erstens dauert das keine 3 Tage. Du willst ja nur das prinzipielle
Handling nachstellen.
Ich kann recht gut abschaetzen, wie lange das dauert.
Denn ich fuerchte, ich habe immer wieder mal "ganz von vorne
angefangen".
Ich meinte ganz und gar nicht, dass Du das halbe Programm neu schreiben
sollst. Es geht nur um eine Beispielanwendung.
Post by Nicole Wagner
Oft schon habe ich mich fuer "neu" entschieden.
Eben, darum geht es im Moment ja nicht.
Post by Nicole Wagner
Post by Joe Galinke
Dein Formular verstreut Variablen in verschiedene Units? Was bedeutet das?
Unit Dos-Konsolen-Rechnung;
....
Prozedure Nicht-Visuelle-Array-Iteration(DB-Info);
....
for i:=Low(DB-Info) to high(DB-Info) do
begin
MathematischeKomplexanweisung (DB[i]);
If i = 50 then
===> Form1.ProgressBar1.StepIt(5);
end;
Nicht Dein Formular verstreut Variablen, Du nutzt eine Variable die auf
dein Formular zeigt recht wild überall.

Das Beispiel sieht schlimm aus.
Einigermaßen elegant wäre ein Datenmodul welches die Berechnung ausführt
und ein Event OnProgress(Step: Integer) anbietet. Form1 hängt sich an das
Event und handhabt Progressbar. Wie der Fortschritt nämlich dargestellt
wird, das geht die Berechnusgroutine nichts an.

Einfacher geht es, indem der Routine eine Parameter ProgressForm:
TMyProgressForm mitgegeben wird. Nun kann man innerhalb der Routine
ProgressForm:ProgressBar... aufrufen oder, etwas sauberer, eine
public-Methode DoProgress(Step: Integer).
TMyProgressForm.DoProgress() versorgt dann den Balken. Ich mag dabei nicht,
dass Deine Werkzeugunit nun ein spezielles Formular, bzw. dessen Klasse,
kennen muss.

Das wäre die ersten einfachen Lösungen.
Post by Nicole Wagner
Ich habe gestern schon mal probiert, statt
"FormName."
zu schreiben
"self."
"Refactor"-Variablen-umbenennen funktionierte nicht mehr.
Erst als ich voll zitierte, inkl. "FormName." wurde meine Methode
wieder korrekt in alle Zusammenhaengen umbenannt.
Das wäre für mich niemals ein Grund, FormName statt Self zu verwenden. Wenn
es mir wichtig wäre würde ich halt schauen, ob ich auf das Self selbst
verzichten könnte.

Nochmal zur Sicherheit, es handelt sich um eine Methode von FormName, in
der Du das brauchst? Zeige die Methode doch mal.



Gruß, Joe
--
Nicole Wagner
2011-04-04 11:47:08 UTC
Permalink
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Klar, damit wird ja alles neu
gelesen.
eben nicht!
Wenn die IB-Komponenten nicht seltsam gestrickt sind, dann sollte das
.Close/.Open entsprechen.
in der Hilfe habe ich gelesen, dass dem so waere.
Probiert habe ich es nicht.
Post by Joe Galinke
Dann möchte ich darauf wetten, dass die
Daten jener Query neu gelesen werden. Setze mal einen Haltepunkt auf
das IBQUery.Active:=true und ändere parallel mit IBExpert mal einen
Wert in der Tabelle, der zu einem anderen Ergebnis führen müsste.
Dann gehe in Deiner Anwendung weiter; die Änderung wird auch in der
Datenmenge sein.
ui, darueber muss ich nachdenken.
Ich schreibe im Grunde gar nichts in mein DBGrid.

Die DB Aenderungen sind so komplex, dass ich mir ein Panel mit normalen
Edits (also TEdit, nicht TDBEDit) gemacht habe, das alle Aenderungen
auflistet. Ein Button prueft erst mal alle Eingabe auf Stimmigkeit und
schickt dann alle Felder an die DB direkt via IBSQL einer anderen Unit.
(dass das eine andere Unit tut, ist ein ganz anderes Thema, das mit dem
Zusammenspiel der DBGrids nichts zu tun hat. Das andere Thema macht
zwar auch Probleme, doch ist zur Zeit auf ToDo)

IBQuery.Active schalte ich zur Zeit, um eine bessere Kontrolle zu
haben, auf Menue-Click.

Auch im OI habe ich "active" abgedreht.
Mir faellt im Augenblick kein Breakpoint ein.
Post by Joe Galinke
Oder ist es nicht so, dass Du das Neueinlesen nur aufgrund eines
Anzeigeproblems nicht siehst?
glaube ich nicht.
Aber ich werde es noch mal extra pruefen.
Post by Joe Galinke
Post by Nicole Wagner
Es fehlen mir Zahlen in meinen berechneten Feldern.
Ich weiss nicht, wie ich meine Events OnCalcFields und
OnFilterRecords (hiessen die so?) aufrufen kann.
Du rufst die nicht auf, das sind Ereignisse. Die werden aufgerufen.
Post by Nicole Wagner
Ein direkter Aufruf der Methoden tut einfach nichts.
Dafür sind die auch nicht gedacht.
ist mir schon klar, aber ich braeuchte es.
Vor allem Abschalten-Koennen wuerde ich es gerne.
So ala
OnCalcEvent.Trigger.Disable;
Post by Joe Galinke
http://www.galinke.de/downloads/SaveDataSetToFile.pas
DANKE!

Mit diesem Thema habe ich mich schon vor Wochen herumgeschlagen, mit
SaveToFile und LoadFromFile. Da ist aber nichts dabei herausgekommen.
Jetzt habe ich es als nicht-dringend auf die ToDo Liste gesetzt.
Post by Joe Galinke
Post by Nicole Wagner
Schilf, nicht Stroh.
Hat sich nett gebogen: Die Zugriffsverzoegerung zwischen meinen
PageControl-Tabs-Wechsel ist weg. Ich kann jetzt "normal" hin- und
herschalten, ohne dazwischen eine Minute Wartezeit.
Dass mein Calc und Filter nicht mehr arbeitet, steht leider auf
einem anderen Blatt und haengt damit zusammen. Doch wenigstens
weiss ich jetzt, dass ich dort meine Problemquelle habe.
"Der Motor meines Wagens ist jetzt endlich ganz leise. Er startet
nicht mehr." SCNR.
haha

Sie arbeiten mittlerweile wieder zuviel. brrrrrrrruuummm roar
Wann was und wovon ausgeloest wird, das habe ich noch immer nicht raus.
Die Listung ist der Hilfe ist recht oberflaechlich.

Jedenfalls finde ich zu meiner Ueberraschung dieses:
Wenn ich die Query zu einem DBGrid aktiv setze, wird das andere
DBGrid/Query in voller Menge durchgearbeitet. Es wird aktiv geschaltet
und alle Events rattern ab.

Ja, ich habe Lookup Felder. Doch wo die Nachschlage-Query auf activ
geschaltet wird, ahne ich bis jetzt noch nicht. Denn ich habe sie im OI
auf false gesetzt und schalte sie nur manuell.
Post by Joe Galinke
Post by Nicole Wagner
Post by Joe Galinke
Dein Formular verstreut Variablen in verschiedene Units? Was
bedeutet >> das?
Post by Nicole Wagner
Unit Dos-Konsolen-Rechnung;
....
Prozedure Nicht-Visuelle-Array-Iteration(DB-Info);
....
for i:=Low(DB-Info) to high(DB-Info) do
begin
MathematischeKomplexanweisung (DB[i]);
If i = 50 then
===> Form1.ProgressBar1.StepIt(5);
end;
Nicht Dein Formular verstreut Variablen, Du nutzt eine Variable die
auf dein Formular zeigt recht wild überall.
Das Beispiel sieht schlimm aus.
eben
Post by Joe Galinke
Einigermaßen elegant wäre ein Datenmodul welches die Berechnung
ausführt und ein Event OnProgress(Step: Integer) anbietet.
meine Fantasie reicht da im Augenblick nicht.
Dann spukt ja das Modul viel zu tief in meine Unit
Dos-Konsolen-Rechnung? Denn nur die weiss, wie und wovon berechnet wird.

Im Grunde will ich meine Dos-Unit sauber halten.
Post by Joe Galinke
Form1
hängt sich an das Event und handhabt Progressbar. Wie der Fortschritt
nämlich dargestellt wird, das geht die Berechnusgroutine nichts an.
eben!
Post by Joe Galinke
TMyProgressForm mitgegeben wird. Nun kann man innerhalb der Routine
ProgressForm:ProgressBar... aufrufen oder, etwas sauberer, eine
public-Methode DoProgress(Step: Integer).
TMyProgressForm.DoProgress() versorgt dann den Balken. Ich mag dabei
nicht, dass Deine Werkzeugunit nun ein spezielles Formular, bzw.
dessen Klasse, kennen muss.
mag ich auch nicht. Gar nicht.
Macht es aber extrem viel Unterschied, ob sie ein anderes Formular oder
eine anderes Modul kennen muss?
Post by Joe Galinke
Das wäre die ersten einfachen Lösungen.
Sie sind besser als meine.
Aber so richtig perfekt wird es noch nicht.
Post by Joe Galinke
Post by Nicole Wagner
Ich habe gestern schon mal probiert, statt
"FormName."
zu schreiben
"self."
"Refactor"-Variablen-umbenennen funktionierte nicht mehr.
Erst als ich voll zitierte, inkl. "FormName." wurde meine Methode
wieder korrekt in alle Zusammenhaengen umbenannt.
Das wäre für mich niemals ein Grund, FormName statt Self zu
verwenden. Wenn es mir wichtig wäre würde ich halt schauen, ob ich
auf das Self selbst verzichten könnte.
Nochmal zur Sicherheit, es handelt sich um eine Methode von FormName,
in der Du das brauchst? Zeige die Methode doch mal.
ui, die ist schon lange wieder im Speichergewirr verschwunden.
Es war dieser Aufbau:


.... // Deklaration

Var Form1: TForm1;

Procedure TForm1.MyUmzubenennende;
begin
end;

Procedure TForm1.TuWas;
begin
Form1.MyUmzubenennende; // pfui, ich weiss
end;

Fuer mich ist Refactor sehr wichtig. Oft erarbeite ich mir eine
Struktur und am Ende bemerke ich, dass im Laufe der Zeit die Namen
Flickwerk wurden. Bevor Delphi Refactor konnte, habe ich mich lange
gequaelt, bevor ich umbenannte. Und das war stets die Quelle von viel
Aerger.

Heute kann ich in Sekunden umbenennen und effizienter arbeiten, weil
ich bei konsquenter Benennung schneller mutmassen kann, was ich mir am
Vortag bei einer Sache gedacht haben koennte. ;-)


Nicole

Günter Kieninger
2011-04-01 06:15:58 UTC
Permalink
Post by Nicole Wagner
Ich vermute den Fehler gerade in der Vernetzung. Etwa, dass irgendetwas
mein onCalc-Event in eine zu lange Schleife draengt
Versuche doch mal http://www.gurock.com/smartinspect/ damit kannst du
schön beobachten welche function aufgerufen wird in welcher Reihenfolge
und wie lang sie läuft.

Gruß aus den Bergen
Günter
Nicole Wagner
2011-04-01 10:49:34 UTC
Permalink
Post by Günter Kieninger
Post by Nicole Wagner
Ich vermute den Fehler gerade in der Vernetzung. Etwa, dass
irgendetwas mein onCalc-Event in eine zu lange Schleife draengt
Versuche doch mal http://www.gurock.com/smartinspect/ damit kannst du
schön beobachten welche function aufgerufen wird in welcher
Reihenfolge und wie lang sie läuft.
Gruß aus den Bergen
Günter
Danke fuer das Link!
Wenn es kann, was ich mir erhoffe, brauche ich es wie einen Bissen Brot.


Nicole
Nicole Wagner
2011-03-30 12:18:19 UTC
Permalink
also zumindest fuer mein Formular brauche ich keine Berg-Bilder mehr.
Als ich nach meinem Refresh (noch vergeblich) suchte, fand ich DAS:

http://docwiki.embarcadero.com/RADStudio/de/Datenbankarchitektur


Nicole
Burkhard Schneider
2011-03-22 07:20:50 UTC
Permalink
Post by Nicole Wagner
Was hingegen zur "spaeteren" Laufzeit also auf Menu-Trigger veranlasst
wird, wird nicht sofort dargestellt. Ich klicke z.B. "Zeilen
ausblenden" oder "dieses fuer jenes berechnen". Ersteres soll im
Filter-Ereignis bearbeitet werden, letzteres im Calc Ereignis.
Was machst du denn nach so einer Menü-Aktion?

Es könnte helfen, einfach bei der zugrundeliegenden Query active:=false und
dann active:=true zu setzen.

Evtl. vorher den aktuellen Datensatz merken und anschließend wieder dorthin
positionieren, wie Joe schon geschrieben hat.

Gruß
Burkhard Schneider
Joe Galinke
2011-03-22 07:35:00 UTC
Permalink
Hallo Burkhard,
Post by Burkhard Schneider
Es könnte helfen, einfach bei der zugrundeliegenden Query active:=false und
dann active:=true zu setzen.
Das entspräche vom Aufwand her einem TIBDataSet.Refresh, die Query wird
erneut ausgeführt. Das kann man sich für das Ändern des Filters aber
sparen.


Gruß, Joe
--
Nicole Wagner
2011-03-26 15:26:57 UTC
Permalink
Post by Joe Galinke
Hallo Burkhard,
Post by Burkhard Schneider
Es könnte helfen, einfach bei der zugrundeliegenden Query
active:=false und dann active:=true zu setzen.
Das entspräche vom Aufwand her einem TIBDataSet.Refresh, die Query
wird erneut ausgeführt. Das kann man sich für das Ändern des Filters
aber sparen.
Gruß, Joe
[active:=false und dann active:=true]
das hatte ich schon vorm Posten probiert.
Half nicht.


Nicole
Frank Rothweiler
2011-04-01 21:59:33 UTC
Permalink
Wie dir bereits von mehreren Seiten mitgeteilt wurde, gehst du
vollkommen falsch an die Sache heran. In einem DBGrid wird nichts
berechtet, sondern lediglich angezeigt. Berechnungen erfolgen stets -
und daran sollte man sich unbedingt halten, wenn man den Überblick
bewahren möchte - vor der Anzeige im DBGrid, und zwar mit den Feldern
des jeweiligen Querys bzw. des jeweiligen Datasets, das die benötigte
Datenmenge aus der Datenbank kapselt.

Benötigst du ein berechnetes Feld, erstellst du dir einfach eines. Dazu
klickst du doppelt auf die entsprechende Query (bzw. Dataset), worauf
der Feld-Editor erscheint. Auf diesen klickst du nun mit der rechten
Maustaste und wählst den Eintrag "Neues Feld" (geht auch mit Strg-N). Im
Feld-Dialog gibst du einen Namen für das Feld ein, das den berechneten
Wert enthalten soll.

Ich habe mir angewöhnt, für Nachschlagefelder das Präfix N_ zu
verwenden, entsprechend für berechnete Felder B_ und für Datenfelder D_.
So heißt dann dein neues Feld beispielsweise B_Emailadresse.

Gehen wir einmal davon aus, du verwaltest in deiner Datenbank eine
Tabelle ADRESSEN, die eine Spalte "Emailadresse" und den Primärschlüssel
"Idx_Emailadressen" enthält. In einer anderen Tabelle PROVIDER gibt es
die Spalte "Emailprovider" mit dem Primärschlüssel "Idx_Emailprovider".
Zusammen ergibt sich dann die Emailadresse, deren "Berechnung" in dem
gerade erzeugten Feld abgelegt werden soll, und die dann vielleicht so
aussieht: ***@online.de. Berechnet werden soll also - als Beispiel
- eine vollständige Emailadresse aus den beiden Tabellen, in der eine
Spalte "Email" heißt und eine andere in derselben Tabelle "Provider"
genannt wurde, aber keine Providernamen enthält, sondern lediglich einen
Index-Wert (Integerwert). Dieser Indexwert korrespondiert mit dem
Primärschlüssel der Tabelle PROVIDER - ein eindeutiger Schlüssel, der
immer nur auf einen Provider zeigt. Um nun im neu erzeugten Feld
B_Emailadresse die Kombination aus der Spalte "Emailadresse" (Tabelle
Adressen) und der Spalte "Emailprovider" (Tabelle PROVIDER) ablegen zu
können, benötigen wir eine Procedure, die du ganz einfach erzeugst:

Du klickst das neu erzeugte Feld "B_Emailadresse" an und wählst
daraufhin im Objektinspektor unter dem Reiter Ereignisse das Ereignis
OnGetText. In das leere Feld daneben klickst du doppelt rein und
erzeugst damit eine Procedure, die z.B. heißt:

"Dataset_AdressenB_EmailadresseGettText(Sender: TObject; var Text:
string; DisplayText: Boolean);

In diese Procedure schreibst du nun deinen Code, der die beiden
Feldinhalte in einem neuen Feld zusammenführt und vergißt dabei auch
nicht das trennende @-Zeichen:

VAR
Email, Provider : STRING
Index_Provider : LONGINT;

BEGIN
Index_Provider :=
Dataset_Adresse.FieldByName('Provider').AsInteger;

IF NOT Dataset_Provider.Locate('Idx_Provider',Index_Provider,[])
THEN
BEGIN
ShowMessage('Eintrag nicht gefunden');
CLOSE; //Fehler aufgetaucht, Programm beenden
EXIT;
END;

Email := Dataset_Adresse.FieldByName('Emailadresse').AsString;
Provider := Dataset_Provider.FieldByName('Provider').AsString;
Text := Email + '@' + Provider;
DisplayText := TRUE;
END;

Du nimmst also aus der aktuellen Emailadresse den Index für den Provider
und ermittelst diesen. Dann lokalisierst du ihn in der Tabelle PROVIDER
und übergibst den gefundenen Eintrag in das neue Feld.

Damit wird dann jedesmal, wenn irgend eine Komponente diese Spalte
abruft, in das Feld "B_Emailadresse" der berechnete Wert eingetragen. In
deinem DBGrid-Spalteneditor löscht du nun das Feld "Emailadresse" und
fügst stattdessen das neu erzeugte Feld "B_Emailadresse" ein. Und auf
wundersame Weise wird dir in deinem DB_Grid der berechnete Wert angezeigt.

Alle anderen Herangehensweisen wären mehr oder weniger Unfug ... wenn du
das jetzt nicht begreifst, dann weiß ich auch nicht mehr ...
Nicole Wagner
2011-04-04 11:05:08 UTC
Permalink
Frank Rothweiler wrote:


[]

danke fuer die genauen Anweisungen!
Werde sie mir dann mal ausdrucken sie Punkt fuer Punkt durchgehen.

Es ist alles soo komplex.
Ich ziehe bei einem Thema an und finde 10 unbekannte neue Teile der
Komponenten. 10 weitere finde ich nicht (selbst).

Meine DBGrids und auch deren berechneten Felder funktionieren im Grunde
schon recht ordentlich. Alle einzeln.
Die Interaktion der Komponenten will noch nicht.
Meine Anwendung sieht aus wie ein zusammengenagelter Formel 1 Bolide.
"fahren" wuerde er. Leider von Fussgaengern ueberholt.


Nicole
Loading...