New2Delphi
asked on
StringList Problem! Please help!
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(DelInde x));
end;
end;
Items.Delete(Items.IndexOf (Del));
end;
Del:= ListView1.GetNextItem(nil, sdAll, [isSelected]);
end;
S.SaveToFile(SaveDir + 'Tools.txt');
S.Free;
end;
procedure TForm1.Button1Click(Sender
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(DelInde
end;
end;
Items.Delete(Items.IndexOf
end;
Del:= ListView1.GetNextItem(nil,
end;
S.SaveToFile(SaveDir + 'Tools.txt');
S.Free;
end;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
or do it from bottom:
for i := S.Count - 1 downto 0 do
S.Delete(i);
for i := S.Count - 1 downto 0 do
S.Delete(i);
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+fiena me)
// loop here
end;
S.Free;
end;
Dragon is right, loop backwards.
procedure
var .....
begin
if filexists(savedir+fiename)
begin
loadfromfile(savedir+fiena
// loop here
end;
S.Free;
end;
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).
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).
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
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
Selected.Subitems.count must be equal to S.Count ( at least )
ASKER
Hmmm... what if I want to edit a string in the list? What procedure should I use?
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;
...
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;
...
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 ;-)
what is ur idea about my last comment? do u agree with me?
hamed ;-)
ASKER
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!
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!
ASKER
Please help me.
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(DelInde x));
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
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(DelInde
ExitCode := False;
break;
end;
end; // for
end; // while
Items.Delete(Items.IndexOf
end;
Del:= ListView1.GetNextItem(nil,
end;
after each delete i refresh the for loop
best regards
hamed
New2Delphi , are you here. Could last code solve your problem ? ;-)
ASKER
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!
data from there, and then update the TStringList. Is this possible? Can you please post sample code
for this. Thanks!
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(DelInde x));
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
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
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(DelInde
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
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
best regards
hamed
ASKER
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!
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
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!
ASKER
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!
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
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!
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
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
ASKER
Yes! That is exactly my problem. Can you help me?
S.SaveToFile(FileName);
oh, he was so faster than me .like Loadfromfile you can use Savetofile.
best regards
hamed
best regards
hamed
ASKER
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?
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?
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.
ASKER
What if it's S.Strings[i] since I do not know for sure what the index is?
e.g.
Edit1.Text := S.Strings[i];
// some editing
// value of i did not change
S.Strings[i] := Edit1.Text
will be fine
Edit1.Text := S.Strings[i];
// some editing
// value of i did not change
S.Strings[i] := Edit1.Text
will be fine
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
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
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
Best regards
Hamed
ASKER
I'll post the results tomorrow. :-)
ok! ;-) but witch results? do you talk about your code ? , your profile ? or ... ? :-)
good coding
hamed
good coding
hamed
ASKER
Yes, the code I use.
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
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
"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.