dbGrid MIN/MAX Wert Zelle farblich markieren oder Font Color



  • @all

    MAX=ermittelter Max-Wert
    MIN=ermittelter Min-Wert

    if( ADOTable1->FieldByName("W1")->Value == Max || ADOTable1->FieldByName("W1")->Value == Min)
     {
      DBGrid1->Canvas->Brush->Color = clRed;
      DBGrid1->Canvas->FillRect(Rect);
      DBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);
     }
    

    Leider färbt er alle weiteren Felder auch ein und nach dem aktualisieren ist alles wieder weg.

    Das ganze soll bei Änderungen von Werten erfolgen und auch bleiben pro Zeile.
    Also ich gebe Werte ein, ermittle den MAX/MIN Wert und diese Zellen sollen farblich hinterlegt werden, dann nächste Zeile wieder von vorn ...

    Thx@all



  • was meinst du mit "färbt er alle weiteren Felder auch"? die ganze Zeile, die ganze Spalte oder die ganze Tabelle?

    bei deinem Quellcode färbt er mir immer die ganze Zeile ein wo Min oder Max sind

    wann führst du den Quellcode denn aus?



  • @Linnea

    Also wenn ich alle Werte eingegeben habe (7) dann ermittle ich den MAX/MIN Wert, errechne die Summe und trage das Ergebis in die nächste Spalte ein.
    Das mach ich bei DBMemo7Exit()

    Die Farbänderung hab ich im DBGrid1DrawColumnCell Event stehen.
    Zuerst macht er allerdings die Spalte(Summe) farbig und dann alle folgenden.
    Wenn ich jetzt mit Maus ias Grid fahre macht er die ganze Zeile farbig.

    Ich komm mit der Zuweisung nicht so recht klar.
    Hab jetzt 2 Tage die ganzen Hinweise gelesen und rumgebastelt, paar nette Anregungen für andere Sachen gefunden, aber das eigentliche Ziel (s.u.) nicht umsetzen können.

    Thx@all



  • Wenn du nur ein einzelnen Feld farbig haben möchstest mußt du noch abfragen welche Spalte grad gezeichnet wird. Das geht entweder über DataCol oder Column. Beide Werte werden im Ereignis OnDrawColumnCell geliefert.



  • Ja das hab ich mir schon gedacht, das ich diese Werte übergeben muss, ich bin bloß noch nicht dahintergestiegenwie ich das ermittle, weil der MIN/MAX wert ja erst nach der letzten eingabe ermittelt wird und ich dann nicht mehr in der Spalte/Zeile bin wo der MIN/MAX Werte drin steht.
    Also muß ich ja das nachträglich irgendwie prüfen können.

    Und dann noch, wenn ich jetzt den nächsten Datensatz aufrufe wird ja das Grid auch wieder neu gezeichnet und die farblichen Markieren sollen aber bestehen bleiben.

    ???

    Thx@all



  • du könntest ein DBGrid1->Refresh(); aufrufen nachdem Min/Max neu gesetzt wurde

    die Prüfung der Spalte erfolgt nur im Ereignis OnDrawColumnCell, z.B.:

    if( Column->Field->FieldName == "W1" &&(ADOTable1->FieldByName("W1")->Value == Max || ADOTable1->FieldByName("W1")->Value == Min) )
     {
      DBGrid1->Canvas->Brush->Color = clRed;
      DBGrid1->Canvas->FillRect(Rect);
      DBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);
     }
    

    Prominenter schrieb:

    Und dann noch, wenn ich jetzt den nächsten Datensatz aufrufe wird ja das Grid auch wieder neu gezeichnet und die farblichen Markieren sollen aber bestehen bleiben.

    wenn der Quellcode im Ereignis OnDrawColumnCell, sollte das auch so sein

    [Edit]das wars für heute 🙂



  • @Linnea

    Irgendwie raff ich das nicht.

    Hier bekomme ich schon die erste Fehlermeldung:

    if( Column->Field->FieldName == "W1" &&(ADOTable1->FieldByName("W1")->Value == Max || ADOTable1->FieldByName("W1")->Value == Min) )
    

    Ich hab hier mal ein Beispielbild, wie das DBGRID am Ende aussehen sollte.
    http://www.concepts-multimedia.de/beispiel.jpg

    Die Liste ist am Ende durchaus mit 100-150 Zeilen belegt, je nach Teilnehmeranzahl.

    Die Eingaben dazu kommen per DBMemo1-7, wenn DBMemo7 fertig soll die Berechnung und Kennzeichnung beginnen, die Punktzahl und die Platzierung ausgegegeben werden.

    @all
    Ich brauch hierbei ein bischen Hilfe von Euch.
    Wie stell ich die jeweiligen Berechnungen an, das das am Ende hinhaut.
    Thx@all



  • hier mal ein Lösungsvorschlag:

    zum Auslesen von min/max:

    #include <vector>
    //  Definition in der Klasse
    std::vector< int > min;
    std::vector< int > max;
    std::vector< int > minindex;
    std::vector< int > maxindex;
    
    //Aufruf in einer Methode nachdem die Tabelle geöffnet wurde
    min.resize(ADOTable1->RecordCount,1000);
    max.resize(ADOTable1->RecordCount,0);
    minindex.resize(ADOTable1->RecordCount,0);
    maxindex.resize(ADOTable1->RecordCount,0);
    for (ADOTable1->First();!ADOTable1->Eof;ADOTable1->Next())
      {
      for (int i=3; i<10; i++)
        {
        int wert = ADOTable1->Fields->Fields[i]->AsInteger;
        if (min[ADOTable1->RecNo] > wert)
          {
          min[ADOTable1->RecNo] = wert;
          minindex[ADOTable1->RecNo] = i;
          }
        if (max[ADOTable1->RecNo] < wert)
          {
          max[ADOTable1->RecNo] = wert;
          maxindex[ADOTable1->RecNo] = i;
          }
        }
      }
    

    in diesem Teil kannst du auch noch die Summenberechnung machen

    zum Einfärben im DBGrid:

    void __fastcall TForm1::DBGrid1DrawColumnCell(TObject *Sender,
          const TRect &Rect, int DataCol, TColumn *Column,
          TGridDrawState State)
    {
    if (DataCol > 2 && DataCol < 10)
      {
      if (DataCol == maxindex[ADOTable1->RecNo] || DataCol == minindex[ADOTable1->RecNo])
        {
        DBGrid1->Canvas->Brush->Color = clRed;
        DBGrid1->Canvas->FillRect(Rect);
        DBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);
        }
      }
    

    da sind jetzt natürlich einige neue Sachen drin, wie z.B. die Verwendung von Vector, aber da mußt du dich halt durcharbeiten 🙂



  • @Linnea

    Danke für deine Mühe, ich hab das mal jetzt so ausprobiert, bekomme aber gleich eine Fehlermeldung:
    -> if (DataCol == maxindex[ADOTable1->RecNo] || DataCol == minindex[ADOTable1->RecNo])

    ---------------------------
    Benachrichtigung über Debugger-Exception
    ---------------------------
    Im Projekt Turnier.exe ist eine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 00404046 in Modul 'Turnier.exe'. Lesen von Adresse 00000004' aufgetreten.
    ---------------------------
    Anhalten   Fortsetzen   Hilfe   
    ---------------------------
    

    Und dann hab ich gelich noch ein Problem:
    Wenn ich den ersten Datensatz ändere, also Werte eingebe, und das DBMemo7 verlasse oder zum nächsten Datensatz springen will erhalte ich :

    ---------------------------
    Benachrichtigung über Debugger-Exception
    ---------------------------
    Im Projekt Turnier.exe ist eine Exception der Klasse EOleException mit der Meldung 'Operation muss eine aktualisierbare Abfrage verwenden' aufgetreten.
    ---------------------------
    Anhalten   Fortsetzen   Hilfe   
    ---------------------------
    

    Ich habe überall ADOTable1->Edit(); gesetzt ???

    Thx@all



  • Sorry, hatte ich überlesen

    //Aufruf in einer Methode nachdem die Tabelle geöffnet wurde
    

    Allerdings habe ich jetzt auch da wo noch gar keine Daten drin stehen farbige Felder.

    :: Hab es gelöst: if (wert != NULL)

    Thx@all



  • @Linnea

    Summenberechnung habe ich hinbekommen

    // Punkte berechnen
    void Punktzahl(TObject *Sender, int lastData)
    {
     if(TADOTable* Table = dynamic_cast<TADOTable*>(Sender))
     {
      min.resize(Table->RecordCount,1000);
      max.resize(Table->RecordCount,0);
      int sum = 0;
      int pkt = 0;
      for (int i=3; i<10; i++)
      {
       int wert = Table->Fields->Fields[i]->AsInteger;
       if (wert)
       {
    	// Alle Punkte zusammenrechnen
    	sum += wert;
    	// MIN Wert
    	if (min[Table->RecNo] > wert )
    	{
    	 min[Table->RecNo] = wert;
    	}
    	// MAX Wert
    	if (max[Table->RecNo] < wert )
    	{
    	 max[Table->RecNo] = wert;
    	}
       }
      }
      // MIN/MAX Wert abziehen
      pkt = sum - min[Table->RecNo] - max[Table->RecNo];
    
      ShowMessage(pkt);
      Table->Edit();
      Table->FieldByName("MIN")->Value = min[Table->RecNo];
      Table->FieldByName("MAX")->Value = max[Table->RecNo];
      Table->FieldByName("Punkte")->Value = pkt;
      Table->FieldByName("Gesamt")->Value = sum;
     }
    }
    

    Jetzt bräuchte ich noch einen Ansatz für die Berechnung der Platzierung anhand der Punkte.

    Thx@all


Anmelden zum Antworten