Discussion:
Dynamisch erzeugtes ClientDataSet und berechnete Felder
(zu alt für eine Antwort)
Stephan Jaschke
2004-02-08 00:29:27 UTC
Permalink
Hallo all zusammen.

Ich hab da nen Problem ;-)

In einer Bibliotheksunit erzeuge ich ein Singleton, das Daten aus
einer Tabelle u.a. für Lookup-Comboboxen zur Verfügung stellt.
Problem ist, das ein Tabellenfeld einen mehrezeilige Text zulässt und
als ListField angezeigt werden soll.
Also hab ich mir gedacht ich erzeuge dynamisch ein berechnetes Feld
in der Datenmenge und packe da den umformatierten Text rein (als eine
Zeile).
Erzeuge ich das berechnete Feld in BeforeOpen, werden die Felder aus
der Abfrage nicht automatisch erzeugt.
Aber ehrlichgesagt würde ich die Felder gerne automatisch erzeugt
haben, damit ich da nicht ran muss, wenn die Struktur geändert wird
(Die Klasse stellt noch andre Funktionalitäten zur Verfügung).
Im AfterOpen sind die Felder da, aber ich kann keins mehr dazubasteln
:-(

Irgendwelche Ideen wie man das lösen könnte?

Ratlos.
Stephan
Marian Aldenhoevel
2004-02-08 14:14:59 UTC
Permalink
Hi,
Post by Stephan Jaschke
Erzeuge ich das berechnete Feld in BeforeOpen, werden die Felder aus
der Abfrage nicht automatisch erzeugt.
Kurze Antwort: Verwende OnAfterOpen.

Lange Antwort:

Das Problem besteht darin, daß es zwei einander leider ausschließende
Wege gibt, auf denen eine Datenmenge zu ihren Felddefinitionen kommen
kann.

Der erste besteht darin, daß die Datenmenge geöffnet wird und
automatisch entsprechende Feldkomponenten erzeugt. So kommt zum
Beispiel eine Abfrage deren Feldliste nicht schon zur Designzeit
feststeht zu ihren Feldern.

Der zweite Weg sind die sogenannten "persistenten Felder", so getauft,
weil sie dafür gedacht sind schon zur Designzeit angelegt und
konfiguriert zu werden. Die so schon vor dem Öffnen der Datenmenge
vorhandenen Feldkomponenten werden dann sozusagen nur noch an die
tatsächlichen Felder gebunden.

Leider schließt das Vorhandensein eines einzigen Feldes beim Öffnen
die automatische Erzeugung aller anderen Felder aus.
Post by Stephan Jaschke
Aber ehrlichgesagt würde ich die Felder gerne automatisch erzeugt
haben, damit ich da nicht ran muss, wenn die Struktur geändert wird
Du hast zwei Möglichkeiten. Erstens kannst Du zusätzlich zu Deinem
berechneten Feld die anderen Felder auch in Code anlegen. Wunschweise
mit den ebenfalls richtigen zur aktuellen Datenstruktur passenden
Namen, Typen und Größen.

Zweitens, und das ist hier wohl die Methode der Wahl, kannst Du _nach_
der automatischen Anlage der physisch vorhandenen Felder auch noch
neue anhängen. Und dafür bietet sich OnAfterOpen an.

Ciao, MM
--
Rosenhain 23, 53123 Bonn - Fon +49 228 6203366, Fax +49 228 624031
www.marian-aldenhoevel.de
"Time is natures way to make sure everything does not happen at once"
Stephan Jaschke
2004-02-08 14:51:24 UTC
Permalink
Marian Aldenhoevel schrieb:
...
Post by Marian Aldenhoevel
Zweitens, und das ist hier wohl die Methode der Wahl, kannst Du
_nach_ der automatischen Anlage der physisch vorhandenen Felder
auch noch neue anhängen. Und dafür bietet sich OnAfterOpen an.
Danke für die Antwort.

Aber leider ist OnAfterOpen keine Alternative, weil ich zu diesem
Zeitpunkt bereits eine geöffnete Datenmenge habe. Und mein Delphi
weigert sich einfach zu einer geöffneten Datenmenge ein Feld
hinzuzufügen. (Kurz: Es gibt ne Exception sobald ich Dataset des
Feldes zuweise.)

Vermutlich bleibt mir nichts anderes übrig als Variante 1 zu
verwenden und alle benötigten Felder ebenfalls dynamisch zu
erstellen. Das wird allerdings eine "Support-Hell" :-((

MfG
Stephan
Marian Aldenhoevel
2004-02-08 15:50:10 UTC
Permalink
Hi,
Post by Stephan Jaschke
Aber leider ist OnAfterOpen keine Alternative, weil ich zu diesem
Zeitpunkt bereits eine geöffnete Datenmenge habe. Und mein Delphi
weigert sich einfach zu einer geöffneten Datenmenge ein Feld
hinzuzufügen. (Kurz: Es gibt ne Exception sobald ich Dataset des
Feldes zuweise.)
Ich habe eben nochmal nachgesehen, wie ich das gemacht hatte, und
ich habe tatsächlich auch nicht OnAfterOpen genommen. Und dann habe
ich mich mit FieldDefs.Update und dem selbstbauen aller physischen
Felder beholfen:

procedure TfmMGMReporting.CreatePersistentFields(aDataSet:TDataSet);
var i:integer;
Field:TField;
begin
if not Assigned(aDataSet) then Exit;

aDataSet.Close;
aDataSet.FieldDefs.Update;

{ Persistente Felder zur Laufzeit erzeugen, das damit wir dann berechnete
Felder hinzufügen können }
for i:=0 to aDataSet.FieldDefs.Count-1 do
begin
Field:=aDataSet.FieldDefs[i].CreateField(aDataSet);
Field.DataSet:=aDataSet;
end;
end;

function
TfmMGMReporting.CreateCalculatedField(aDataSet:TDataSet;aFieldClass:TFieldClass;aFieldName:String):TField;
begin
if not Assigned(aDataSet) then
begin
Result:=NIL;
Exit;
end;

aDataSet.Close;
if (aDataSet.FieldCount=0) then CreatePersistentFields(aDataSet);

Result:=aFieldClass.Create(aDataSet);
with Result do
begin
FieldKind:=fkCalculated;
FieldName:=aFieldName;
DataSet:= aDataSet;
end;
end;

Ciao, MM
--
Rosenhain 23, 53123 Bonn - Fon +49 228 6203366, Fax +49 228 624031
www.marian-aldenhoevel.de
"Time is natures way to make sure everything does not happen at once"
Stephan Jaschke
2004-02-08 18:14:34 UTC
Permalink
Marian Aldenhoevel schrieb:
...
Post by Marian Aldenhoevel
Ich habe eben nochmal nachgesehen, wie ich das gemacht hatte,
und ich habe tatsächlich auch nicht OnAfterOpen genommen. Und
dann habe ich mich mit FieldDefs.Update und dem selbstbauen
[code]

Danke Marian.
Der entscheidende Tip war die Geschichte mit FieldDefs und
FieldDefs.Update. Das ganze am besten nach dem Create oder im
BeforeOpen und ggfs. noch Updated vorher auf False setzen, damit die
Defininitionen neu gebaut werden. Alles klar.

Feine Sache. So geht's.

Stephan

--

Lesen Sie weiter auf narkive:
Loading...