• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 400
  • Last Modified:

Search Listview

How do I search a listview for a name? and if not found add a new

so if New is found check New (1) if found check New (2) if not found add New (2)
0
eNarc
Asked:
eNarc
  • 5
  • 4
  • 4
  • +3
3 Solutions
 
jimyXCommented:
Can you clarify more please? How many columns and what is New (1) and New(2)?
If you need to search the first column:
procedure TForm1.Button5Click(Sender: TObject);
var
  i:integer;
  Found:Boolean;
begin
  Found:= False;
  for i:= 0 to ListView1.Items.Count-1 do
    begin
      if ListView1.Items[i].Caption = 'New' then
        begin
          Found:=True;
          break;
        end;
    end;
  if not Found then
    begin
      ListView1.Items.Add;
      ListView1.Items.Item[ListView1.Items.Count-1].Caption := 'New';
    end;
end;

Open in new window

0
 
eNarcAuthor Commented:
its just the caption.


within 1 colomn.


New
New (1)
New (2)



now when I add its gonna be New By Default, I'm needing to search through the list and then put the next number which would be

New (4)

how could I achieve this?
0
 
jimyXCommented:
I think you meant:
If you have:
New
New (1)
New (2)
The next will be:
New (3)
Is that correct?

Also what is the possibility of having different order?

Is it always going to be in this order:
1
2
3
...
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
jimyXCommented:
For example is it possible to have:
New
New (1)
New (2)
New (4)

So when you add new item it will be:
New (3)

Or you always have them in order (i.e. the last item will be the greater)?
0
 
eNarcAuthor Commented:
its just like finding a name that isn't used and using that name. if the name is used then try next number. its like in chrome, you add a photo, if there is a name the same it will use (1) and so on, even like creating folders, using the same way.

any ideas?
0
 
jimyXCommented:
Here you are:
procedure TForm1.Button6Click(Sender: TObject);
var
  i, j:integer;
  Str :String;
begin
  i:=0;
  j:=1;
  Str := 'New';
  while i <=  ListView1.Items.Count-1 do
    begin
      if ListView1.Items.Item[i].Caption = Str then
        begin
          Str := 'New (' + IntToStr(j) +')';
          inc(j);
          i := 0;
          continue;
        end;
      inc(i);
    end;

  ListView1.Items.Add;
  ListView1.Items.Item[ListView1.Items.Count-1].Caption := Str;
end;

Open in new window

0
 
Ephraim WangoyaCommented:

Try this
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, Menus;

type
  TForm3 = class(TForm)
    btnNew: TButton;
    ListView1: TListView;
    btnDelete: TButton;
    procedure btnNewClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    function GetNewItemIndex: Integer;
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

function IntegerSort(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := StrToInt(List[Index1]) - StrToInt(List[Index2]);
end;

procedure TForm3.btnDeleteClick(Sender: TObject);
var
  I: Integer;
begin
  if Assigned(ListView1.Selected) then
  begin
    I := ListView1.Items.IndexOf(ListView1.Selected);
    ListView1.Items.Delete(I);
  end;
end;

procedure TForm3.btnNewClick(Sender: TObject);
var
  NewIndex: Integer;
begin
  NewIndex := GetNewItemIndex;
  with ListView1.Items.Add do
    Caption := 'New(' + IntToStr(NewIndex) + ')';
end;

function TForm3.GetNewItemIndex: Integer;
//just get all item indeces and store in a list, we then sort the list and look for
//gaping holes
var
  I, Index: Integer;
  IndexList: TStringList;
  function ExtractIndex(const ACaption: string): Integer;
  var
    Br1, Br2: Integer;
    Temp: string;
  begin
    Result := -1;
    Br1 := Pos('(', ACaption);
    Br2 := Pos(')', ACaption);
    if (Br1 > 0) and (Br2 > Br1) then
    begin
      Temp := Copy(ACaption, Br1+1, Br2-Br1-1);
      Result := StrToIntDef(Temp, -1);
    end;
  end;
begin
  Result := -1;
  if ListView1.Items.Count = 0 then
  begin
    Result := 1;
    Exit;
  end;

  IndexList := TStringList.Create;
  ListView1.Items.BeginUpdate;
  try
    IndexList.Add('0');
    for I := 0 to ListView1.Items.Count - 1 do
    begin
      Index := ExtractIndex(ListView1.Items[I].Caption);
      if Index > 0 then
        IndexList.Add(IntToStr(Index));
    end;
    IndexList.CustomSort(IntegerSort);

    for I := 0 to IndexList.Count - 2 do
      if (StrToInt(IndexList[I]) +1 <> StrToInt(IndexList[I+1])) then
      begin
        Result := StrToInt(IndexList[I]) + 1;
        Break;
      end;

    if Result < 0 then
      Result := IndexList.Count;
  finally
    ListView1.Items.EndUpdate;
    IndexList.Free;
  end;
end;

end.

Open in new window

0
 
Snip3rXCommented:
Hello Experts,
hope this what u mean:
procedure TForm1.Button1Click(Sender: TObject);
var LItem   : TListItem;
    i, Count: Integer;
    tmp, Name: String;
begin
  Count:=0;
  For i:=0 To ListView1.Items.Count-1 Do
  Begin
    tmp := ListView1.Items.Item[i].Caption;
    If tmp = 'New' Then Count:=1;
    If Length(tmp)>=5 Then
    If StrToInt(Copy(tmp, 5, Length(tmp))) = Count Then
    Count := StrToInt(Copy(tmp, 5, Length(tmp)))+1;
  End;
  If Count=0 Then Name:= 'New'
  Else Name:= 'New ' + IntToStr(Count);
  LItem := ListView1.Items.Add;
  LItem.Caption := Name;
end;

Open in new window

Sn!per X
Search-ListView---Delphi--SRC-.zip
0
 
jimyXCommented:
The code I provided in post #35497251 answers the question and does exactly what the Author has requested.
0
 
Ephraim WangoyaCommented:

@jimmyX

You are continually modifying the search string for no reason. And your code assumes there is a proper order of the items.

Str := 'New (' + IntToStr(j) +')';
         
That is not the right way to do it at least not if the answer is to used for later reference.

You only need to find the missing index once and construct the entry regardless of the item orders
0
 
mlmccCommented:
Actually the code is correct.

It starts looking for "New" in the list.  If found you now have to see if "New(1)" is in the list and so on until you find either "New: is not used or the first n such that "New(n)" is not used.

mlmcc
0
 
Snip3rXCommented:
@ewangoya

Your code is long and its need to involve TStringList!!
The Code i provided short, and does not need to create StringList! & Solved the question,

Anyway, i dont think deleting the question is good, because i think the question is already answered
from all the comments above, so if there is no Points Spliting, so i suggest to give the points to jimyX because he was the faster.
0
 
Ephraim WangoyaCommented:
@Snip3rX
1. Its not how fast yo answer a question and it does not matter whether the code is long or not. Sometimes when you optimize stuff, you may end up with long code (I'm not saying my code is optimized)
2. Your code does not work at all, If you run it, you get an integer conversion error

@jimmyX
Sorry, your actually does work. Here is the problem with your code which made me think it did not work to begin with

  while i <=  ListView1.Items.Count-1 do
  begin
    if ListView1.Items.Item[].Caption = Str then
    begin
      Str := 'New (' + IntToStr(j) +')';
      inc(j);
      i := 0;  //you are actually changing the value of the loop control variable within the loop
      continue;
    end;
    ...............

Personally, I don't condone such code but I must say that it works. If its good for the asker, then that's fine, I have no problem with that at all

cheers
0
 
systanCommented:
there are many ways to cook, be sure the ingredients are not rotten and the food is not raw. ;)
0
 
mlmccCommented:
In a WHILE loop you have to change the value of the loop control variable otherwise you will be in an infinite loop.

He is changing it so the loop essentially restarts but that is because when j is incremented you have to search from the beginning of the list again since there is no guarantee the list is any specific order.

mlmcc
0
 
Ephraim WangoyaCommented:

I was not very clear with what I said. The variable definitely has to be incremented.

I'm pointing to the fact that the variable is reset to the start value within the loop its controlling.
0
 
mlmccCommented:
True and to restart the search through the list you have to reset it when you find the one you want
Consider this list

New(1)
New
New(2)
New(4)
New(3)

If after finding New you just contiinue the list looking for New(1) it won't be found but it does exist as the first element in the list.  Thus the list index must get reset so the search can start back at the beginning of the list.

If the list were to be ordered in ascending value there would be no need to reset the index because it wouldn't be in the earlier part of the list.  Since there is no guarantee the list is sorted in any order the loop control must be reset.

mlmcc
0
 
mlmccCommented:
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 5
  • 4
  • 4
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now