Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Filterproblem mit TTable (https://www.delphipraxis.net/82055-filterproblem-mit-ttable.html)

Grolle 7. Dez 2006 12:29

Datenbank: Ads local Server • Version: 7.1 • Zugriff über: TDataSet

Filterproblem mit TTable
 
Hallo,
ich möchte eine Filterung der Datenbank nach Jahreszahlen und zwar:
Sortierkriterien: 3;4;5; oder 2-5
In dem Datenbankfeld werden die Daten durch Semikolon getrennt gespeichert (3;5;6....)
Meine bisherige Lösung ist die Datenbankfelder pro Datensatz zu durchlaufen und bei
einem Treffer eine 1 bzw. eine 0 in ein Extra-DBFeld zu schreiben und darauf dann den Filter
zu verwenden. Weiß jemand da eine performantere Lösung (womöglich ohne zusätzliches DBFeld)?
Viele Grüße...

bttb930 7. Dez 2006 12:50

Re: Filterproblem mit TTable
 
würde man die frage verstehen könnte man die vielleicht helfen.

vielleicht hilft LIKE oder MATCHES?

shmia 7. Dez 2006 12:51

Re: Filterproblem mit TTable
 
Zitat:

Zitat von Grolle
In dem Datenbankfeld werden die Daten durch Simikolon getrennt gespeichert (3;5;6....)

Fehlerhaftes Datenbankdesign.
das verstösst gegen die 1. Normalform
Zitat:

Die erste Normalform (1NF) verlangt, dass die Information in jedem Feld einer Datenbank atomar ist, das heißt eine nicht weiter zerlegbare Einzelinformation. Eine Spalte wie PLZ_ORT oder STRASSE_HAUSNR würde beispielsweise dagegen verstoßen.
Lies mal: http://support.microsoft.com/kb/209534/de

Grolle 7. Dez 2006 13:00

Re: Filterproblem mit TTable
 
Zitat:

Zitat von shmia
Fehlerhaftes Datenbankdesign. das verstösst gegen die 1. Normalform

Ich weiss. Es ist ein Kundenwunsch!

Zitat:

Zitat von bttb930
würde man die frage verstehen könnte man die vielleicht helfen.
vielleicht hilft LIKE oder MATCHES?

Was genau versteht du nicht?

//Edit: Ich habe Mist erzählt. In der Datenbank werden die Daten nicht durch
einen Semikolon getrennt gespeichert, sondern so: 012345 ...

Viele Grüße...

mkinzler 7. Dez 2006 22:49

Re: Filterproblem mit TTable
 
Zitat:

Was genau versteht du nicht?
Nach was du filtern willst.

Grolle 7. Dez 2006 22:58

Re: Filterproblem mit TTable
 
Hi,
nach Jahreszahlen. Diese stehen in einem DB-Feld in dieser Form: 345 (für 2003,2004,2005)
Als Filter soll folgende Eingabe möglich sein: 245 oder 2-5
Viele Grüße....

marabu 8. Dez 2006 09:08

Re: Filterproblem mit TTable
 
Hallo Stefan,

wenn das Datenbankfeld immer einen Wert enthält, der durch das Weglassen beliebiger Ziffern aus der Zeichenfolge 0123456789 gebildet werden kann, dann würde ich einen pattern match mit dem Operator LIKE vorbereiten:

Delphi-Quellcode:
function MatchStr(const sFilter: String; cWild: Char = '%'): String;
var
  i: Integer;
begin
  Result := StringOfChar(cWild, 10);
  for i := 1 to Length(sFilter) do
    Result[Succ(Ord(sFilter[i]) - Ord('0'))] := sFilter[i];
  Result := CompactStr(Result, cWild);
end;
Die Funktion MatchStr('245') liefert dir dann das Pattern '%2%45%' welches du dann für deinen pattern match verwenden kannst. Der Ansatz lässt sich für Bereichsangaben ausbauen.

Grüße vom marabu

Grolle 8. Dez 2006 11:41

Re: Filterproblem mit TTable
 
Hi Marabu,
danke für deinen Vorschlag. Mit meinem bisherigen Ansatz habe ich auch noch einige Probleme:
Delphi-Quellcode:
var
sf : TIniFile;
i : integer;
s : string;
begin
  readstring;
  Form1.AdsTable1.First;
  sf := TIniFile.create(ExtractFilePath(ParamStr(0))+'daten\checkbox.ini');
  While not Form1.AdsTable1.eof do
    begin
      s := Form1.AdsTable1.FieldByName('def3').AsString;
      for i := 0 to 9 do
        if (sf.ReadBool('Jahre',IntToStr(i),true)) and
          (Form1.AdsTable1.FieldByName('bool').AsString = '0')
          and (pos(IntToStr(i),s)>0) then
          begin
            Form1.AdsTable1.Edit;
            Form1.AdsTable1.FieldByName('bool').AsString := '1';
            Form1.AdsTable1.Post;
          end
        else
          begin
            Form1.AdsTable1.Edit;
            Form1.AdsTable1.FieldByName('bool').AsString := '0';
            Form1.AdsTable1.Post;
          end;
      Form1.AdsTable1.Next;
    end;
  Form1.AdsTable1.Filter := 'bool="1"';
  Form1.AdsTable1.Filtered := true;
  sf.Free;
end;
Die Daten kommen aus ner Ini-Datei. Aber in der for-Schleife ist irgendwo ein Fehler?!?
Wie dem auch sei, ich werde mir deine Version mal versuchen auszubauen, da sie wohl etwas
performanter ist :stupid:
// Edit: Was ist denn CompactStr in deinem Code?
Viele Grüße....

marabu 8. Dez 2006 12:56

Re: Filterproblem mit TTable
 
Sorry, hier ein Nachschlag:

Delphi-Quellcode:
function CompactStr(const s: String; c: Char = ' '): String;
var
  i, iDel: Integer;
begin
  Result := s;
  iDel := 0;
  for i := 1 to Length(s) do
    if (i > 1) and (s[i] = c) and (s[Pred(i)] = c)
      then Inc(iDel)
      else Result[i - iDel] := s[i];
  SetLength(Result, Length(s) - iDel);
end;
Grüße

Grolle 8. Dez 2006 14:39

Re: Filterproblem mit TTable
 
Hi Marabu,
danke, das klappt ganz gut. Leider habe ich jetzt gesehen, dass Ads kein LIKE
im Filter unterstützt :cry:

hoika 8. Dez 2006 17:18

Re: Filterproblem mit TTable
 
Hallo,

dann nimm halt ne Query.


Heiko

marabu 8. Dez 2006 18:51

Re: Filterproblem mit TTable
 
Hi,

Zitat:

Zitat von Grolle
... Leider habe ich jetzt gesehen, dass Ads kein LIKE im Filter unterstützt ...

du meinst sicherlich, dass die BDE in einem Filter keinen LIKE Operator kennt? Das BDE-Äquivalent zu "feld LIKE 'DR%'" ist "feld = 'DR*'". Vermutlich werden aber keine komplexen Pattern unterstützt - siehe FilterOptions foPartialCompare. Wenn alle Stricke reißen und du nicht auf Queries umstellen kannst oder willst, dann kannst du auch das Ereignis OnFilterRecord() verwenden. Allerdings wirst du dann bei größeren Datasets nicht allzu glücklich dreinschauen.

Freundliche Grüße

Grolle 9. Dez 2006 13:17

Re: Filterproblem mit TTable
 
Hi,
warum BDE? Ich benutz doch den ADS Local Server!
Kannst du mir sagen, wie man OnFilterRecord() konkret
darauf anwendet bzw. überhaupt nutzt?
Viele Grüße...

marabu 9. Dez 2006 20:40

Re: Filterproblem mit TTable
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Stefan,

vergiss das mit der BDE - da war ich wegen TTable kurz etwas aus der Spur gefahren.

Zu OnFilterRecord() - das könnte etwa so aussehen:

Delphi-Quellcode:
// sMatch := MatchStr('245');

procedure TDemoForm.TableFilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
  Accept := Match(DataSet['JAHRE'], sMatch);
end;
Statt meiner Funktion Match() kannst du auch die Funktion Like() oder vollwertige regular expressions verwenden - ganz nach deinem Geschmack.

Gute Nacht

Grolle 9. Dez 2006 20:43

Re: Filterproblem mit TTable
 
Besten Dank! Werde mich gleich mal dransetzen :coder:
Gute Nacht

Grolle 10. Dez 2006 12:23

Re: Filterproblem mit TTable
 
Hallo,
habe alles soweit gemacht, jedoch bekomme ich jetzt zwischendurch folgende Exception:
Zitat:

Variante des Typs (Null) konnte nicht in Typ (String) konvertiert werden EVariantTypeCastError
Muss ich bei der Benutzung von onfilterrecord irgendwas beachten? (Benutze auch andere Filter!)

mkinzler 10. Dez 2006 12:38

Re: Filterproblem mit TTable
 
Überprüfe vorher auf Null (.isNull)

marabu 10. Dez 2006 13:19

Re: Filterproblem mit TTable
 
Hi,

wenn NULL-Werte vorkommen können, dann kann man sich auch so helfen:

Delphi-Quellcode:
 Accept := Match(VarToStr(DataSet['JAHRE']), sMatch);
Freundliche Grüße

Grolle 10. Dez 2006 20:13

Re: Filterproblem mit TTable
 
Danke, das klappt schonmal super. Allerdings kommt es nach mehrmaligem einsetzen von
Filtern zu einem Durcheinander. Gibt es keine vernünftige Hilfe/Tutorial zur Verwendung
von onfilterrecord mit filtern (gemeinsame und getrennte Nutzung)? Die Delphi-Hilfe gibt
da ja kaum was her :?
Viele Grüße....

marabu 10. Dez 2006 20:18

Re: Filterproblem mit TTable
 
Hi,

Zitat:

Zitat von Grolle
... Allerdings kommt es nach mehrmaligem einsetzen von
Filtern zu einem Durcheinander. ...

kannst du das genauer beschreiben? Wie gehst du vor und was passiert?

Freundliche Grüße

Grolle 10. Dez 2006 20:27

Re: Filterproblem mit TTable
 
Hi,
hier der Text:
Delphi-Quellcode:
procedure TForm1.AdsTable1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
begin
  //if not AdsTable1.FieldByName('def3').IsNull then
  Accept := Form6.Match(VarToStr(DataSet['def3']),Form6.sMatch);
end;

procedure TForm6.Button1Click(Sender: TObject);
begin
  sMatch := MatchStr(Edit1.Text);
  Form1.AdsTable1.Filtered := true;
  edit1.Text := '';
  Close;
end;
Die anderen Filter rufe ich aus einem PopUp-Menü auf:
Delphi-Quellcode:
procedure TForm1.MenuItemClick(sender : TObject);
var
s, g : string;
begin
  with Sender as TMenuItem do
    if count = 0 then
      begin
        s := Caption;
        s := StringReplace(s,'&','',[rfReplaceAll]);
        g := parent.Caption;
        g := StringReplace(g,'&','',[rfReplaceAll]);
        if s = lng.GetValue('topitem') then ADSTable1.Filtered := False
        else if s = 'Special Filter' then Form6.Show
        else if s = lng.GetValue('nodeitem') then
          begin
            AdsTable1.Filter := 'node = "'+g+'"';
            AdsTable1.Filtered := true;
          end
        else
          begin
            if g = '' then
            begin
              AdsTable1.Filter := 'node="'+s+'"';
              AdsTable1.Filtered := true;
            end
            else
            begin
              AdsTable1.Filter := 'node = "'+g+'" .AND. tree="'+s+'"';
              AdsTable1.Filtered := true;
            end;
          end;
      end;
end;

marabu 10. Dez 2006 22:04

Re: Filterproblem mit TTable
 
Hallo Stefan,

bevor du den Filter neu setzt, solltest du Filtered auf False setzen. Und schau mal hier:

Delphi-Quellcode:
//  s := Caption;
//  s := StringReplace(s, '&', '', [rfReplaceAll]);
s := Menus.StripHotKey(Caption);
Gute Nacht

Grolle 11. Dez 2006 10:25

Re: Filterproblem mit TTable
 
Hallo,
habe jetzt jedesmal bevor der filter neu gesetzt wird fltered auf false gesetzt.
Aber es geht immer noch durcheinander. Wird onfilterrecord bei jedem filtern aus-
gelöst? Kann das der Fehler sein?

marabu 11. Dez 2006 10:54

Re: Filterproblem mit TTable
 
Hallo,

ich kann mir gar nichts darunter vorstellen, wenn du schreibst "Aber es geht immer noch durcheinander". Auch wüsste ich nicht, wie die Auswertung des Filterkriteriums im Ereignis OnFilterRecord() ein wechselndes Ergebnis liefern könnte, je nachdem wie oft die Routine durchlaufen wird. Ich fürchte du musst das alles etwas besser beschreiben, damit ich verstehe.

Freundliche Grüße

Grolle 11. Dez 2006 11:05

Re: Filterproblem mit TTable
 
Hi,
einmal geschieht ja eine Filterzuweisung durch das PopUpMenü.
Unabhängig davon soll aber auch wenn der User es wünscht über
eine andere Maske (im onfilterrecord) die Daten filtern können.
Ich meine, dass die Daten zusammengewürfelt werden (onfilterrecord
und der eigentliche filter). das geht soweit, bis ich gar nix mehr
angezeigt bekomme. :gruebel:

marabu 11. Dez 2006 11:15

Re: Filterproblem mit TTable
 
Okay, verstehe.

Die Kombination der beiden Filtertechniken (OnFilterRecord() und Filter/ed) ist zulässig. Die entsprechende Hilfeseite in der Online Hilfe hast du sicher gelesen. Ich bin sicher, dass du den Fehler irgendwo in deinem Code stecken hast. Wenn du nicht weiter kommst, dann kannst du eine Demo erstellen mit der man dein Problem sehen kann. Fehler die ich reproduzieren kann, kann ich auch beseitigen - oder zumindest erklären.

Freundliche Grüße

Grolle 19. Dez 2006 09:21

Re: Filterproblem mit TTable
 
Hallo Marabu,
habe nochmal ein bischen rumprobiert und alles läuft einwandfrei.
Es lag einfach daran, dass ich den Filter bzw. sMatch nicht an der
richtigen Stelle zurückgesetzt hatte. Jetzt klappt alles einwandfrei!
Besten Dank nochmal :-D

Grolle 21. Aug 2007 16:41

Re: Filterproblem mit TTable
 
Hallo,

ich habe zu diesem alten Thema nochmal eine Frage:
Im Moment suche ich ja so mit onfilterrecord():
Delphi-Quellcode:
Accept := Match(VarToStr(DataSet['JAHRE']), sMatch);
Der übergebene String lautet dann z. B.: %2%45%
Das Ergebnis ist dann z. B.: 123456 - also alles, was diese 3 Ziffern enthält.
Nun die Frage: Ist das auch möglich, über eine oder-Verknüpfung zu suchen? also
enthalten sein muss 2 oder 4 oder 5? (Mit einer Ziffer (%2%) geht das ja schon).

Viele Grüße,
Stefan Göppert

hoika 22. Aug 2007 08:06

Re: Filterproblem mit TTable
 
Hallo,

glaube ich nicht,
dazu brauchst du dann ne Query.


Heiko

Grolle 22. Aug 2007 11:32

Re: Filterproblem mit TTable
 
Hallo,

eine Query kommt leider nicht in Frage. Bei normalen Filtern kann
man doch auch eine oder-Verknüpfung für ein Feld einbauen? Irgendwie
muss das doch gehen. Ich habe leider auch die Delphi-Hilfe nicht
parat. Vielleicht kann mir jemand schreiben was sie zu onfilterrecord()
sagt.

Viele Grüße ...

mkinzler 22. Aug 2007 11:48

Re: Filterproblem mit TTable
 
Zitat:

eine Query kommt leider nicht in Frage
Warum? TTable macht(e) eigentlich nur bei der BDE Sinn, da hier ernormer Overhead erzeugt wird.

Zitat:

Zitat von Delphi-Hilfe
TDataSet.OnFilterRecord Ereignis

Wird jedes Mal ausgelöst, wenn ein anderer Datensatz in der Datenmenge aktiviert und ein Filter verwendet wird.

Klasse
TDataSet

Syntax


[Delphi] property OnFilterRecord: TFilterRecordEvent;


Beschreibung
Mit Hilfe einer Ereignisbehandlungsroutine für OnFilterRecord können Sie für jeden Datensatz in der Datenmenge festlegen, ob er in der Anwendung sichtbar ist. Um anzugeben, dass ein Datensatz die Filterbedingung erfüllt, muss der Parameter Accept in der Ereignisbehandlungsroutine auf true gesetzt werden. Soll ein Datensatz ausgeschlossen werden, setzen Sie Accept auf false. Die meisten von TDataSet abgeleiteten Klassen (z. B. ADO- oder BDE-Datenmengen) initialisieren Accept mit true, bevor die Ereignisbehandlungsroutine für OnFilterRecord aufgerufen wird.
Warnung:
Die Definition einer OnFilterRecord-Ereignisbehandlungsroutine für unidirektionale Datenmengen ist nicht zulässig, da diese keine Filter unterstützen. Wenn Sie trotzdem eine Behandlungsroutine für OnFilterRecord implementieren, wird eine Exception ausgelöst.


Das Filtern ist aktiviert, wenn die Eigenschaft Filtered den Wert true hat. Beim Verarbeiten eines Filters wird die Eigenschaft State der Datenmenge in dsFilter geändert.

Verwenden Sie eine OnFilterRecord-Ereignisbehandlungsroutine für Kriterien, die nicht durch die Eigenschaft Filter implementiert werden können. Wenn Sie beispielsweise die Eigenschaft Filter verwenden, sind keine Feldvergleiche bei lokalen Tabellen (Paradox, dBASE, Access, FoxPro) möglich. Mit einer Ereignisbehandlungsroutine für OnFilterRecord können aber alle Kriterien implementiert werden.
Tipp:
Berücksichtigen Sie unbedingt die Interaktionen zwischen der Eigenschaft Filter und der Ereignisbehandlungsroutine für OnFilterRecord, wenn Sie beide zugleich in einer Anwendung verwenden, damit nicht unbeabsichtigt ein leere Filtermenge entsteht.


Verwandte Informationen
TDataSet.Filter
TDataSet.Filtered
TDataSet.FilterOptions
TDataSet.State
Filter erzeugen
Durch Datensätze einer gefilterten Datenmenge navigieren
Teilmengen von Daten mithilfe von Filtern anzeigen und bearbeiten
Eine Behandlungsroutine für das Ereignis OnFilterRecord schreiben


Borland® Copyright © 2005 Borland Software Corporation. Alle Rechte vorbehalten.



Alle Zeitangaben in WEZ +1. Es ist jetzt 19:50 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