AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language StringGrid nach Spalten aufsteigend und absteigend sortieren
Thema durchsuchen
Ansicht
Themen-Optionen

StringGrid nach Spalten aufsteigend und absteigend sortieren

Offene Frage von "p80286"
Ein Thema von Ykcim · begonnen am 9. Aug 2011 · letzter Beitrag vom 10. Aug 2011
Antwort Antwort
Seite 1 von 2  1 2      
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#1

StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 9. Aug 2011, 11:35
Delphi-Version: 5
Hallo Zusammen,

es gibt zwar schon viel zu dem Thema, wie man StringGrids sortieren kann, aber ich habe nichts gefunden, was ich verwenden kann und alleine bekomme ich es einfach nicht hin. Ich habe auf dem Bereich der Sortierung nicht viel Erfahrung, was die ganze Sache nicht einfacher macht. Ich verwende TurboDelphi...

Ich habe folgendes Problem:
Ich habe ein StringGrid mit folgenden Spalten:
Datum---Kunde---Bedarf---Fertigungsauftrag---Arbeitsgang
15.08.---------------------------------------100--------------------50
15.08.---------------------------------------123--------------------60
16.08.---------xy-------100
16.08.---------zz-------200
18.08.---------------------------------------119--------------------40
18.08.---------------------------------------125--------------------20
18.08.---------------------------------------124--------------------30
19.08.---------ab-------250
19.08.---------df-------180
und so weiter

Aktuell wird mein StringGrid nach der ersten Spalte sortiert. Ich brauche aber eine Sortierung nach mehreren Spalten, denn ich möchte, dass wenn das Datum der Fertigungsaufträge gleich ist, dass dann der Fertigungsauftrag mit der höheren Arbeitsgangnummer oben steht. Nach der Sortierung sollte die Tabelle so aussehen:

Datum---Kunde---Bedarf---Fertigungsauftrag---Arbeitsgang
15.08.---------------------------------------123--------------------60
15.08.---------------------------------------100--------------------50
16.08.---------xy-------100
16.08.---------zz-------200
18.08.---------------------------------------119--------------------40
18.08.---------------------------------------124--------------------30
18.08.---------------------------------------125--------------------20
19.08.---------ab-------250
19.08.---------df-------180
und so weiter

ich hatte in nachstehende Code gefunden. Aber der hat zum einen das Problem, dass er Zahlen als Text verarbeitet (also 100 sieht er als kleiner als 90, wegen der 1) und zum zweiten werden die Spalten alle vom kleinsten bis zum größten sortiert. Ich brauche aber etwas, was, wie oben beschrieben, beides kann.
Delphi-Quellcode:
type
   TMoveSG = class(TCustomGrid); // reveals protected MoveRow procedure

 {...}

procedure SortGridByCols(Grid: TStringGrid; ColOrder: array of Integer);
var
   i, j: Integer;
   Sorted: Boolean;

function Sort(Row1, Row2: Integer): Integer;
var
   C: Integer;
begin
   C := 0;
   Result := AnsiCompareStr(Grid.Cols[ColOrder[C]][Row1], Grid.Cols[ColOrder[C]][Row2]);
   if Result = 0 then
   begin
     Inc(C);
     while (C <= High(ColOrder)) and (Result = 0) do
     begin
       Result := AnsiCompareStr(Grid.Cols[ColOrder[C]][Row1],
         Grid.Cols[ColOrder[C]][Row2]);
       Inc(C);
     end;
   end;
end;

begin
   if SizeOf(ColOrder) div SizeOf(i) <> Grid.ColCount then Exit;

   for i := 0 to High(ColOrder) do
     if (ColOrder[i] < 0) or (ColOrder[i] >= Grid.ColCount) then Exit;

   j := 0;
   Sorted := False;
   repeat
     Inc(j);
     with Grid do
       for i := 0 to RowCount - 2 do
         if Sort(i, i + 1) > 0 then
         begin
           TMoveSG(Grid).MoveRow(i + 1, i);
           Sorted := False;
         end;
   until Sorted or (j = 1000);
   Grid.Repaint;
end;
Hat jemand eine Idee, denn ich bekomme es selber nicht hin.

Vielen Dank
Ykcim
Patrick

Geändert von Ykcim ( 9. Aug 2011 um 12:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#2

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 9. Aug 2011, 13:46
Entschuldige wenn ich gereizt klinge, aber mir platzt jedesmal der Kragen wenn jemand seine "Daten-Anzeige" sortieren will. Warum machst Du das nicht vorher mit den Daten mit denen Du auch das Grid füllst?
Ich würde eine Tlist mit einem Record nehmen, aber eine TObjectlist ist wohl etwas komfortabler.
Spätestens wenn Du mehr als 500 Datensätze in Deinem Bestand hast, ist die Frage ob Du jedes Mal alle Datensätze in Deine Anzeige stopfen willst.
Imenser Vorteil ist, das Du jedes Feld mitdem richtigen Typ behandeln kannst. Da muß man keine virtuellen führenden Nullen in Strings packen, damit die numerische Sortierreihenfolge eingehalten wird.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 9. Aug 2011, 14:36
Hallo K-H,

vielen Dank für Deine Antwort. Ich kann verstehen, dass es von außen betrachtet, vielleicht wenig Sinn macht, wenn man ein StringGrid sortieren lässt. Allerdings ist das nicht einfach nur eine Liste, die da gezeigt wird. Hier werden zwei Listen zusammengeführt, die getrennt voneinander - ähnlich wie ich es aufgezeigt habe, dargestellt werden müssen. Eine Sortierung nachdem die Procedure fertig ist, kann und darf nicht möglich sein, weil sonst das Ergebnis hin ist. Es muss schon so gemacht werden und auch mit einem StringGrid.
Aber vielleicht, wenn es keine Sortierung gibt, die den Annforerungen entspricht, macht es Sinn, die Daten in einer temporären Komponente sortieren zu lassen.
Oder wenn es die Möglichkeit gibt, ein Array of Array entsprechend zu sortieren, bin ich auch daran sehr interessiert...

Vielen Dank im Voraus für Eure Bemühungen

Ykcim
Patrick

Geändert von Ykcim ( 9. Aug 2011 um 14:39 Uhr)
  Mit Zitat antworten Zitat
whsd

Registriert seit: 30. Nov 2007
Ort: Bad Krozingen
7 Beiträge
 
#4

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 9. Aug 2011, 15:20
Schau mal in Deine privaten Nachrichten oder sende mir Deine E-Mail-Adresse.
Gruß
whsd
  Mit Zitat antworten Zitat
delnu
(Gast)

n/a Beiträge
 
#5

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 9. Aug 2011, 20:34
Die von mir benutzte Gridsortierung habe ich gerade nicht zur Hand, weil ich an einem andern Rechner bin.
Aber die nachfolgend zu findende entspricht ihr weitgehend, wenn ich auch nicht weiß, was das für eine Unit
"XStringGrid" sein soll. Bei mir hieß die noch anders.

http://www.koders.com/delphi/fid8EF9...09319460.aspx?

Syntax : Procedure SortStringgrid( Grid: TXStringGrid; byColumn: LongInt;
ascending: Boolean );

Die Parameter :
Grid = zu sortierendes StringGrid
byColumn = zu sortierende Spalte
ascending = Sortierrichtung

Ich verstehe die Aufregung von p80286 über sortierte Stringgrids nicht. Das ist extrem hilfreich, je nachdem,
welche Spalte gerade relevant ist. Natürlich muß man ziemlich trixen, wenn z.B. nach Datum sortiert werden soll, denn man will ja nicht nach Tag, Monat, Jahr sortieren, sondern nach Jahr, Monat, Tag. Falls Interesse besteht, würde ich mal gucken, wo ich das habe - ist schon etliche Jährchen her ...
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#6

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 9. Aug 2011, 23:53
Also ich mag es ja selber nicht unbedingt, wenn man eine Frage stellt und dann als Antwort bekommt, dass man es ganz anders machen soll(te). Trotzdem muss ich mal fragen, warum verwendest Du kein DBGrid? Gibt es irgendwas, dass Dich dazu zwingt? (Das Zusammenführen lasse ich nicht gelten, das ist eine Kernfunktion von SQL)
Alles was Du schreibst, (Mehrfach-)Sortierung (erst recht nach Datum, Zahlen), Listen zusammenführen usw. verlangt nach SQL und folglich einem DBGrid zur Darstellung. Dein "Monstercode", der nicht mal einen Teil der Anforderungen erfüllt, würde sich auf wenige Zeilen reduzieren und zudem robust werden.
Gruß, Jo
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 10. Aug 2011, 01:48
So ist es bei mir gelaufen.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids;

type
  TDateSortFlags = (dsfKunde, dsfBedarf, dsfFertigungsauftrag, dsfArbeitsgang);

  TRecord = Record
    Kunde: string;
    Datum: TDateTime;
    Bedarf, Fertigungsauftrag, Arbeitsgang: integer;
  end;

  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure SortByDate (const Jahr: string; const dsf: TDateSortFlags);
    procedure SetRow (const I: integer; const ARecord: TRecord; const Jahr: string);
    function GetRow (const I: integer; const Jahr: string): TRecord;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


function TForm1.GetRow (const I: integer; const Jahr: string): TRecord;
begin
  with Result, StringGrid1 do
  begin
    if Jahr <> 'then
      Datum:= StrToDateTime(Cells[FixedCols, I]+Jahr)
    else
      Datum:= StrToDateTime(Cells[FixedCols, I]);

    Kunde:= Cells[FixedCols+1, I];

    Bedarf:= StrToIntDef(Cells[FixedCols+2, I], -1);
    Fertigungsauftrag:= StrToIntDef(Cells[FixedCols+3, I], -1);
    Arbeitsgang:= StrToIntDef(Cells[FixedCols+4, I], -1);
  end;
end;


procedure TForm1.SetRow (const I: integer; const ARecord: TRecord; const Jahr: string);
begin
  with ARecord, StringGrid1 do
  begin
    if Jahr <> 'then
      Cells[FixedCols, I]:= FormatDateTime('dd.mm.', Datum)
    else
      Cells[FixedCols, I]:= FormatDateTime('dd.mm.yyyy', Datum);

    Cells[FixedCols+1, I]:= Kunde;

    if Bedarf < 0 then
      Cells[FixedCols+2, I]:= '-'
    else
      Cells[FixedCols+2, I]:= IntToStr(Bedarf);

    if Fertigungsauftrag < 0 then
      Cells[FixedCols+3, I]:= '-'
    else
      Cells[FixedCols+3, I]:= IntToStr(Fertigungsauftrag);

    if Arbeitsgang < 0 then
      Cells[FixedCols+4, I]:= '-'
    else
      Cells[FixedCols+4, I]:= IntToStr(Arbeitsgang);
  end;
end;


procedure TForm1.SortByDate (const Jahr: string; const dsf: TDateSortFlags);
var
  I, J: integer;
  T1, T2: TRecord;
  ExChange: boolean;
begin
  for I:= StringGrid1.FixedRows to StringGrid1.RowCount-2 do
    for J:= I+1 to StringGrid1.RowCount-1 do
    begin
      ExChange:= false;
      T1:= GetRow(I, Jahr);
      T2:= GetRow(J, Jahr);

      if T1.Datum > T2.Datum then // up
        ExChange:= true
      else
        if T1.Datum = T2.Datum then
        begin
          if dsf = dsfKunde then
            if T1.Kunde > T2.Kunde then ExChange:= true; // up

          if dsf = dsfBedarf then
            if T1.Bedarf < T2.Bedarf then ExChange:= true; // down

          if dsf = dsfFertigungsauftrag then
            if T1.Fertigungsauftrag < T2.Fertigungsauftrag then ExChange:= true; // down

          if dsf = dsfArbeitsgang then
            if T1.Arbeitsgang < T2.Arbeitsgang then ExChange:= true; // down
        end;
      if ExChange then
      begin
        SetRow(I, T2, Jahr);
        SetRow(J, T1, Jahr);
      end;
    end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  SortByDate ('2011', dsfFertigungsauftrag);
end;


procedure TForm1.FormCreate(Sender: TObject);
var
  I, J, K: integer;
begin
  randomize;
  with StringGrid1 do
  begin
    for I:= FixedRows to RowCount-1 do
      for J:= FixedCols to ColCount-1 do
        Cells[J, I]:= '-';

    K:= FixedCols;
    Cells[K, FixedRows]:= '15.08.';
    Cells[K, FixedRows+1]:= '15.08.';
    Cells[K, FixedRows+2]:= '16.08.';
    Cells[K, FixedRows+3]:= '16.08.';
    Cells[K, FixedRows+4]:= '18.08.';
    Cells[K, FixedRows+5]:= '18.08.';
    Cells[K, FixedRows+6]:= '18.08.';
    Cells[K, FixedRows+7]:= '19.08.';
    Cells[K, FixedRows+8]:= '19.08.';

    K:= FixedCols+1;
    for J:= FixedRows to RowCount-1 do
      Cells[K, J]:= IntToStr(RowCount-1-J);

    K:= FixedCols+2;
    Cells[K, FixedRows+2]:= '100';
    Cells[K, FixedRows+3]:= '200';
    Cells[K, FixedRows+7]:= '250';
    Cells[K, FixedRows+8]:= '180';

    K:= FixedCols+3;
    Cells[K, FixedRows]:= '100';
    Cells[K, FixedRows+1]:= '123';
    Cells[K, FixedRows+4]:= '119';
    Cells[K, FixedRows+5]:= '125';
    Cells[K, FixedRows+6]:= '124';

    K:= FixedCols+4;
    Cells[K, FixedRows]:= '50';
    Cells[K, FixedRows+1]:= '60';
    Cells[K, FixedRows+4]:= '40';
    Cells[K, FixedRows+5]:= '20';
    Cells[K, FixedRows+6]:= '30';
  end;
end;

end.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#8

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 10. Aug 2011, 09:03
Entschuldige wenn ich gereizt klinge, aber mir platzt jedesmal der Kragen wenn jemand seine "Daten-Anzeige" sortieren will. Warum machst Du das nicht vorher mit den Daten mit denen Du auch das Grid füllst?
Ich kann diesen Einwand nachvollziehen. Wieso nicht die zugrundeliegenden Daten sortieren und erst dann im Grid darstellen? Dann kümmert sich die "Datenliste" um die korrekte Sortierung für verschiedenste Datentypen (Integer, Double, TDateTime, String, bla, blubb). Das finde ich zumindest zielführender als auf der Darstellungsebene mühselig herumfummeln zu müssen.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
831 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 10. Aug 2011, 16:36
Hallo Zusammen,

vielen Dank für die vielen Antworten und Anmerkungen!

Vorab, auch wenn es nicht wirklich schön ist, habe ich das Problem mit einer Repeat- und einer For-Schleife gelöst.
Delphi-Quellcode:
  i:=0;
  repeat
    i:=i+1;
    Status:=true;
    for J := 1 to Grid.RowCount - 1 do
      begin
        if (Grid.Cells[3,j]<>'') and (Grid.Cells[3,j]<>' ') and
           (Grid.Cells[3,j-1]<>'') and(Grid.Cells[3,j-1]<>' ') and
           (Grid.Cells[6,j-1]<>'') and(Grid.Cells[6,j-1]<>' ') and
           (Grid.Cells[6,j]<>'') and(Grid.Cells[6,j]<>' ') and
           (Grid.Cells[0,j]=Grid.Cells[0,j-1]) and
           (strtoint(Grid.Cells[6,j])>strtoint(Grid.Cells[6,j-1])) then
          begin
            Status:=false;
            for K := 0 to Grid.ColCount - 1 do
              begin
                Tempo:=Grid.Cells[k,j-1];
                Grid.Cells[k,j-1]:=Grid.Cells[k,j];
                Grid.Cells[k,j]:=Tempo;
                Tempo:=''
              end;

          end;

      end;
  until (Status=true) or (I>1000) ;
Die vielen If-Anweisungen benötge ich zum einen um die Anforderungen zu beschreiben und um mögliche Fehler innerhalb der automatisch eingelesenen Daten vorzubeugen.
Bin aber an anderen grundsätzlichen Lösungen interessiert!

Warum lasse ich das den SQL-Server nicht machen? Um es kurz zu sagen, ich weiß nicht, wie das in diesem Falle funktionieren soll.
Aber ich beschreibe Euch die Situation mal, im Zweifel lerne ich - wie so oft.

Mein StringGrid wird aus Daten sechs Tabellen befüllt. Aber sehen wir uns erst einmal nur die beiden wichtigsten an. Das ist auf der einen Seite der Kundenbedarf und auf der anderen Seite die Fertigungsaufträge. In der Darstellung nachher, soll es genauso aussehen, wie ober beschrieben, nämlich komplett sortiert nach Lieferdatum (für die Kundenbedarfe) und Fertigstellungsdatum (für die Fertigungsaufträge). Während die Kundenbedarfsdaten sich auf zwei Spalten konzentrieren, stehen die Fertigungsauftragsdaten ind drei weiteren, aber nie in der gleichen Zeile.
Wenn es mehrere Fertigungsaufträge mit dem gleichen angestrebten Fertigstellungsdatum gibt, sollen diese so sortiert sein, dass der weiteste oben steht.

Die restlichen Tabellen werden für andere Daten benötigt, die zu den Fertigungsaufträgen noch benötigt werden.

Hier noch einmal die Ziel-Darstellung:
Datum---Kunde---Bedarf---Fertigungsauftrag---Arbeitsgang
15.08.----------------------------------123--------------------60
15.08.----------------------------------100--------------------50
16.08.-----xy-------100
16.08.-----zz-------200
18.08.----------------------------------119--------------------40
18.08.----------------------------------124--------------------30
18--------------------------------------125--------------------20
19.08.-----ab-------250
19.08.-----df-------180

Darüber hinaus wird eine Spalte berechnet, die ich aber jetzt auch außen vorlassen möchte.

Würdet Ihr so eine Aufgabenstellung, die ich schon vereinfacht habe, versuchen komplett auf dem Datenbankserver zu generieren? Ich habe keine Idee, wie das funktionieren soll.

Vielen Dank und Lieben Gruß
Ykcim
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.625 Beiträge
 
Delphi 12 Athens
 
#10

AW: StringGrid nach Spalten aufsteigend und absteigend sortieren

  Alt 10. Aug 2011, 16:42
Ohne jetzt die genaue DB-Struktur zu kennen klingt es für mich, als könnte man das in einem JOIN über die betroffenen Tabellen zusammenbasteln und anschließend nach Anforderung sortieren.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:53 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