Announcement

Collapse
No announcement yet.

Formatieren der Ausgaben einer Query-Abfrage

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Formatieren der Ausgaben einer Query-Abfrage

    Hallo,

    weiß jemand eine Möglichkeit die Ausgabe von TQuery-Ergebnissen im Titel und im Dateninhalt (Kommastellen) zu formatieren ?

    Der as Operator für Titel-Umbenennung funktioniert hier nicht.

    SELECT FeldA,FeldB,FeldC from TabTest

    Die Ausgabe dieser Query wird in einem DBGrid dargestellt.<br>
    Alle Titeln werden in Gross-Schrift und genauso wie in der Tabelle dargestellt. Die Zahlen sind unformatiert und daher unschön.

    Im Grid selbst kann ich ja keine persistenten Felder anlegen.

    Übrigens, die Query ist neutral und dient zur Darstellung unterschiedlichster Tabellen, daher sind hier persistente Felder nicht möglich.

    Gruss<br>Helmut

  • #2
    Hallo,

    in diesem Fall ist Fleißarbeit angesagt, indem zur Laufzeit: <br>
    a) für jede Spalte der Datentyp ermittelt wird, <br>
    b) für jede Spalte zur Laufzeit eine TField-Instanz erzeugt wird, und<br>
    c) je nach vorgefundenem Datentyp der TField-Instanz ein Standard-Format zugewiesen wird

    Comment


    • #3
      Vielen Dank Herr Kosch!

      Ich habe so etwas noch nie gemacht und keine Ahnung wie ich zu den Daten komme.

      Hätten Sie zufällig ein Beispiel zu obiger Query ?

      Gruss<br>Helmu

      Comment


      • #4
        Noch nicht ;-

        Comment


        • #5
          Sehr geehrter Herr Kosch!

          Fall Sie Zeit finden, wäre es schön, wenn Sie mir dabei helfen könnten.

          Gruss<br>Helmu

          Comment


          • #6
            Hallo,

            das Problem bei TQuery ist, dass im Gegensatz zu TTable die TFields beim Öffnen wieder gelöscht werden. Man muss also einen Streaming-Mechanismus nachrüsten, der das "Laden aus der DFM" simuliert. Ich werden frühestens am Wochenende dazu kommen

            Comment


            • #7
              Danke vorab

              Comment


              • #8
                Hallo,

                es ging doch einfacher als zuerst vermutet, wenn die TQuery-Instanz vorher einmal kurz geöffnet wird ;-)
                <pre>
                procedure TForm1.ButtonTQueryFieldsClick(Sender: TObject);
                var
                i : Integer;
                aField : TField;
                begin
                aField := nil;
                with Query1 do
                begin
                SQL.Add('SELECT * FROM Customer');
                // Datenmenge kurzzeitig aktivieren
                DisableControls;
                Active := True;
                Active := False;
                EnableControls;
                // Feldinfos auslesen + TField-Instanzen erzeugen/konfigurieren
                for i := 0 to (FieldDefs.Count - 1) do
                begin
                case FieldDefs.Items[i].DataType of
                ftString : aField := TStringField.Create(Owner);
                ftFloat : aField := TFloatField.Create(Owner);
                ftDateTime : aField := TDateTimeField.Create(Owner);
                end;
                with aField do
                begin
                FieldName := FieldDefs.Items[i].DisplayName;
                DisplayLabel := '»' + FieldName + '«';
                Name := 'Query1' + FieldName;
                DataSet := Query1;
                Index := FieldCount;
                if (aField is TStringField) then
                Size := FieldDefs.Items[i].Size;
                end;
                FieldDefs.Update;
                end;
                Open;
                end;
                end;
                </pre&gt

                Comment


                • #9
                  VIELEN DANK Herr KOSCH!!

                  Als kleine Kompensation habe ich alle Ihre Bücher bestellt.

                  Gruss<br>Helmu

                  Comment


                  • #10
                    :-

                    Comment


                    • #11
                      Hallo,

                      alles funktioniert. Jetzt fehlt mir nur noch eine Möglichkeit, ein Zahlenfeld zu formatieren, z.B. '###,##0.00' o.a.

                      Leider gibt es kein Feld wie Display- oder Editformat.

                      Auf welchem Weg könnte man eine Formatierung erreichen ?

                      Gruss<br>Helmu

                      Comment


                      • #12
                        Hallo,

                        selbstverständlich kann die TField-Eigenschaft <b>DisplayFormat</b> dazu genutzt werden, um bei Float-Feldern zum Beispiel über die Format-Anweisung <b>#0.00</b> die Darstellung mit 2 Nachkommastellen zu erzwingen. Damit der Compiler kein Veto einlegt, ist nach der IS-Prüfung auf TFloatField eine explizite Typumwandlung notwendig:
                        <pre>
                        procedure TForm1.ButtonTQueryFieldsClick(Sender: TObject);
                        var
                        i : Integer;
                        aField : TField;
                        begin
                        aField := nil;
                        with Query1 do
                        begin
                        SQL.Add('SELECT * FROM Customer');
                        DisableControls;
                        Active := True;
                        Active := False;
                        EnableControls;
                        for i := 0 to (FieldDefs.Count - 1) do
                        begin
                        case FieldDefs.Items[i].DataType of
                        ftString : aField := TStringField.Create(Owner);
                        ftFloat : aField := TFloatField.Create(Owner);
                        ftDateTime : aField := TDateTimeField.Create(Owner);
                        end;
                        with aField do
                        begin
                        FieldName := FieldDefs.Items[i].DisplayName;
                        DisplayLabel := '»' + FieldName + '«';
                        Name := 'Query1' + FieldName;
                        DataSet := Query1;
                        Index := FieldCount;
                        if (aField is TStringField) then
                        Size := FieldDefs.Items[i].Size;
                        if (aField is TFloatField) then
                        TFloatField(aField).DisplayFormat := '#0.00';
                        end;
                        FieldDefs.Update;
                        end;
                        Open;
                        end;
                        end;
                        </pre>
                        Der wichtige Teil verbirgt sich dabei hinter "... if (aField <b>is TFloatField</b>) then <b>TFloatField(</b>aField<b>).DisplayFormat</b> := '#0.00'. Auf diesem Weg kann man alles das machen, was auch beim Anlegen von persistenten TField-Instanzen über den Objektinspektor konfigurierbar ist.

                        &#10

                        Comment


                        • #13
                          Hallo,

                          danke Hr.Kosch für Ihre laufenden Bemühungen. Auf die Idee der Typumwandlung wäre ich nicht gekommen, obwohl ich vielfältigste Experimente angestellt habe.

                          Ich glaube, ich habe jetzt nur mehr folgendes Problem zu lösen.

                          Die betreffende Query (deren Ausgabe formatiert wird), kann im Programm je nach Anwenderreaktion mehrfach hintereinander aufgerufen werden.

                          Der erste Aufruf ist OK. Ab dem zweiten Aufruf erhalte ich 2 Fehlermeldungen "Eine Komponente mit der Bezeichnung Query1xxxx existiert bereits", danach die Fehlermeldung "Query1: Doppelter Feldname 'xxxx'"

                          Ich dachte mir schon, wann werden die TField-Komponenten wieder freigegeben, welche per .Create gebildet wurden ?

                          Ist es möglich, sofort nach dem Aufbau der Query, inklusive der formatierten Darstellung im GRID, die TField-Instanzen freizugeben (ohne daß die Darstellung im Grid beeinflußt wird, dieses bleibt am Bildschirm zur Anzeige stehen) ?

                          Wie merke ich mir, welche Instanzen freizugeben sind ?
                          <br><br><br>
                          Ich möchte Sie gleich zu einem <b>anderen Problem</b> fragen, welches ich seit einigen Tagen habe.

                          Es werden in einer Prozedur, z.B. 5 verschiedene Formulare per "FormName := TFormName.Create(Application);" gebildet.

                          Application deshalb weil ich mich in keiner Klasse befinde, deren self-Operator ich verwenden könnte.

                          Danach werden dieselben Formulare in umgekehrter Reihenfolge mittels FreeAndNil(FormName) wieder freigegeben. Bei der Freigabe des letzten Formulares erhalte ich die Fehlermeldung<br>
                          <b>Zugriffsverletzung</b> bei Adresse 048887503. Schreiben von Adresse 00000001. Prozeß wurde angehalten.

                          Der Debugger zeigt, daß in der Prozedur <b>FreeAndNil</b> der Pointer mit TObject(Obj) := nil; noch korrekt auf nil gesetzt wird, beim anschließenden P.Free tritt dann der (reproduzierbare) Fehler auf.

                          Ich bin mir keiner Schuld bewußt, umso mehr ich diese Praktik seit langem anwende. Kann es an der Menge der Formulare liegen ? Es betrifft jeweils nur dieses eine Formular, welches als erstes gebildet wird. Zum Zeitpunkt der Freigabe, befinde ich mich nicht mehr im Formular.

                          Gruss<br>Helmu

                          Comment


                          • #14
                            Hallo,

                            zum 1. Problem: <br>
                            Hier ist es am einfachsten, die TQuery-Instanz erst zur Laufzeit dynamisch zu erzeugen und am Ende (Benutzer schliesst die Darstellung/Datenmenge) wieder zu zerstören. Die TFields werden dann von der VCL automatisch abgeräumt. Ansonsten müsste man über die FieldDefs-Methode <b>Clear</b> nach dem Schliessen der angezeigten Datenmenge von Hand abräumen.

                            zum 2.Problem <br>
                            Wird ein Formular in mehreren Instanzen erzeugt? Wenn ja, darf "FormName" als Referenzvariable auf diese Formularinstanz nur beim ersten (!) Aufruf verwendet werden, alle anderen Instanzen benötigen eine <b>eigene</b> Referenzvariable. <br>
                            Alternativ kann man diese sogar einsparen:
                            <pre>
                            ...
                            with TFormName.Create(Application) do
                            begin
                            ...
                            end;
                            ...
                            </pre&gt

                            Comment


                            • #15
                              Hallo,

                              danke für den Tip 1.

                              Ich kann damit nach dem Beenden alle Instanzen abräumen.

                              Es stellt sich jedoch noch das Problem, daß das betreffende Ausgabegrid eine Zeit lang für den Anwender sichtbar ist.

                              Je nach Befehlen des Anwenders wird dieses mehrfach aktualisiert (jeweils Aufruf der Query).

                              Ich könnte das Zwischendurch-Problem "Instanz schon vorhanden" umgehen, indem ich vor dem Create von afield abfrage ob eine Instanz mit diesem Feldnamen schon existiert.

                              Wie müßte diese Abfrage lauten ?
                              <br><br><br>

                              Zu 2:

                              Jedes Formular hat seinen eigenen Namen und Instanz (wird jeweils nur einmal verwendet), z.B.

                              FormA := TFormA.Create(Application);<br>
                              FormB := TFormB.Create(Application);<br>
                              FormC := TFormC.Create(Application);<br>
                              FormD := TFormD.Create(Application);<br>
                              FormE := TFormE.Create(Application);<br>

                              ....

                              FreeAndNil( FormE );<br>
                              FreeAndNil( FormD );<br>
                              FreeAndNil( FormC );<br>
                              FreeAndNil( FormB );<br>
                              FreeAndNil( FormA ); // Hier erfolgt die Fehlermeldung

                              Das erstaunliche daran ist, daß ich diese Variante mit 4 Forms schon lange verwendet habe. Ich kann jetzt nicht genau lokalisieren, wann der Fehler zum erstenmal auftrat. Erst beim 5.Form ?

                              Vielen Dank nochmals!

                              Helmut
                              &#10

                              Comment

                              Working...
                              X