Link to home
Start Free TrialLog in
Avatar of pka4916
pka4916

asked on

Filter / Sorting with VirtualTree from Soft-Gems

I am trying to figure out a way how to sort properly and filter items out of a tree.

when i have this this in a treeview

001  Donald     USA
002  Donald     EUR
003  John       SPA
004  John       EUR
005  Rudy       ITA
006  Rene       USA

I want to see only the ones that are out of the USA,  if there is no USA then select EUR

so the list would end like this

001  Donald     USA
004  John       EUR
006  Rene       USA

I can't figure out, how to proceed.  the following code will filter all the duplicate names,
but don't know how to add the criteria for the country.

thank you so much for all your help
PdupeTreeData = ^TdupenodeData;
  Tdupenodedata = record
        number      : string;
        name         : string;
         country        : string;
    end;
 
var
  i1, i2: Integer;
  mytreedata1,mytreedata2 : PVirtualNode;
  x : integer;
  my1 : PdupeTreeData;
  my2 : PdupeTreeData;
 
 
dupetree.beginupdate;
 
Node1 := dupetree.GetFirst;
  while Node1<>nil do
  begin
    my1 := dupetree.GetNodeData(Node1);
    Node2 := dupetree.GetNext(Node1);
    while Node2<>nil do
    begin
      my2 :=dupetree.GetNodeData(Node2);
      if  my1.name = my2.name  then
      begin
        temp := dupetree.getnext(Node2);
        dupetree.isvisible[node2]:=false ;
        Node2:=temp;
      end else
        Node2 := dupetree.GetNext(Node2);
    end;
   Node1 := dupetree.GetNext(Node1);
  end;
dupetree.Endupdate;

Open in new window

Avatar of Geert G
Geert G
Flag of Belgium image

your var declaration changed ?

your criteria do not match your sample ...
shouldn't it be :

004  John       EUR
005  Rudy       ITA

why not use a TStrings to find the duplicates ?

you don't check if the first item is in the duplicates, this wouldn't work correctly (you need to hide first node)
001  Donald     SPA
002  Donald     EUR

var
  Node1, Node2 : PVirtualNode;
  n, m : integer;
  my1 : PdupeTreeData;
  my2 : PdupeTreeData;
  found: TStringList;
 
dupetree.beginupdate;
try
  found := TStringList.Create;
  try
    Node1 := dupetree.GetFirst;
    while Node1<>nil do
    begin
      my1 := dupetree.GetNodeData(Node1);
      // first add all duplicates to the list
      found.clear;
      found.AddObject(my1.country, Node1);
      Node2 := dupetree.GetNext(Node1);
      while Node2<>nil do
      begin
        my2 := dupetree.GetNodeData(Node2);
        if  my1.name = my2.name  then
          found.AddObject(my2.country, Node2);
        Node2 := dupetree.GetNext(Node2);
      end;
      // now process the list
      repeat
        n := found.IndexOf('USA');
        if n <> -1 then 
          found.Delete(n); // remove all usa
      until n = -1;
      n := found.IndexOf('EUR');
      if n <> -1 then // hide all non EUR duplicate nodes
      begin
        for m := 0 to found.Count-1 do
          if m <> n then 
            dupetree.isvisible[PVirtualNode(found.objects[m])] := false;
      end; // else leave all EUR nodes visible
      Node1 := dupetree.GetNext(Node1);
    end;
  finally
    found.Free;
  end;
finally
  dupetree.Endupdate;
end;

Open in new window

Avatar of pka4916
pka4916

ASKER

I tried this code, but it's giving an error

found.AddObject(my1.country, Node1);

imcompatible types   Tobject and TvirtualNode

Avatar of pka4916

ASKER

the list should end like this

Original
001  Donald     USA
002  Donald     EUR
003  John       SPA
004  John       EUR
005  Rudy       ITA
006  Rene       USA

I want to see only the ones that are out of the USA,  if there is no USA then select EUR
so the list would end like this
Results:
001  Donald     USA
004  John       EUR
006  Rene       USA


005   ITA   does not have USA or EUR  so this will be invisible.  
you only want to see the ones out of the USA
then why do you want to show

001  Donald     USA
006  Rene       USA

These are in the USA !

you don't make sense
Avatar of pka4916

ASKER

?  that's what I am saying

I am showing the before and after the filter.

Think I see the confusing.   I want to show all the people that are IN the USA



Avatar of pka4916

ASKER

I Can't change my posts,  sorry about that.

aha, well you could do it like this:

filter on a country
procedure TForm1.FilterCountry(aCountry: string);
var
  Node1, Node2 : PVirtualNode;
  m : integer;
  my1 : PdupeTreeData;
  my2 : PdupeTreeData;
  found: TStringList;
begin 
  dupetree.beginupdate;
  try
    found := TStringList.Create;
    try
      Node1 := dupetree.GetFirst;
      while Node1<>nil do
      begin
        my1 := dupetree.GetNodeData(Node1);
        // first add all duplicates to the list
        found.clear;
        found.AddObject(my1.country, TObject(Integer(Node1)));
        Node2 := dupetree.GetNext(Node1);
        while Node2<>nil do
        begin
          my2 := dupetree.GetNodeData(Node2);
          if  my1.name = my2.name  then
            found.AddObject(my2.country, TObject(Integer(Node2)));
          Node2 := dupetree.GetNext(Node2);
        end;
        // now process the list
        for m := 0 to found.Count-1 do
          if found[m] <> aCountry then 
            dupetree.isvisible[PVirtualNode(Integer(found.objects[m]))] := false;
        Node1 := dupetree.GetNext(Node1);
      end;
    finally
      found.Free;
    end;
  finally
    dupetree.Endupdate;
  end;
end;

Open in new window

Avatar of pka4916

ASKER

Thank you very much,  that part is working now.

I hate to be a pest, but how can I  get the next country? meaning
I had Original
001  Donald     USA
002  Donald     EUR
003  John       SPA
004  John       EUR

I want to see only the ones that are IN  the USA,  BUT if there is no USA then select EUR
so the list would end like this

Since there is no John USA,  I want John EUR to show up in the list also.

Results:
001  Donald     USA
004  John       EUR

Thank you
just the processing of the list would change


var n: integer;
 
        // now process the list
        n := found.IndexOf('USA');
        for m := 0 to found.Count-1 do
          if found[m] <> aCountry then
          begin
            if not ((n = -1) and (found[m]) = 'EUR')) then // only hide when no usa and not EUR
              dupetree.isvisible[PVirtualNode(Integer(found.objects[m]))] := false;
          end;

Open in new window

Avatar of pka4916

ASKER

Geert,  you rock!!!!!

this is working perfect,  

I thought I was smart, and I added another country, but that doesn't seem to work correctly.
is this how you suppose to do it?
 
cause it seems to skip some when i add that line

i had to do a  add a label  "donextone"   otherwise it would still process the next line.

I wish i could give you more then 500 points, cause what i couldn't figure out in  the last 7 weeks,  you did in 1 day
n := found.IndexOf('USA');
  for m := 0 to found.Count-1 do
      if found[m] <> aCountry then
          begin
            if not ((n = -1) and (uppercase(found[m]) <> 'EUROPE') and  
                     uppercase(found[m]) = JAPAN'')) then
                     dupetree.isvisible[PVirtualNode(Integer
                        (found.objects[m]))] := false;goto donextone;
 
            if not ((n = -1) and (uppercase(found[m]) = 'EUROPE')) then
            dupetree.isvisible[PVirtualNode(Integer(found.objects
              [m]))] := false;goto donextone;
          end;
 
donextone:
Node1 := dupetree.GetNext(Node1);

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Geert G
Geert G
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
oops typo:
var
  Node1, Node2 : PVirtualNode;
  m, n, o : integer;

Open in new window

Avatar of pka4916

ASKER

Geert, thank you so much for this.   you are a life saver.
Avatar of pka4916

ASKER

Thank you so much for helping me out with this.
I can finally sleep again.