Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Einer query zusätzliche Felder hinzufügen und als CheckBox editieren (https://www.delphipraxis.net/163954-einer-query-zusaetzliche-felder-hinzufuegen-und-als-checkbox-editieren.html)

baurat 23. Okt 2011 16:02

Datenbank: MySQL • Version: 5.1 • Zugriff über: Zeos

Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Hallo zusammen,
ich krame gerade meine alten Delphikenntnisse aus, um eine Absenzenverwaltung für unsere Schule zu basteln.

Was ich brauche: ich hole aus einer Query die Namen der Schüler eines Kurses (sch_id, sch_name).
Die Namen sollen in einem DBGrid angezeigt werden, allerdings möchte ich daneben noch eine (bzw. merhere) Spalte mit einer Checkbox haben - die wird angeklickt, wenn ein Schüler zu einem bestimmten Termin gefehlt hat - dh. diese Information kommen nicht aus einer Query, sondern werden beliebig editiert und dann am einfachsten am Ende mit einem "alles speichern" Zeile für Zeile ausgelesen und dann weiterverarbeitet (für alle angeklickten wird eine Absenz gespeichert). Je nach Fall sollen es mehrere unabhängige Spalten werden, die man anklicken kann (gefehlt_Tag1, gefehlt_Tag2 etc).

Was ich bislang probiert habe: (Mysql 5, Zeos, Delphi 6 prof)
- zusätzliche Felder direkt per mysql generieren:
select sch_id, sch_name, false as gefehlt from schueler...
- oder zusätzliche Felder über die Query hinzufügen (als int oder boolean,beides probiert)
- zum Anzeigen habe ich das SMDBGrid mit dem "vorgefertigten" Checkbox-Editor versucht - der zeigt zwar Checkboxen richtig an, wenn die Daten aus einer query kommen, man kann aber keine Werte ändern (obwohl natürlich query, query.felder, grid und grid.spalten auf readonly = false gesetzt sind)
- und das JvDBUltimateGrid aus den Jedi-Komponenten, das hat ja auch die Eigenschaft "boolean editor".. damit kann ich zwar ne checkbox setzen, die aber beim Verlassen des Felds wieder unchecked wird.

Ich bin gerade wirklich am Verzweifeln. Lasse ich mir die Felder als stinknormale integer anzeigen, kann ich Werte ändern. Die gleichen Daten an einem SMDBGrid angehängt, ändert das SMDBGrid dann auch schön artig die Checkboxen - aber eben ein direktes Anklicken der Boxen im SMDBGrid funzt nicht.

Hat jemand vielleicht einen Tipp, wie ich das lösen kann?

Vielen Dank für eure Hilfe!
LG.. Heiko

Bummi 23. Okt 2011 16:11

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Berechnete Felder sind ja readonly, bei manchen Datasets kann man das überschreiben oder direkt berechnete Felder einfügen, deren Schreibschutz man entfernt, auf Feld.SetText kann entsprechend reagiert werden.
Der einfachere Ansatz wäre die Daten in ein Clientdataset zu kopieren, dem die benötigten Spalten bereits hinzugefügt wurden und dieses für die Darstellung zu verwenden.

Ich hatte etwas derartiges mal gekapselt ....

Delphi-Quellcode:
  type
    TMyFieldDef=Record
      Name:String;
      Size:Integer;
      DataType:TFieldType;
    end;
    TFieldDefArray = array of TMyFieldDef;
Delphi-Quellcode:
function   GetClientDSForDS (ADataSet: TDataSet; AFieldDefArray: TFieldDefArray; AClientDataSet: TClientDataSet=nil): TClientDataSet;
var
i: integer;
  Function NoAutoInc(ft:TFieldType):TFieldType;
   begin
     if ft=ftAutoInc then Result := ftInteger else Result := ft;
   end;
begin

  if Assigned(AClientDataSet) then
    Result := AClientDataSet
  else
    result := TClientDataSet.Create(nil);
  Result.Close;
  Result.FieldDefs.Clear;

  for I := 0 to ADataSet.FieldCount-1 do
  begin
    Result.FieldDefs.Add(ADataSet.Fields[I].FieldName, NoAutoInc(ADataSet.Fields[I].DataType), ADataSet.Fields[I].Size);
  end;


  for I := 0 to High(AFieldDefArray)do
    result.FieldDefs.Add(AFieldDefArray[I].Name, AFieldDefArray[I].DataType, AFieldDefArray[I].Size);

  Result.CreateDataSet;
  ADataSet.First;
  while not ADataSet.Eof do
  begin
    Result.Append;
    for I := 0 to ADataSet.FieldCount-1 do
    begin
      result.FieldByName(ADataSet.Fields[I].FieldName).Assign(Adataset.Fields[i]);
    end;
    Result.Post;
    ADataSet.Next;
  end;
end;

sx2008 23. Okt 2011 16:13

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Verwende eine Memory-Table mit allen Feldern die du benötigst.
Dann kopiere die Datensätze aus deiner Query (sch_id, sch_name) in die Memory-Table.
Die zusätzlichen Felder bleiben leer (NULL) oder können mit einem Defaultwert belegt werden.
Damit sind dann alle Daten im Speicher und können beliebig editiert werden.

In der JVCL gibt es z.B. in Unit JvMemoryDataset die Klasse TJvMemoryData.

baurat 24. Okt 2011 19:05

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Hallo,
vielen Dank für eure schnellen Antworten, die beide - so wie ich das sehe - in die gleiche Richtung gehen. Der Fehler liegt also darin, dass die Datenmenge aus der Query nicht editierbar ist und deswegen die geänderten Checkboxen ihre Werte nicht zurückschreiben können. Richtig?

Beide Ideen finde ich genial, werd ich jetzt gleich mal ausprobieren!

LG.. Heiko

baurat 24. Okt 2011 21:39

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
..Ernüchterung :(

1) @SX2008: JvMemoryTable... Sollte doch eigenltich nicht so schwer sein. Ich gebe als Dataset meine Datenquery an und nutze "Borrow Structure", um die Struktur zu importieren - damit hab ich alle Felder in der memTable. Interessanterweise sind manche auf readonly = true gesetzt, manche nicht, ebenso manche mit required= true bzw. false.
Wenn ich aber die Daten holen will (egal ob in der IDE oder per LoadFromDataSet(meineSQLQuery, meineSQLQuery.RecordCount, lmCopy, true)), passiert... immer wieder ein Fehler "Feld_xxx darf nicht leer sein!". In meineSQLQuery steht was drin, daran liegts nicht. Seltsam.

Wie bekommst du die Daten in die memTable?

2) @ Bummi: Ich muss gestehen: meine aktive Delphi-Zeit ist lange her. Bin mir deswegen nicht ganz sicher ob ich deine Zeilen richtig eingebaut hab.
In meinem main-form steht jetzt also ganz oben gleich nach der uses-Klauses die Type-Def. für TMyFieldDef. In die Public-Deklaration von Tf_main hab ich dann die Signatur der GetClientDSForDS Methode rein, den Quelltext dann natürlich in die Implementation.

Das wird compiliert, nur... wie wende ich es an?
Ich muss mir ja erst dieses Definitionen-Array basteln. Hast du da evtl. noch nen Code-Schnipsel?
Ich brauch ja einfach nur drei Felder: schuelerid (ftInteger), kursid (ftInteger), schuelername (ftString). Die Daten hierfür liegen in meineSQLQuery. Die Methode liefert mir theoretisch die Daten aus meineSQLQuery in einem clientDataSet zurück. Aber leider krachts auch hier - genau der gleiche Fehler wie oben!?!?!

Sobald ich die MemoryTable auf active=true setze bzw. GetClientDSForDS aufrufe, stolpert er und sagt "Feldxxx darf nicht leer sein" - das ist das erste Feld von meineSQLQuery.

Irgendwelche Ideen...?

Mannmannmann warum muss das alles so schwer sein... ;)

Bummi 24. Okt 2011 22:03

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Ich hätte es nicht in die Klasse eingebaut, sondern gegf. in eine Tools-Unit.
Das mit dem Recordarray ist nicht kompliziert
Delphi-Quellcode:
var
  RA:TFieldDefArray;
begin
SetLength(RA,2);
RA[0].Name := 'Feldx';
RA[0].Datatype := ftString;
RA[0].Size := 20;

RA[1].Name := 'Feldy';
RA[1].Datatype := ftboolean;
RA[1].Size := 0;


//Wenn Du nichts einfügen willst
SetLength(RA,0);
Wenn Du die Felder per SQL schon drin hast kannst Du ein leeres FieldDefArray mitgeben.

Der Fehler "Feldxxx darf nicht leer sein" scheint schon beim alleinigen lesenden Zugriff auf den Dataset aufzutreten das Clientdataset hat ja keine derartigen Einschränkungen zugewiesen bekommen, mit Zeos und MySQL bin ich allerdings nicht bewandert ...

baurat 27. Okt 2011 19:15

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Tataaaa!

Dank Bummis Hilfe hab ich's mit seiner Möglichkeit über ein ClientDataSet hinbekommen.
Hatte ja eh eine Tools-Unit, da war das gut aufgehoben (uses-Klausel anpassen wg. DataSet).

Da ich MySQL verwende muss ich die boolean-Felder manuell hinzufügen (mysql ersetzt boolean durch tinyint, dann klappt das mit dem SMDB-Grid nicht automatisch mit den Checkboxen).

Kleines Kosmetikproblem: ich bekomme aus meiner Query noch einige andere Felder, für die "Absenzeingabe" will ich aber nur den Namen + die Checkboxfelder anzeigen, deswegen muss ich zur Laufzeit alle anderen unsichtbar setzen (schöner wärs die Eigenschaften alle schon zur Entwurfszeit festlegen zu können). Aber egal, alles kein großes Problem jetzt!

Nochmals vielen Dank für eure Hilfe, Problem gelöst :))

baurat 27. Okt 2011 21:42

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Kleine Nachfrage: weiß jemand, wie ich alle Felder einer Spalte bearbeiten kann?

Hintergrund: ein Kurs findet normalerweise z.B. 4mal pro Woche statt, dh. ich erzeuge 4 Checkbox-Spalten. Es kann aber z.B. sind dass es in der aktuellen Woche nur 2 Termine gibt - da ich auch "Fehlanzeige" speichern möchte, darf ich also nicht blind durch alle Spalten gehen, sondern muss es ermöglichen, dass man z.B. Spalte 3 und 4 disabled.

Bearbeiten kann ich mit column.readonly := true blocken, das geht locker.
Aber nun möcht ich noch, dass alle evtl gesetzen Haken dieser Spalte wieder gelöscht (dh. auf feld.asboolean := false und zudem idealerweise die ganze Spalte angegraut wird. Das könnte schön über OnTitleClick erfolgen, dachte ich.

Also in der Art:
Delphi-Quellcode:
procedure TmeinForm.smdb_KursabsenzenTitleClick(Column: TColumn);
  if Column.ReadOnly = false then begin
    //UncheckAll(smdb_Kursabsenzen, Column); <- Versuch, klappt aber nicht
    Column.ReadOnly := true;
    Column.Color := clblue;
  end else begin
    Column.ReadOnly := false;
    Column.Color := clwhite;
  end;
Leider klappt auch das Setzen der Farben nicht.

Hat jemand dazu vielleicht nen Hinweis...?

Danke!


Ich w

baurat 28. Okt 2011 23:53

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Kommando leider doch nochmal zurück. An sich klappt alles, nur werden offenbar alle integer-Felder nicht kopiert - lass ich mir den Inhalt des originalen DataSets anzeigen, stehen die schuerlerids schön als int drin. Nach dem Kopieren in das ClientDataSet sind alle Spalten identisch, nur die int-Werte der schuelerids sind jetzt leer!

Ist leider doof, ich brauch die Schülerids natürlich, um die Fehlzeiten zuordnen zu können :(

Bummi, hast du eine Idee woran das liegen könnte?

Etwas verzweifelnde Grüße
Heiko

Bummi 29. Okt 2011 09:33

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Mhhh, nicht auf Anhieb, hast Du mal debugt nach TFieldType des Feldes ....

baurat 29. Okt 2011 21:26

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Zitat:

Zitat von Bummi (Beitrag 1133335)
Mhhh, nicht auf Anhieb, hast Du mal debugt nach TFieldType des Feldes ....

In die Richtung hab ich auch schon überlegt. Das Feld schuelerid hat ja auch schon vorher beim "Import" in die MemTable für Probleme gesort, das hat sicher die gleiche Ursache.
Dachte vielleicht, dass das an einem Spezialfeldtyp von den Zeos-Komponenten liegt, dass die da irgendwas tricksen was nicht Standard ist - dem ist aber leider nicht so, die persistenten Felder in der mysql-Query sind alle die Felder aus der DB-Unit (schuelerid ist TLargeIntField).

Debuggen: Hm. In der NoAutoInc wird schuelerid as ftLargeInt richtigerweise erkannt. Warum klappts nicht? Wenn ich in NoAutoInc ftLargeInt als ftInteger erzeuge, funktionierts!?!?

Verstehe ich nicht :(

Naja, mal sehen obs noch weitere Schwierigkeiten damit gibt...
Auf jeden Fall nochmal Danke!

Bummi 29. Okt 2011 21:59

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
hast Du eine ältere Delphiversion?
http://www.distribucon.com/blog/Comm...,guid,220.aspx

baurat 30. Okt 2011 12:20

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Ahhhhh, das sieht doch stark nach einer Ursache aus. Ja, ich hab noch D6 prof.

Offenbar ist die "neue" midas.dll abwärtskompatibel bis D5 (http://www.distribucon.com/midas.aspx) , deswegen hab ich sie mal runtergeladen.

Jetzt hab ich sie mal spaßeshalber in c:\windows\syswow64 für die alte ersetzt, aber das ändert offenbar nichts, gleicher Fehler. Die midas.dll wird im laufenden Projekt eingebunden (Ansicht - Debug - Module). Aber ohne den Zusatz
if (ft = ftLargeint) then Result := ftInteger
in NoAutoInc bleiben die schuelerids leer.


Naja immerhin läufts so, ist zwar seltsam aber damit werd ich wohl leben (müssen).

Trotzdem Danke!

Lg Heiko

Sir Rufo 30. Okt 2011 13:19

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Ich denke dafür würde ich mir eine temporäre Tabelle auf dem MySQL erzeugen und diese dann im DBGrid anzeigen lassen.

Dabei kann man auch berücksichtigen, dass man eben nur x Spalten benötigt (das CREATE TEMPORARY TABLE-Statement muss man halt anpassen).

Wenn die Eingabe abgeschlossen ist, dann trägt man einfach (geht z.B. auch mit einer StoredProcedure) die Werte aus der temporären Tabelle in die echte Tabelle ein.

Das sollte auch unabhängig von der verwendeten Delphi-Version möglich sein, da wir aus der Client-Sicht eine echte komplett beschreibbare Tabelle vor uns haben ;)

Ach ja, man darf natürlich die Feldliste nicht schon zur Design-Time komplett zuweisen, da wir ja eine dynamische Feldliste haben ;)

baurat 1. Nov 2011 23:31

AW: Einer query zusätzliche Felder hinzufügen und als CheckBox editieren
 
Zitat:

Zitat von Sir Rufo (Beitrag 1133558)
Ich denke dafür würde ich mir eine temporäre Tabelle auf dem MySQL erzeugen und diese dann im DBGrid anzeigen lassen.

Dabei kann man auch berücksichtigen, dass man eben nur x Spalten benötigt (das CREATE TEMPORARY TABLE-Statement muss man halt anpassen).

Wenn die Eingabe abgeschlossen ist, dann trägt man einfach (geht z.B. auch mit einer StoredProcedure) die Werte aus der temporären Tabelle in die echte Tabelle ein.

Das sollte auch unabhängig von der verwendeten Delphi-Version möglich sein, da wir aus der Client-Sicht eine echte komplett beschreibbare Tabelle vor uns haben ;)

Ach ja, man darf natürlich die Feldliste nicht schon zur Design-Time komplett zuweisen, da wir ja eine dynamische Feldliste haben ;)

... ja, im Prinzip läufts auf das gleiche hinaus. Hatte an eine UDF schon mal gedacht, denn es geht ja noch weiter: ich hab jetzt eine Liste mit Namen und IDs und sagen wir mal 4 Spalten zum Anklicken der Anwesenheit. Jetzt muss ich aber noch für *jedes* Feld ne extra Query an die DB schicken, ob für diesen Termin schon eine Entschuldigung vorliegt. DAs macht bei sagen wir mal 20 Schülern mal schnell 80 Anfragen, die übers Netz gehen. Die DB liegt irgendwo bei 1&1, ich hoffe dass das performancemäßig halbwegs hinhaut. Aber genau deswegen dachte ich schon an ne UDF, die das in einem Aufwasch serverseitig erledigt und mir dann nur eine Ergebnismenge liefert, anstelle 80 hin- und herzutelefonieren.

Nur sind UDF dann halt das nächste Thema, mit dem ich noch nie zu tun hatte. Ideal wäre sowas wie
select getAbsenzenliste(kursid, termin1, termin2, ...., terminx)
wobei termin1 bis terminx einfache zeitstempel sind.
Die UDF holt dann erst mal alle kursmitglieder des kurses und prüft dann für jeden jeden Termin durch. Tja, im Kopf hätt ich's schon...

Na mal sehen, aktuell klappts mit dein Einzelqueries schon mal ganz gut, das Netz darf halt nicht klemmen...


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:26 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz