おはようございます。
再びお世話になります。
TStringListにデータを格納していて、LisiViewに表示させたいのですがうまくいきません。
まだまだ未熟で自分ではどうしたらよいかよくわかりませんでした。
TStringListには以下のようにデータが入っています。
aaa
bbb
(一行あき)
ccc
aaa
bbb
(一行あき)
ccc
というかんじでどんどんデータは追加されます。
Form1での処理で格納したデータ(SL)をForm2でListViewに表示したいのですが・・・。 ListViewのLI.Cuptionにaaa(SL[0]・SL[3)を、SubItemsにbbb(SL[1]・SL[4])、Memo1にSL[2]と[7]をというふうにしたくて考えてみましたが、リストのインデックスが範囲を超えていますというエラーが出てしまいました。
自分なりにコードを考えてはみたのですが・・・
やはりループの範囲と「」内のも問題でしょうか・・・・?
すみません、かなりの初心者で・・・(;_;)
見当違いなコードを書いているのかもしれませんが、
ご指導お願いします。
var
LI:TListItem;
i:integer;
begin
SL:=TStringList.Create;
try
SL.LoadFromFile('FileName');
for i:=0 to SL.Count-4 do
begin
LI:=ListView1.Items.Add;
LI.Caption:=SL[i*4];
LI.SubItems.Add(SL[i*4+1]);
Memo1.Text.Add:=SL[i*4+3]
end;
finally
SL.Free;
end;
end;
LIはCreateされていませんし、SLはどこで宣言されているのでしょうか?インデックスが範囲を超えているというのはその通りでしょう。ListView1.Items.Addは何を追加しているのでしょうか?
ループの制御変数 i のカウントアップに伴って
欲しい文字列の位置が計算されているかをまず考えてみてはいかがですか?
コードからするとこんな風になると思います。
i : 0->1->2->3->4
---------------------------
[i*4] : 0->4->8->12->16
[i*4+1]: 1->5->9->13->17
[i*4+3]: 3->7->11->15->19
でもって、SL(StringList)変数の要素数は足りてますか?
> ListView1.Items.Addは何を追加しているのでしょうか?
ListView1に新たなリスト項目(TListItem)を作成・追加しているんだと思いますが。
すみません、説明不足でした。
SLはForm1のpublicで宣言してあります。
それをForm2で使おうと思ってたので、
少し不足していました。
procedure TForm2.FormCreate(Sender: TObject);
var
LI:TListItem;
i:integer;
begin
Form1.SL:=TStringList.Create;
try
Form1.SL.LoadFromFile('FileName');
for i:=0 to Form1.SL.Count-4 do ←Form1でデータがどんどん追加
begin されることになるのですが、
LI:=ListView1.Items.Add; ここの部分に問題ありですか?
LI.Caption:=Form1.SL[i];
LI.SubItems.Add(Form1.SL[i*4+1]);
Memo1.text:=Form1.SL[i*4+3];
end;
finally
Form1.SL.Free;
end;
SL.Countから 4 を差し引いている意味は何でしょうか?
SL.Count=4のとき
i=0, SL[i]=SL[0], sl[i*4+1]=sl[1], sl[i*4+3]=sl[3]
i=1, SL[i]=SL[1], sl[i*4+1]=sl[5](Error), sl[7](Error)
SL.COunt=5のとき
i=0, SL[i]=SL[0], sl[i*4+1]=sl[1], sl[i*4+3]=sl[3]
i=1, SL[i]=SL[1], sl[i*4+1]=sl[5], sl[i*4+3]=sl[7](Error)
SL.COunt=6のとき
i=0, SL[i]=SL[0], sl[i*4+1]=sl[1], sl[i*4+3]=sl[3]
i=1, SL[i]=SL[1], sl[i*4+1]=sl[5], sl[i*4+3]=sl[7](Error)
i=2, SL[i]=SL[2], sl[i*4+1]=sl[9](Error), sl[i*4+3]=sl[11](Error)
となると思います。
Errorのところで、「リストのインデックスが範囲を超えています」がでますよね。
ですので、ロジックに間違いがあるはずです。
SLの要素は、
SL.Count=0の時、空です。
SL.Count>0のとき、SL[0]からSL[SL.Count - 1]までの要素があります。
−4にしたのは−1でエラーがでたので何が原因なのかわからなくて
iの繰り返し回数に問題があるのかと思い減らしてみました・・・。
SL.Countはデータの行数と考えていいんですよね?
あの・・・ロジックていうのはどの部分のことでしょうか・・?
本当に素人で申し訳ありません。
SL.Countはデータの行数です。
たぶん、ロジックの間違いは、ループの回数設定の部分だと思います。
コードから察するに、
一回のループで入力データの4行分を使うようになっていますから、
その4行分を1つのかたまりと考えて、ループの回数を決定する必要があります。
つまり、for i:=0 to (SL.Count div 4)-1 do とすべきではないかと思います。
この場合、当然入力行は4の倍数でなければなりません。
Halbow です。
> あの・・・ロジックていうのはどの部分のことでしょうか・・?
えーと、やりたいことは
> ListViewのLI.Captionにaaa(SL[0]・SL[3)を、SubItemsにbbb(SL[1]・SL[4])、
> Memo1にSL[2]と[7]をというふうにしたくて考えてみましたが
ですね。で、i をインデックスにして巡回するわけですが
> for i:=0 to Form1.SL.Count-4 do ←Form1でデータがどんどん追加
> begin されることになるのですが、
> LI:=ListView1.Items.Add; ここの部分に問題ありですか?
> LI.Caption:=Form1.SL[i];
> LI.SubItems.Add(Form1.SL[i*4+1]);
> Memo1.text:=Form1.SL[i*4+3];
> end;
これだと
i := 0 のとき
LI.Caption -> SL[0]
LI.SubItem -> SL[1]
Memo1.Lines.Add -> SL[3]
i := 1 のとき
LI.Caption -> SL[1]
LI.SubItem -> SL[5]
Memo1.Lines.Add -> SL[7]
となってぜんぜんやりたいことができてませんね。
また、SL.Count が たとえば 10 だとすると、i が 2 のときで SL[i*4+3] は
SL[11] となって、「リストのインデックスが範囲を超えています」がでます。
分かりましたか?
Halbow です。
> ListViewのLI.Captionにaaa(SL[0]・SL[3)を、SubItemsにbbb(SL[1]・SL[4])、
> Memo1にSL[2]と[7]をというふうにしたくて考えてみましたが
これって、単純に i の関数にできないのではないでしょうか。
>> ListViewのLI.Captionにaaa(SL[0]・SL[3)を、SubItemsにbbb(SL[1]・SL[4])、
>> Memo1にSL[2]と[7]をというふうにしたくて考えてみましたが
>これって、単純に i の関数にできないのではないでしょうか。
そうですね。コードとこの考えのどちらを望んでいらっしゃるのでしょうか。
きちんと表示できました!!
ひとかたまりとして表現しなければいけなかったんですね・・・。
とても勉強になりました。
本当にありがとうございました。
Halbow です。
> きちんと表示できました!!
おぉ、そうですか。それはよかったですね。すみませんが for のところだけでも
コードを示してくださいませんか。どのように実現できたか想像できませんのです。
通りすがりさんからの4:50返答をもとに解決できました。
こちらから返事を書いている間にHalbowさんや通りすがりさんからレスを
頂いていたのに申し訳ありません。
うまく質問できていなかったことをお許しください。
ご迷惑おかけしました。
本当にありがとうございました。
わたしも、知りたい。
すみません、遅くなりました。
通りすがりさんがおっしゃられていたことをそのまま使わせていただきました。
あとはこちらのミスで不充分なところがありました。
procedure TForm2.FormCreate(Sender: TObject);
var
LI:TListItem;
i:integer;
begin
Form1.SL:=TStringList.Create;
try
Form1.SL.LoadFromFile('FileName');
for i:=0 to (SL.Count div 4)-1 do
begin
LI:=ListView1.Items.Add;
LI.Caption:=Form1.SL[i*4]; ←*4が抜けていました・・・。
LI.SubItems.Add(Form1.SL[i*4+1]);
Memo1.Lines.Add:=Form1.SL[i*4+3];
end;
finally
Form1.SL.Free;
end;
本当にご迷惑おかけしました。
ありがとうございました。
Halbow です。
コードをありがとうございます。
前にしめしていただいた「やりたいこと」とは違うようですね。
それはともかく、
procedure TForm2.FormCreate(Sender: TObject);
var
LI:TListItem;
i:integer;
begin
Form1.SL:=TStringList.Create;
ここですが、Form1.SL のインスタンスはここでつくられてここではきされていますね。
でしたら、ふつうに
procedure TForm2.FormCreate(Sender: TObject);
var
LI:TListItem;
i:integer;
SL:TStringList; // ローカル変数にする
begin
SL := TStringList.Create;
とするとよいとおもいます。わざわざ Form1 から変数を借りてくる必要は
ありません。
アドバイスありがとうございました。
うまく説明できていなくて本当にすみませんでした・・・。
逆に面倒をおかけしてしまって・・・。
親切に詳しく教えていただいて本当に感謝いたします。
ありがとうございました。
ツイート | ![]() |