Stringgrid - Nutzung der Picklist

Rund um die LCL und andere Komponenten
Antworten
RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Stringgrid - Nutzung der Picklist

Beitrag von RuhrPotto »

Ich verwende ein Stringgrid zum Einlesen und Bearbeiten / Ergänzen von CSV-Daten vor der Übernahme in eine Datenbank.
Dabei kommen Checkboxen und Picklisten zum Einsatz.

Während die Inhalte der Checkboxen problemlos gesetzt und ausgelesen werden können, habe ich bei der Picklist ein Problem:

1. Wie kann ich zeilenweise einen Vorschlag für den Feldinhalt setzen?
und
2. Wie kann ich den Inhalt der Auswahl ( ItemIndex der Picklist ) zeilenweise wieder auslesen.

Momnetan hab ich die Vermutung, dass 1. gar nicht geht und 2. nur über den Umweg, den ausgewählten Text der Zelle wieder in einen Index umzuwandeln.

Hat jemand eine andere Möglichkeit / Lösung?

Danke
Jeder macht Fehler - viele Fehler brauchen EDV!

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Stringgrid - Nutzung der Picklist

Beitrag von Michl »

Doch, doch, das geht alles. Je nach Vorstellung variiert der Arbeitsumfang.

Wenn du Columns nutzt, diese zur Designzeit im Objetinspektor definierst, kannst du den ButtonStyle auf cbsPickList stellen und Einträge in das Property PickList eintragen und schon hast du eine Picklist, dessen ItemIndex sich nach dem Inhalt der Zelle richtet. Der in der PickList gewählte Eintrag wird automatisch in die Zelle übernommen.

Willst du den Automatismus nicht nutzen, kannst du das auch händisch erledigen. Der Einstieg wäre hier: http://wiki.freepascal.org/Grids_Refere ... _run_time.
Damit hast du eine TCustomComboBox, deren Index du mittels ItemIndex setzen kannst usw.

Man kann auch recht unkompliziert einen eigenen Editor schreiben, so nutze ich zum Beispiel einen, der im Editmodus eine Auswahl an Vorschlägen zur Verfügung stellt und je nach Eingabe des Textes diese Auswahl aktualisiert (ähnlich dem Suchfenster beim Firefox).

Wenn du gar nicht weiter kommst, zeige doch mal etwas Code, was du probiert hast oder lade hier ein Minimalbsp. ohne Executable und Libs hier hoch.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: Stringgrid - Nutzung der Picklist

Beitrag von RuhrPotto »

Also - das Erstellen der Picklist ist nicht mein Problem.

Code: Alles auswählen

 
//Füllen der Kategorieauswahlfelder in Picklist
  sgData.Columns[5].PickList.Clear;
  for i := 0 to HIGH(aKat) do
  begin
    if aKat[i].KatUID <> 0 then pre := cStrich+cBlank else pre := cEmpty;
    sgData.Columns[5].PickList.Add(pre + aKat[i].KBez);
  end; 
 
Die Picklist ist in Col 5 und in allen Rows gleich. Der Anwender wählt hier eine Zuordnung aus.

Beim Füllen des Grids soll die Picklist auf einen Vorschlag gesetzt werden, der sich am inhalt einer anderen Zelle orientiert - etwa so als startk vereinfachtes Beispiel:

Code: Alles auswählen

 
 
Function GetKatVorschlag(sText:string):integer;
begin
  result := -1;
   if sText = 'Affe' then result := 1;
  ...
   if sText = 'Rose' then result := 4;
end;
 
PickList[5,iRow].ItemIndex := GetKatVorschlag(sgData.Cells[1,iRow]);
 
Alternativ habe ich darüber nachgedacht, den "Text" direkt einzustellen (also "Affe").
Dies löst aber nicht das Problem des Rückgabewertes ausser ich frag auf eine leere Zelle ab.

Hoffe es ist verständlich.
Jeder macht Fehler - viele Fehler brauchen EDV!

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Stringgrid - Nutzung der Picklist

Beitrag von Michl »

Wie oben schon geschrieben:
Michl hat geschrieben:Damit hast du eine TCustomComboBox, deren Index du mittels ItemIndex setzen kannst usw.
RuhrPotto hat geschrieben:Beim Füllen des Grids soll die Picklist auf einen Vorschlag gesetzt werden, der sich am inhalt einer anderen Zelle orientiert
Sollte z.B. so funktionieren:

Code: Alles auswählen

  TForm1 = class(TForm)
...
  private
    FcbxEditor: TCustomComboBox;
    procedure FcbxEditorEnter(Sender: TObject);
  end;
...
procedure TForm1.StringGrid1SelectEditor(Sender: TObject;
  aCol, aRow: Integer; var Editor: TWinControl);
begin
  if Editor is TCustomComboBox then begin
    FcbxEditor := TCustomComboBox(Editor);
    FcbxEditor.OnEnter := @FcbxEditorEnter;
  end;
end;
 
procedure TForm1.FcbxEditorEnter(Sender: TObject);
begin
  FcbxEditor.ItemIndex := GetKatVorschlag(...);
end;
Weitere Ereignisse identisch.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: Stringgrid - Nutzung der Picklist

Beitrag von RuhrPotto »

@Michl : Danke für die Hilfe! Das Anzeigen eines Vorschlages funktioniert soweit.

Aber ich hab leider ein Brett vorm Kopf. Das Auslesen des ItemIndex bei der Prüfung krieg ich nicht hin.
Wenn alle Datenreihen bearbeitet wurden, dann sollen die Zellinhalte des Grids geprüft werden - in etwa so:

Code: Alles auswählen

 
procedure TFrmMain.btCheckGridDataClick(Sender: TObject);
var
  i : integer;
begin
  for i := 1 to sgData.RowCount -1 do
    begin
      if sgData.Cells[0,i] = '0' then  //cbsCheckboxColumn - false - keine Auswahl
        begin
          Memo1.Lines.Add('> Keine Übernahme für : ' + sgData.Cells[1,sgData.Row]);
          Continue;
        end;
      if sgData.Cells[2,i] ItemIndex  <= 0 then //cbsPickList
        begin
          Memo1.Lines.Add('> Auswahlfehler : ' + sgData.Cells[1,sgData.Row]);
          Continue;
        end;
 
       //Übertrag in Ergebnismenge ....
    end;
end; 
 
Die Prüfung der Datenreihe soll erst nach ButtonClick erfolgen.
Wie kann ich denn dann noch auf den Index zugreifen?
Jeder macht Fehler - viele Fehler brauchen EDV!

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Stringgrid - Nutzung der Picklist

Beitrag von Michl »

Geht sicherlich auch anders, doch wenn der Editor schon wieder freigegeben wurde, müsstest du einfach die letzte Wahl in einer Variablen (Index oder Inhalt) speichern. Z.B. irgendwie so (ist nicht ganz sauber, funktioniert aber bei mir, da TComboBox nur die Properties von TCustomComboBox veröffentlicht, OnChange bei TCustomComboBox aber protected ist):

Code: Alles auswählen

  TForm1 = class(TForm)
...
  private
    FcbxEditor: TComboBox;
    FcbxLastSelect: String;
    procedure FcbxEditorChange(Sender: TObject);
  end;
...
procedure TForm1.StringGrid1SelectEditor(Sender: TObject;
  aCol, aRow: Integer; var Editor: TWinControl);
begin
  if Editor is TCustomComboBox then begin //<-- das mit nächster Zeile
    FcbxEditor := TComboBox(Editor); //<-- ist eigentlich verboten
    FcbxEditor.OnChange := @FcbxEditorChange;
  end;
end;
 
procedure TForm1.FcbxEditorChange(Sender: TObject);
begin
  FcbxLastSelect := FcbxEditor.Items[FcbxEditor.ItemIndex];
end;
Wenn du es sauber haben willst, müsstest du das Ereignis für TCustomComboBox öffentlich machen.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: Stringgrid - Nutzung der Picklist

Beitrag von RuhrPotto »

Danke Michl - hast mir den Tag gerettet!

Da ich das Grid am Ende vollständig durchlaufen muss und dieses mit verschiedenen Abhängigkeiten variabel biszu 15 Spalten hat, verwende ich ich eine Indextabelle zur Zwischenspeicherung.
Erscheint mir zum jeztigen Zeitpunkt die zweckmässigste Lösung:

Code: Alles auswählen

 
var
  FcbxEditorSelections : array of integer;  
...
//Länge analog Griddaten und vorbelegen mit keine Auswahl
SetLength(FcbxEditorSelections,sgData.RowCount-1);
for i := 0 to High(FcbxEditorSelections) do FcbxEditorSelections[i] := -1; 
 
...
procedure TFrmMain.FcbxEditorEnter(Sender: TObject);
var
  ind : integer;
begin
  ind := GetKatVorschlag(sgData.Cells[1,sgData.Row]);
  FcbxEditor.ItemIndex := ind;
  FcbxEditorSelections[sgData.Row -1] := ind; //Vorauswahl zwischenspeichern
end;  
 
...
procedure TFrmMain.FcbxEditorChange(Sender: TObject);
begin
  FcbxEditorSelections[sgData.Row -1] := FcbxEditor.ItemIndex;  //Auswahl durch Anwender geändert
end;  
 
//Plausi der Griddaten
procedure TFrmMain.btCheckGridDataClick(Sender: TObject);
var
  i : integer;
  wfS : string;
begin
  for i := 1 to sgData.RowCount -1 do
    begin
      ...
 
      if FcbxEditorSelections[i -1] <= 0 then
        begin
          Memo1.Lines.Add('> Keine Zuordnung für : ' + sgData.Cells[1,i]);
          Continue;
        end;
     ...
    end;
end;   
 
 
Damit kann ich Prüfung in einer Schleife nunmehr problemlos handeln und ungültige / fehlerhafte Datenreihen rausfiltern.
Jeder macht Fehler - viele Fehler brauchen EDV!

Antworten