Solved

StringList Problem! Please help!

Posted on 2001-07-23
34
353 Views
Last Modified: 2010-04-06
Hi! I seem to have a problem with the following code. I always get an "Out of Bounds" error. I don't know why it does that. Can someone help me out. Thanks!

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  S: TStringList;
  Del: TListItem;
  DelIndex: String;
begin
  if ListView1.Selected = nil then
    Exit;

  S := TStringList.Create;
  Del:= ListView1.Selected;

  try
    S.LoadFromFile(SaveDir + 'Tools.txt');
  except
    S.Free;
    Exit;
  end;

  while Del <> nil do
    begin
      with ListView1 do
        begin
          for i := 0 to S.Count - 1 do
            begin
              if S.Strings[i] = (Selected.Caption + '=' + Selected.SubItems[i]) then
                begin
                  DelIndex := S.Strings[i];
                  S.Delete(S.IndexOf(DelIndex));
                end;
            end;

          Items.Delete(Items.IndexOf(Del));
        end;

      Del:= ListView1.GetNextItem(nil, sdAll, [isSelected]);
    end;

  S.SaveToFile(SaveDir + 'Tools.txt');
  S.Free;
end;
0
Comment
Question by:New2Delphi
  • 12
  • 11
  • 5
  • +3
34 Comments
 
LVL 5

Expert Comment

by:scrapdog
ID: 6310630
You are iterating through the StringList and deleting items from it in the same loop.

"S.Count - 1" in the for loop is evaluated at the beginning of the loop, not for every iteration.

If you want to reevaluate on every iteration (because S.Count changes after a delete), then use a "while" loop instead of a for loop.
0
 
LVL 5

Accepted Solution

by:
scrapdog earned 30 total points
ID: 6310638
i := 0;
while (i < S.Count) do
begin
    if S.Strings[i] = (Selected.Caption + '=' + Selected.SubItems[i]) then
    begin
        DelIndex := S.Strings[i];
        S.Delete(S.IndexOf(DelIndex));
    end;
    Inc(i);
end;
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6310655
or do it from bottom:

for i := S.Count - 1 downto 0 do
  S.Delete(i);

0
 

Expert Comment

by:d32coder
ID: 6310914
You should also only have S.Free; in one place (at the end).  This will help prevent an access to a stringlist that no longer exists.  

Dragon is right, loop backwards.



procedure
var .....
begin

if filexists(savedir+fiename) then
 begin
 loadfromfile(savedir+fiename)
 
 // loop here

 end;
 
 S.Free;
end;
0
 
LVL 5

Expert Comment

by:scrapdog
ID: 6310933
As long as we're talking about S.Free

try
   S.LoadFromFile(SaveDir + 'Tools.txt');
 except
   S.Free;
   Exit;
 end;


You should probably use try..finally instead of try..except.  Place the "try" before the S.LoadFromFile, and the "finally" right after S.SaveToFile.

It is not a good idea to call Exit in an exception handler;  it is better to call "raise".  (You wouldn't need to do that when you use finally).
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6311312
hello,

i think error msg ( index out of bound ) is not for <S> ( as a StringList ) . it is for <Selected.SubItems[i]>. ( although it can be for S , if just tools.txt was empty ).

this becouse of that the selected Item has not a SubItem. if the selected item has it . there is not eny error msg!

that is better he write :

if Selected.SubItems.Count <> 0 then
...
...
...

best regards
hamed
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6311326
Selected.Subitems.count must be equal to S.Count ( at least )
0
 

Author Comment

by:New2Delphi
ID: 6320729
Hmmm... what if I want to edit a string in the list? What procedure should I use?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6320841
You mean string in the StringList?

e.g. You want to change value for String #3:

var
  MyString: string;
begin
  MyString := StringList.Strings[2];
  if InputQuery('StringList', 'Enter new value',
    MyString) then
    StringList.Strings[2] := MyString;
...



0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6321159
Edit a String at StringList or Edit(add) a child as Subitem? although there is not so difference.(i think DragonSlayer comment is good)

what is ur idea about my last comment? do u agree with me?

hamed ;-)
0
 

Author Comment

by:New2Delphi
ID: 6324896
DragonSlayer's comment about doing it from bottom worked fine.

Now I have a problem with editing. See what my program does is take website addresses from a textfile, load it into a TStringList and then load the data into a TListView. Now if I want to edit, add or delete it, I just go back to the StringList and do the neccessary function on it. The code I posted was the function to delete an item from the TStringList. It compares the item in the TStringList with the selected item of the TListView and if they are the same, it deletes it from the TStringList and TListView. Also, the code I posted had a typo. Selected.SubItems[i] should be Selected.SubItems[0] since I only have one sub-item.

Anyway, when editing, what I want to do is load the item from my TListView onto 2 Edit boxes, edit the data from there, and then update the TStringList. Is this possible? Can you please post sample code for this. Thanks!
0
 

Author Comment

by:New2Delphi
ID: 6328645
Please help me.
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6329524
I think I found your mistake :

when u delete one string from S then Count decrese one, there fore u must refresh the for loop ( becouse if u not i passes end of Items of S )

now this is the corrected code :

 while Del <> nil do
   begin
     with ListView1 do
       begin
        ExitCode := False;

         while not Exitcode do
         begin
         ExitCode := True;
         for i := 0 to S.Count - 1 do
           begin
             if S.Strings[i] = (Selected.Caption + '=' + Selected.SubItems[0]) then
               begin
                 DelIndex := S.Strings[i];
                 S.Delete(S.IndexOf(DelIndex));
                 ExitCode := False;
                 break;
               end;
           end; // for
         end; // while

         Items.Delete(Items.IndexOf(Del));
       end;

     Del:= ListView1.GetNextItem(nil, sdAll, [isSelected]);
   end;

after each delete i refresh the for loop

best regards
hamed
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6331794
New2Delphi , are you here. Could last code solve your problem ? ;-)
0
 

Author Comment

by:New2Delphi
ID: 6336843
Hi! When editing, what I want to do is load the selected item from my TListView onto 2 Edit boxes, edit the
data from there, and then update the TStringList. Is this possible? Can you please post sample code
for this. Thanks!
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6337163
hi New2Delphi , how are you?

lets do step by step ( I am not shur i understand exactly that u want ) :

1. u want load selected item from TListView to 2 Edit Boxes.

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Caption;

i think u mean u want to load subitem to another EditBox.then :

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Selected.SubItems[0];

2.now you can Edit them in Edit Boxes

3.at the end you want to Update your TStringList ( I guess you mean <S> witch is a TStringList ):


if S.Strings[i] = (Edit1.Text + '=' + Edit2.Text) then
              begin
                DelIndex := S.Strings[i];
                S.Delete(S.IndexOf(DelIndex));
                ExitCode := False;
                break;
              end;
         

I think your goal is stile not so clear for me. is that 3 step usefull your u.

I think that is better we use a real time communication . chat is a good way but i have not ICQ. just I have Yahoomessanger in my computer . also i have not ID in that ( Yaho... used by my brother and he is not here know ) if you know a easy chat room ( that means we dont need any package for use it ) please tell me . we will design the time and will use that chatroom.

i think by chat room you can find your need very rapidly.

also other experts can attach us on that chat room.

best regards
hamed

















sorry, but i can not understand what u say! please tell me clearer. lets do step by step.

1. can it solve your last problem. that means is it stile related to that error message or not ?

2. if it is a new problem please repeat the question. with code and exactly point to line that you have problem!

3. I can not see where is your editing code! in your last codes.

best regards
hamed

0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6337167
the text in the end is the last version of my comment. i wanted to send it becouse i can not understand what is your need. but read it again and write my main comment that you can read in start.

best regards
hamed
0
 

Author Comment

by:New2Delphi
ID: 6339162
hamed, sorry if I don't make any sense. Anyway, deleting from the StringList is not a problem anymore. My problem is editing a string from the StringList. I do not have sample code because I don't know if this is possible.

What my program does is load the contents of the StringList to a ListView. When I want to edit a string I load it from the ListView into 2 edit boxes:

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Selected.SubItems[0];

And then I edit it as necessary. Now, when I click on the "Save" button what I want to do is save the edited string back to the StringList so that the old string will be replaced with the edited one? Can this be done? Can you post code that will allow me to do this? Thanks!
0
 

Author Comment

by:New2Delphi
ID: 6339189
hamed, sorry if I don't make any sense. Anyway, deleting from the StringList is not a problem anymore. My problem is editing a string from the StringList. I do not have sample code because I don't know if this is possible.

What my program does is load the contents of the StringList to a ListView. When I want to edit a string I load it from the ListView into 2 edit boxes:

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Selected.SubItems[0];

And then I edit it as necessary. Now, when I click on the "Save" button what I want to do is save the edited string back to the StringList so that the old string will be replaced with the edited one? Can this be done? Can you post code that will allow me to do this? Thanks!
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6339469
is it mean you want to save S ( as StringList ) to the original txt file ?

that means :

1. you load S from txt file
2. Edit S ( as StringList ) in any way that u want
3. restore S to txt file by save button

now u can do step 1, and step 2. is ur problem to do step 3. that mean u want to know how u can store again the Updated S to the txt file?

best regards
hamed
0
 

Author Comment

by:New2Delphi
ID: 6339620
Yes! That is exactly my problem. Can you help me?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6339813
S.SaveToFile(FileName);
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6340949
oh, he was so faster than me .like Loadfromfile you can use Savetofile.

best regards
hamed
0
 

Author Comment

by:New2Delphi
ID: 6343059
Yes, I know you have to save it to file. What I want to know is if the edited string will be saved with the same index number and if not, can you specify waht code I can use to do so. Thanks!

e.g.

If the original string is Test12=1234567 with an index of 3 and I change it to Test13=4567890 if I save it will it still be in the same index number?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6343123
if you changed it using S.Strings[3] := 'Test13=4567890' then it will be saved with the same index number, IF you did not sort it.
0
 

Author Comment

by:New2Delphi
ID: 6343363
What if it's S.Strings[i] since I do not know for sure what the index is?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6343496
e.g.

Edit1.Text := S.Strings[i];
// some editing
// value of i did not change
S.Strings[i] := Edit1.Text

will be fine
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6345244
i am stile mixture! ;-) the savetofile method save S in .txt file in the same order of its item . now do you wont for example save .txt file with sorted form? like this
Test1 = ...
Test2 = ...
Test3 = ...
Test4 = ...
..
.

after change. if u want it . you must at first Set S before saveing and when S updated in your need form you can use savetofile.

if it is your problem i think you can use sort Items in S. or somthing like this!

if i am still in wrong way please tell me ! dont worry about our time we are here to help each other .

best regards
hamed
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6353790
New2Delphi,what was happened? ;-) maybe you become tired becouse we can not understand all your your problems  exactly! :-( . if you want send me your App, email address : h_mohsenian@yahoo.com & mohsenianrad@scribe.com and discribe your problem with code. also if you want tell me more about yourself . I saw your profile , but there were not any thing about you!

Best regards
Hamed
0
 

Author Comment

by:New2Delphi
ID: 6362556
I'll post the results tomorrow. :-)
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6362726
ok! ;-) but witch results? do you talk about your code ? , your profile ? or ... ?  :-)

good coding
hamed
0
 

Author Comment

by:New2Delphi
ID: 6367317
Yes, the code I use.
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 8711400
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Accept scrapdog's comment as answer

Note:
This recommendation is based on the "original" question asked, and the points offered does not warrant a split. My apologies to the other experts.

Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Thank you,
Russell

EE Cleanup Volunteer
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now