Filter / Sorting with VirtualTree from Soft-Gems

pka4916
pka4916 used Ask the Experts™
on
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

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Geert GOracle dba
Top Expert 2009

Commented:
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

Author

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

found.AddObject(my1.country, Node1);

imcompatible types   Tobject and TvirtualNode

Author

Commented:
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.  
Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

Geert GOracle dba
Top Expert 2009

Commented:
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

Author

Commented:
?  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



Author

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

Geert GOracle dba
Top Expert 2009

Commented:
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

Author

Commented:
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
Geert GOracle dba
Top Expert 2009

Commented:
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

Author

Commented:
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

Oracle dba
Top Expert 2009
Commented:
a label ?
ooo ... try and avoid that, this is only for backward compatibity and makes it hard to follow the flow of the code
it can all be written without a label

let's assume you have list of alternative countries ...
and the country you want

so you first show all for the country you want
and then if not found, the first country from the alts list in the order they are added
procedure TForm1.FilterCountry(aCountry: string);
var
  Node1, Node2 : PVirtualNode;
  m : integer;
  my1 : PdupeTreeData;
  my2 : PdupeTreeData;
  found, alts: TStringList;
begin 
  aCountry := UpperCase(aCountry);
  dupetree.beginupdate;
  try
    alts := TStringList.Create;
    try
      alts.Add('EUROPE');
      alts.Add('JAPAN');
      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(UpperCase(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(UpperCase(my2.country), TObject(Integer(Node2)));
            Node2 := dupetree.GetNext(Node2);
          end;
          // now process the list
          n := found.IndexOf(aCountry);
          o := -1; // index of first country
          // if non us find first alts country
          if n = -1 then  
            for m := 0 to alts.Count-1 do
            begin
              o := found.IndexOf(alts[m]);
              if o <> -1 then  // found !
                Break;
            end;
          // now hide everything for not country and not first alt country
          for m := 0 to found.Count-1 do
            if (m <> n) and (m <> o) then
              dupetree.isvisible[PVirtualNode(Integer(found.objects[m]))] := false;
          Node1 := dupetree.GetNext(Node1);
        end;
      finally
        found.Free;
      end;
    finally
      alts.Free;
    end;
  finally
    dupetree.Endupdate;
  end;
end;

Open in new window

Geert GOracle dba
Top Expert 2009

Commented:
oops typo:
var
  Node1, Node2 : PVirtualNode;
  m, n, o : integer;

Open in new window

Author

Commented:
Geert, thank you so much for this.   you are a life saver.

Author

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

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial