StringGrid Durchsuchung funktioniert nicht richtig

    StringGrid Durchsuchung funktioniert nicht richtig

    Hallo zusammen

    Ich habe ein Testprogramm geschrieben in dem ein StringGrid durchsucht werden soll und zwar wie folgt:

    1) Durchsung soll >= der eingegeben Zahl (Edit1) erfolgen
    2) Es soll immer eine Spalte nach der anderen durchsucht werden und nicht alles auf einmal.

    Jetzt zu meinem Problemm die durchsuchung funktioniert nur mit = , wenn ich aber >= eingebe gibt er mit den wert aus der 3 Spalte aus und nicht wie er sollte aus der 1 Spalte.

    hier mal der Quellcode

    Delphi-Code

    1. procedure TForm1.FormShow(Sender: TObject);
    2. var
    3. rowcount, currentrow: Integer;
    4. begin
    5. // Gathering row count
    6. query.SQL.Text:='select * from mydata';
    7. query.Open;
    8. rowcount:=query.RecordCount + 1;
    9. query.Close;
    10. // Setting up col names
    11. grid.Cols[0].SetText('');
    12. grid.Cols[1].SetText('15x1');
    13. grid.Cols[2].SetText('18x1');
    14. grid.Cols[3].SetText('22x1');
    15. // Setting up rows
    16. grid.RowCount:=rowcount;
    17. grid.FixedRows:=1;
    18. query.SQL.Text:='select * from mydata';
    19. query.Open;
    20. while not query.Eof do
    21. begin
    22. currentrow:=query.fieldbyname('id').AsInteger;
    23. grid.Cells[0,currentrow]:=query.fieldbyname('linevalue').AsString;
    24. grid.Cells[1,currentrow]:=query.fieldbyname('15x1').AsString;
    25. grid.Cells[2,currentrow]:=query.fieldbyname('18x1').AsString;
    26. grid.Cells[3,currentrow]:=query.fieldbyname('22x1').AsString;
    27. query.Next;
    28. end;
    29. query.Close;
    30. end;
    31. procedure TForm1.Edit1Change(Sender: TObject);
    32. var
    33. rowcount,col, row: Integer;
    34. begin
    35. rowcount:=grid.RowCount-1;
    36. begin
    37. // searching per column
    38. for row:=1 to rowcount do
    39. begin
    40. for col:=1 to 3 do
    41. begin
    42. if grid.Cells[col,row] = edit1.Text then
    43. begin
    44. edit2.Text:=grid.Cells[col,0];
    45. edit3.Text:=grid.Cells[0,row];
    46. break;
    47. end;
    48. end;
    49. end;
    50. end;
    51. // deleting results if edit1 = empty
    52. if edit1.Text = '' then
    53. begin
    54. edit2.Clear;
    55. edit3.Clear;
    56. end;
    57. end;
    58. procedure TForm1.CheckBox1Click(Sender: TObject);
    59. begin
    60. edit1.OnChange(Sender);
    61. end;
    62. end.


    hier noch ein Auszug aus der Tabelle



    Nicht wundern das die werte in einer anderen Spalten auch vorhanden sein könnte. Das ist einen Tabelle aus einem Tabellenfachbuch

    Noch zur Info, ich verwende Delphi XE2 das Stringgrid wird aus einer Datenbank gefüllt mittels Zeos Access

    Ich bedanke mich schon mal für die Hilfe, habe selbst mal hin und her Probiert aber es will nich wie es soll.
    Dir ist bewusst, dass in Deinem Edit keine Zahl steht, sondern höchstens die Stringdarstellung einer Zahl, dasselbe in den Zellen Deines StringGrids? Dadurch vergleichst Du keine Zahlen, sondern Strings, und da gelten andere Regeln (z.B. 2 > 100). Abgesehen davon, dass die Datenhaltung in visuellen Komponenten nicht das Gelbe vom Ei ist, musst Du also für einen korrekten Vergleich beide Vergleichswerte zuerst in Zahlen umwandlen (StrToInt, StrToFloat, TryStrToInt, TryStrToFloat, etc., was halt bei Dir am besten passt).
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    Nein, das ist ja nicht Sache des StringGrids, den eigentlich gemeinten Datentyp zu wissen, es stellt einfach nur Strings dar. Und wenn Du einen String in eine Zahl umwandeln kannst, wer hindert Dich daran, das mit dem zweiten auch zu tun? Heraus kommen dann 2 Zahlen, die Du vergleichen kannst.
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    vieleicht Denke ich jetzt um zich Ecken aber das würde heisen ich müste jede einzelne Zelle erst umwandeln, da mit ich sie vergleichen kann.
    Da mein Programm circa 25 verschidenen Tabellen enthalten wird ist das ein ordentlicher Aufwand. Das was ich jetzt hier gepostet habe ist einfach eine Testfunktion, da würde es ja noch gehen.
    Gibt es irgen eine möglichkeit das ich z.B. das mit einer anderen Komponente leichter gelöst bekomme.
    habe mir das nicht so schwer vorgestellt.
    Schnelle Lösung: schreib Dir einfach eine Funktion, die 2 Strings entgegennimmt und deren „Zahleninhalte“ vergleicht. Diese Funktion ziehst Du dann einfach zum Vergleichen heran. Elegantere Lösung: Speichere Deine Daten nicht in einer visuellen Komponente, sondern in einer geeigneten Struktur wie einer Liste aus Records. Das StringGrid dient dann nur noch nur Darstellung dieser Liste, zahlenmäßige Auswertungen etc. werden von der Liste übernommen.
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    So, hier ein kleines Beispiel, wie man das machen könnte. Zunächst die Datenstruktur:

    Delphi-Code

    1. type
    2. // Record, der die Daten eines einzelnen Datensatzes aufnimmt
    3. TDataRecord = record
    4. strict private
    5. FID: integer;
    6. FLineValue: integer;
    7. FLineValueSet: Boolean;
    8. F15x1: integer;
    9. F15x1Set: Boolean;
    10. F18x1: integer;
    11. F18x1Set: Boolean;
    12. F22x1: integer;
    13. F22x1Set: Boolean;
    14. procedure Set15x1(const Value: integer);
    15. procedure Set18x1(const Value: integer);
    16. procedure Set22x1(const Value: integer);
    17. procedure SetLineValue(const Value: integer);
    18. function Get15x1AsStr: string;
    19. function Get18x1AsStr: string;
    20. function Get22x1AsStr: string;
    21. function GetLineValueAsStr: string;
    22. public
    23. class function Create: TDataRecord; static;
    24. property ID: integer read FID write FID;
    25. // Die folgenden Properties folgem dem Schema
    26. // - Wert
    27. // - Wert wurde gesetzt? Wenn nicht, als NULL betrachten
    28. // - String-Repräsentation des Wertes ('' bei nicht gesetztem Wert)
    29. property LineValue: integer read FLineValue write SetLineValue;
    30. property LineValueSet: Boolean read FLineValueSet;
    31. property LineValueAsStr: string read GetLineValueAsStr;
    32. property _15x1: integer read F15x1 write Set15x1;
    33. property _15x1Set: Boolean read F15x1Set;
    34. property _15x1AsStr: string read Get15x1AsStr;
    35. property _18x1: integer read F18x1 write Set18x1;
    36. property _18x1Set: Boolean read F18x1Set;
    37. property _18x1AsStr: string read Get18x1AsStr;
    38. property _22x1: integer read F22x1 write Set22x1;
    39. property _22x1Set: Boolean read F22x1Set;
    40. property _22x1AsStr: string read Get22x1AsStr;
    41. end;
    42. ...
    43. class function TDataRecord.Create: TDataRecord;
    44. begin
    45. Result := Default (TDataRecord);
    46. end;
    47. function TDataRecord.Get15x1AsStr: string;
    48. begin
    49. if F15x1Set then
    50. Result := IntToStr(F15x1)
    51. else
    52. Result := '';
    53. end;
    54. function TDataRecord.Get18x1AsStr: string;
    55. begin
    56. if F18x1Set then
    57. Result := IntToStr(F18x1)
    58. else
    59. Result := '';
    60. end;
    61. function TDataRecord.Get22x1AsStr: string;
    62. begin
    63. if F22x1Set then
    64. Result := IntToStr(F22x1)
    65. else
    66. Result := '';
    67. end;
    68. function TDataRecord.GetLineValueAsStr: string;
    69. begin
    70. if FLineValueSet then
    71. Result := IntToStr(FLineValue)
    72. else
    73. Result := '';
    74. end;
    75. procedure TDataRecord.Set15x1(const Value: integer);
    76. begin
    77. F15x1 := Value;
    78. F15x1Set := true;
    79. end;
    80. procedure TDataRecord.Set18x1(const Value: integer);
    81. begin
    82. F18x1 := Value;
    83. F18x1Set := true;
    84. end;
    85. procedure TDataRecord.Set22x1(const Value: integer);
    86. begin
    87. F22x1 := Value;
    88. F22x1Set := true;
    89. end;
    90. procedure TDataRecord.SetLineValue(const Value: integer);
    91. begin
    92. FLineValue := Value;
    93. FLineValueSet := true;
    94. end;

    Jetzt die Liste:

    Delphi-Code

    1. // Liste, die Einträge des oben definierten Typs sowie eine Auswertungsfunktion enthält
    2. TDataList = class(TList<TDataRecord>)
    3. public
    4. // Funktion, die alle Listeneinträge in den relevanten Feldern mit dem übergebenen
    5. // Wert vergleicht
    6. // Rückgabe: Index des gefundenen Datensatzes und im out-Parameter FieldIndex den
    7. // Index des Feldes, in dem der passende Wert gefunden wurde
    8. function FindFirstEqualOrGreaterValue(Value: integer;
    9. out FieldIndex: integer): integer;
    10. end;
    11. ...
    12. function TDataList.FindFirstEqualOrGreaterValue(Value: integer;
    13. out FieldIndex: integer): integer;
    14. var
    15. i: integer;
    16. found: Boolean;
    17. begin
    18. FieldIndex := -1;
    19. Result := -1;
    20. found := false;
    21. for i := 0 to Count - 1 do
    22. begin
    23. if Items[i]._15x1Set and (Items[i]._15x1 >= Value) then
    24. begin
    25. found := true;
    26. FieldIndex := 0;
    27. end
    28. else if Items[i]._18x1Set and (Items[i]._18x1 >= Value) then
    29. begin
    30. found := true;
    31. FieldIndex := 1;
    32. end
    33. else if Items[i]._22x1Set and (Items[i]._22x1 >= Value) then
    34. begin
    35. found := true;
    36. FieldIndex := 2;
    37. end;
    38. if found then
    39. begin
    40. Result := i;
    41. break;
    42. end;
    43. end;
    44. end;

    Jetzt noch das Demo-Formular:

    Delphi-Code

    1. procedure TfrmDemo.FormCreate(Sender: TObject);
    2. begin
    3. FDataList := TDataList.Create;
    4. end;
    5. procedure TfrmDemo.FormDestroy(Sender: TObject);
    6. begin
    7. FDataList.Free;
    8. end;
    9. procedure TfrmDemo.ReadDataFromDB;
    10. var
    11. Data: TDataRecord;
    12. Field: TField;
    13. begin
    14. FDataList.Clear;
    15. query.SQL.Text := 'select * from mydata';
    16. query.Open;
    17. while not query.Eof do
    18. begin
    19. Data := TDataRecord.Create;
    20. Data.ID := query.FieldByName('id').AsInteger;
    21. Field := query.FieldByName('linevalue');
    22. if not Field.IsNull then
    23. Data.LineValue := Field.AsInteger;
    24. Field := query.FieldByName('15x1');
    25. if not Field.IsNull then
    26. Data._15x1 := Field.AsInteger;
    27. Field := query.FieldByName('18x1');
    28. if not Field.IsNull then
    29. Data._18x1 := Field.AsInteger;
    30. Field := query.FieldByName('22x1');
    31. if not Field.IsNull then
    32. Data._22x1 := Field.AsInteger;
    33. FDataList.Add(Data);
    34. query.Next;
    35. end;
    36. query.Close;
    37. end;

    Da ich zu faul war, auch noch eine Datenbank aufzusetzen, konnte ich den Code nicht ergiebig testen, es sollte aber funktionieren. Zur Darstellung greifst Du nun eben nicht mehr auf die Query zu, sondern auf die befüllte Liste (im Beispiel FDataList).
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    Welche Komponenten Du verwendest, ist völlig egal, das ist ja der Sinn dahinter. Du kannst die Daten in einem StringGrid, einer ListView oder auch dem VirtualStringTree anzeigen, an meinem Code ändert das nichts.
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    Machen wir es mal etwas anders: die eigenen Datenstrukturen verschieben wir in eine extra Unit (das sollte man sowieso tun).

    Delphi-Code

    1. unit DeliverencData;
    2. interface
    3. uses System.SysUtils, System.Generics.Collections;
    4. type
    5. // Record, der die Daten eines einzelnen Datensatzes aufnimmt
    6. TDataRecord = record
    7. strict private
    8. FID: integer;
    9. FLineValue: integer;
    10. FLineValueSet: Boolean;
    11. F15x1: integer;
    12. F15x1Set: Boolean;
    13. F18x1: integer;
    14. F18x1Set: Boolean;
    15. F22x1: integer;
    16. F22x1Set: Boolean;
    17. procedure Set15x1(const Value: integer);
    18. procedure Set18x1(const Value: integer);
    19. procedure Set22x1(const Value: integer);
    20. procedure SetLineValue(const Value: integer);
    21. function Get15x1AsStr: string;
    22. function Get18x1AsStr: string;
    23. function Get22x1AsStr: string;
    24. function GetLineValueAsStr: string;
    25. public
    26. class function Create: TDataRecord; static;
    27. property ID: integer read FID write FID;
    28. // Die folgenden Properties folgem dem Schema
    29. // - Wert
    30. // - Wert wurde gesetzt? Wenn nicht, als NULL betrachten
    31. // - String-Repräsentation des Wertes ('' bei nicht gesetztem Wert)
    32. property LineValue: integer read FLineValue write SetLineValue;
    33. property LineValueSet: Boolean read FLineValueSet;
    34. property LineValueAsStr: string read GetLineValueAsStr;
    35. property _15x1: integer read F15x1 write Set15x1;
    36. property _15x1Set: Boolean read F15x1Set;
    37. property _15x1AsStr: string read Get15x1AsStr;
    38. property _18x1: integer read F18x1 write Set18x1;
    39. property _18x1Set: Boolean read F18x1Set;
    40. property _18x1AsStr: string read Get18x1AsStr;
    41. property _22x1: integer read F22x1 write Set22x1;
    42. property _22x1Set: Boolean read F22x1Set;
    43. property _22x1AsStr: string read Get22x1AsStr;
    44. end;
    45. // Liste, die Einträge des oben definierten Typs sowie eine Auswertungsfunktion enthält
    46. TDataList = class(TList<TDataRecord>)
    47. public
    48. // Funktion, die alle Listeneinträge in den relevanten Feldern mit dem übergebenen
    49. // Wert vergleicht
    50. // Rückgabe: Index des gefundenen Datensatzes und im out-Parameter FieldIndex den
    51. // Index des Feldes, in dem der passende Wert gefunden wurde
    52. function FindFirstEqualOrGreaterValue(Value: integer;
    53. out FieldIndex: integer): integer;
    54. end;
    55. implementation
    56. { TDataRecord }
    57. class function TDataRecord.Create: TDataRecord;
    58. begin
    59. Result := Default (TDataRecord);
    60. end;
    61. function TDataRecord.Get15x1AsStr: string;
    62. begin
    63. if F15x1Set then
    64. Result := IntToStr(F15x1)
    65. else
    66. Result := '';
    67. end;
    68. function TDataRecord.Get18x1AsStr: string;
    69. begin
    70. if F18x1Set then
    71. Result := IntToStr(F18x1)
    72. else
    73. Result := '';
    74. end;
    75. function TDataRecord.Get22x1AsStr: string;
    76. begin
    77. if F22x1Set then
    78. Result := IntToStr(F22x1)
    79. else
    80. Result := '';
    81. end;
    82. function TDataRecord.GetLineValueAsStr: string;
    83. begin
    84. if FLineValueSet then
    85. Result := IntToStr(FLineValue)
    86. else
    87. Result := '';
    88. end;
    89. procedure TDataRecord.Set15x1(const Value: integer);
    90. begin
    91. F15x1 := Value;
    92. F15x1Set := true;
    93. end;
    94. procedure TDataRecord.Set18x1(const Value: integer);
    95. begin
    96. F18x1 := Value;
    97. F18x1Set := true;
    98. end;
    99. procedure TDataRecord.Set22x1(const Value: integer);
    100. begin
    101. F22x1 := Value;
    102. F22x1Set := true;
    103. end;
    104. procedure TDataRecord.SetLineValue(const Value: integer);
    105. begin
    106. FLineValue := Value;
    107. FLineValueSet := true;
    108. end;
    109. { TDataList }
    110. function TDataList.FindFirstEqualOrGreaterValue(Value: integer;
    111. out FieldIndex: integer): integer;
    112. var
    113. i: integer;
    114. found: Boolean;
    115. begin
    116. FieldIndex := -1;
    117. Result := -1;
    118. found := false;
    119. for i := 0 to Count - 1 do
    120. begin
    121. if Items[i]._15x1Set and (Items[i]._15x1 >= Value) then
    122. begin
    123. found := true;
    124. FieldIndex := 0;
    125. end
    126. else if Items[i]._18x1Set and (Items[i]._18x1 >= Value) then
    127. begin
    128. found := true;
    129. FieldIndex := 1;
    130. end
    131. else if Items[i]._22x1Set and (Items[i]._22x1 >= Value) then
    132. begin
    133. found := true;
    134. FieldIndex := 2;
    135. end;
    136. if found then
    137. begin
    138. Result := i;
    139. break;
    140. end;
    141. end;
    142. end;
    143. end.

    Diese Unit bindest Du nun in der Deines Formulars ein.

    Delphi-Code

    1. unit FormularUnit;
    2. interface
    3. uses
    4. ..., DeliverencData;

    Zusätzlich verpassen wir dem Formular (bei mir heißt die Klasse TfrmDemo) ein Feld vom Typ TDataList und die Datenbank-Lesemethode.

    Delphi-Code

    1. type
    2. TfrmDemo = class(TForm)
    3. ...
    4. procedure FormCreate(Sender: TObject);
    5. procedure FormDestroy(Sender: TObject);
    6. private
    7. { Private-Deklarationen }
    8. FDataList: TDataList;
    9. procedure ReadDataFromDB;
    10. public
    11. { Public-Deklarationen }
    12. end;

    Im FormCreate wird die Liste erzeugt und im FormDestroy wieder freigegeben.

    Delphi-Code

    1. implementation
    2. {$R *.dfm}
    3. procedure TfrmDemo.FormCreate(Sender: TObject);
    4. begin
    5. FDataList := TDataList.Create;
    6. end;
    7. procedure TfrmDemo.FormDestroy(Sender: TObject);
    8. begin
    9. FDataList.Free;
    10. end;
    11. procedure TfrmDemo.ReadDataFromDB;
    12. var
    13. Data: TDataRecord;
    14. Field: TField;
    15. begin
    16. FDataList.Clear;
    17. query.SQL.Text := 'select * from mydata';
    18. query.Open;
    19. while not query.Eof do
    20. begin
    21. Data := TDataRecord.Create;
    22. Data.ID := query.FieldByName('id').AsInteger;
    23. Field := query.FieldByName('linevalue');
    24. if not Field.IsNull then
    25. Data.LineValue := Field.AsInteger;
    26. Field := query.FieldByName('15x1');
    27. if not Field.IsNull then
    28. Data._15x1 := Field.AsInteger;
    29. Field := query.FieldByName('18x1');
    30. if not Field.IsNull then
    31. Data._18x1 := Field.AsInteger;
    32. Field := query.FieldByName('22x1');
    33. if not Field.IsNull then
    34. Data._22x1 := Field.AsInteger;
    35. FDataList.Add(Data);
    36. query.Next;
    37. end;
    38. query.Close;
    39. end;

    Jetzt kannst Du auf die Daten aus der Liste zugreifen und sie darstellen, sei es wie bisher in einem StringGrid oder auch in einer anderen Komponente.
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.

    ismirschlecht schrieb:

    Ich ahme jetzt mal ein Forenmitglied nach, welches sich leider rargemacht hat:
    GRUNDLAGEN

    Na, wen ahme ich da nach ?


    Den, der zwar nicht mehr hier schreibt, aus pers. Gründen... aber immer noch mitliest :)

    PS: und immer schön Grundlagen lernen und ON-Topic bleiben
    Es gibt Wissenschaftler, die behaupten, dass Logik "universell", also überall gleich, sei...
    Ich treffe täglich Menschen, die mit "ihrer" Logik das Gegenteil beweisen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DragonsLear“ ()