TStringListのデータをListViewに表示するには?

解決


デコデコ  2003-12-11 15:53:55  No: 6047

おはようございます。
再びお世話になります。

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;


HOota  2003-12-11 16:37:57  No: 6048

LIはCreateされていませんし、SLはどこで宣言されているのでしょうか?インデックスが範囲を超えているというのはその通りでしょう。ListView1.Items.Addは何を追加しているのでしょうか?


通りすがり  2003-12-11 17:36:51  No: 6049

ループの制御変数 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)変数の要素数は足りてますか?


通りすがり  2003-12-11 18:10:18  No: 6050

> ListView1.Items.Addは何を追加しているのでしょうか?
ListView1に新たなリスト項目(TListItem)を作成・追加しているんだと思いますが。


デコデコ  2003-12-11 21:42:18  No: 6051

すみません、説明不足でした。
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;


通りすがり  2003-12-11 21:58:10  No: 6052

SL.Countから 4 を差し引いている意味は何でしょうか?


にしの  2003-12-11 22:07:48  No: 6053

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]までの要素があります。


デコデコ  2003-12-12 01:39:23  No: 6054

−4にしたのは−1でエラーがでたので何が原因なのかわからなくて
iの繰り返し回数に問題があるのかと思い減らしてみました・・・。
SL.Countはデータの行数と考えていいんですよね?

あの・・・ロジックていうのはどの部分のことでしょうか・・?

本当に素人で申し訳ありません。


通りすがり  2003-12-12 01:50:11  No: 6055

SL.Countはデータの行数です。

たぶん、ロジックの間違いは、ループの回数設定の部分だと思います。
コードから察するに、
一回のループで入力データの4行分を使うようになっていますから、
その4行分を1つのかたまりと考えて、ループの回数を決定する必要があります。
つまり、for i:=0 to (SL.Count div 4)-1 do とすべきではないかと思います。
この場合、当然入力行は4の倍数でなければなりません。


Halbow  2003-12-12 01:57:02  No: 6056

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  2003-12-12 02:07:35  No: 6057

Halbow です。

> ListViewのLI.Captionにaaa(SL[0]・SL[3)を、SubItemsにbbb(SL[1]・SL[4])、
> Memo1にSL[2]と[7]をというふうにしたくて考えてみましたが

これって、単純に i の関数にできないのではないでしょうか。


通りすがり  2003-12-12 02:14:33  No: 6058

>> ListViewのLI.Captionにaaa(SL[0]・SL[3)を、SubItemsにbbb(SL[1]・SL[4])、
>> Memo1にSL[2]と[7]をというふうにしたくて考えてみましたが
>これって、単純に i の関数にできないのではないでしょうか。
そうですね。コードとこの考えのどちらを望んでいらっしゃるのでしょうか。


デコデコ  2003-12-12 02:18:07  No: 6059

きちんと表示できました!!
ひとかたまりとして表現しなければいけなかったんですね・・・。
とても勉強になりました。

本当にありがとうございました。


Halbow  2003-12-12 02:23:59  No: 6060

Halbow です。

> きちんと表示できました!!

おぉ、そうですか。それはよかったですね。すみませんが  for のところだけでも
コードを示してくださいませんか。どのように実現できたか想像できませんのです。


デコデコ  2003-12-12 02:25:04  No: 6061

通りすがりさんからの4:50返答をもとに解決できました。
こちらから返事を書いている間にHalbowさんや通りすがりさんからレスを
頂いていたのに申し訳ありません。
うまく質問できていなかったことをお許しください。
ご迷惑おかけしました。
本当にありがとうございました。


通りすがり  2003-12-12 02:25:45  No: 6062

わたしも、知りたい。


デコデコ  2003-12-12 03:57:04  No: 6063

すみません、遅くなりました。
通りすがりさんがおっしゃられていたことをそのまま使わせていただきました。
あとはこちらのミスで不充分なところがありました。

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  2003-12-12 04:24:24  No: 6064

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 から変数を借りてくる必要は
ありません。


デコデコ  2003-12-12 04:48:16  No: 6065

アドバイスありがとうございました。

うまく説明できていなくて本当にすみませんでした・・・。
逆に面倒をおかけしてしまって・・・。

親切に詳しく教えていただいて本当に感謝いたします。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加