- ベストアンサー
リストボックスでの選択項目分削除について。
こんばんは。 リストボックスでのマルチセレクトで選択した項目を削除する 方法で悩んでいます。 (リストボックスで3項目選択したとして、この3項目を削除する方法) 解答は現在勉強している本に掲載されているのですが意味が分からず。 解答のコードの方にはリストを後ろから削除しているみたいなのですが、 前から削除しても大丈夫だと思いやってみましたが、エラーが出てしまいます。 解説には、先頭から削除するとその時点でリストのインデックス値がずれて しまう。と書いてあるのですが、後ろから削除しても一緒だと考えこんでいます。 解答コード ********************************************************** Private Sub Command2_Click() Dim i As Integer '選択状態(Selected=true)の項目だけ削除 For i = List1.ListCount - 1 To 0 Step -1 If List1.Selected(i) = True Then List1.RemoveItem i End If Next i End Sub ********************************************************* と言う解答コードを自分は、前から削除するように 自分なりのコード ********************************************************* Private Sub Command2_Click() Dim i As Integer For i = 0 To listcount-1 If List1.Selected(i) = True Then List1.RemoveItem i End If Next i End Sub ************************************************************* で作成してみましたが、やっぱりエラーが。 なぜ、前から削除するとエラーになってしまうのか、 もう少し具体的に教えてくれると助かります。 よろしくお願いします。m(__)m
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
こんにちわ。 コードの処理に沿って順番に説明しますね。 リストの内容はA~Eの5個あり、BとDを選択した状態だとします。 *リストの内容** 1|A 2|B ←選択 3|C 4|D ←選択 5|E ************** これを解答コードのように後ろから削除する場合、5から1まで繰り返し判定するわけですが、 1回目(5):Eは選択されていませんので何もしません。 2回目(4):Dが選択されているので削除します。 *リストの内容** 1|A 2|B ←選択 3|C 4|E ************** 3回目(3):Cは選択されていませんので何もしません。 4回目(2):Bが選択されているので削除します。 *リストの内容** 1|A 2|C 3|E ************** 5回目(1):Aは選択されていませんので何もしません。 結果、以下のようなリストになり正常に動作します。 *リストの内容** 1|A 2|C 3|E ************** 同じ様にmineral01さんのコードのように前から削除する場合、 1回目(1):Aは選択されていませんので何もしません。 2回目(2):Bが選択されているので削除します。 *リストの内容** 1|A 2|C 3|D ←選択 4|E ************** 3回目(3):Dが選択されているので削除します。 (この時点でインデックスがずれているためCの判定が飛ばされてしまいます。) *リストの内容** 1|A 2|C 3|E ************** 4回目(4):4番目の要素が無いためエラーになります。 この段階ではもうリストの内容が3つしかないために、4番目の内容を取得しようとするとインデックスエラーとなってしまいます。 どうしても前から削除したい場合は、以下のコードで大丈夫だと思います。 mineral01さんのコードに追記してみました。 ********************************************************* Private Sub Command2_Click() Dim i As Integer For i = 0 To List1.listcount - 1 If List1.Selected(i) = True Then List1.RemoveItem i i = i - 1 End If If i >= List1.ListCount - 1 Then Exit For End If Next i End Sub ************************************************************* 長文なってしまい、申し訳無いです。参考になれれば幸いです。
その他の回答 (4)
- BlueRay
- ベストアンサー率45% (204/453)
BlueRayです。少しばかり追加解説です。 ダルマA 順|○| 1|A| 2|B| 3|C| 4|D| 5|E| リストの順番は、下から1,2,3,4,5です。 そして、ダルマが一番最後を表しています。
- BlueRay
- ベストアンサー率45% (204/453)
ダルマ落しで表現しますね。○をダルマでと思ってください(^^; ダルマA ダルマB 順|○| 順|○| 1|A| 5|A| 2|B| 4|B| 3|C| 3|C| 4|D| 2|D| 5|E| 1|E| 解答コードがダルマAで、mineral01さんのコードがダルマBです。 順と書いてある通りに崩していきます。 では、参考までに1番目を崩してみましょう。 ダルマA ダルマB 順 順 1|○| 5|○| 2|B| 4|A| 3|C| 3|B| 4|D| 2|C| 5|E| 1|D| 次に2番目を崩してみましょう。 ダルマA ダルマB 順 順 1 5 2|○| 4|○| 3|C| 3|A| 4|D| 2|B| 5|E| 1|D| 以下5番目まで崩して、ダルマを一番下に落とすことが出来るのはどちらですか。 明らかにダルマAですね。ダルマBは4回目で何も出来ないですね。 連続項目削除は、この様に最後までダルマを落とせる様にしなくてはいけないんです。 わかりにくかったら、補足してください。ではでは。
お礼
説明ありがとうございます。 皆様の説明で、理解するとことができました。 かなり悩んでいたので、本当に助かりました。 ありがとうございます。
- maruru01
- ベストアンサー率51% (1179/2272)
こんにちは。maruru01です。 リストを1つ削除すると、その度にそれより後ろ(Indexが大きいもの)のIndexが変更(1つずつ繰り上がる)されてしまうからです。 前(Indexの小さい方)から削除すると、後ろの削除対象のリストのIndexが変更(1つ繰り上がる)されるので、選択したものと別のものを削除したり、エラーになったりします。 後ろ(Indexの大きい方)から削除すれば、その後ろのIndexが変更されても構わないわけです。(削除対象が前(Indexが小さい方)にしかないので。) では。
お礼
後ろから削除することによって、削除対象が小さい方にしかないので、 全て効率よく(index値をずれなくして)削除できるんですね。 また、後ろからだと比較したインデックスが変更されても大丈夫と言うことが 分かりました。 説明、本当にありがとうございました。m(__)m
- imogasi
- ベストアンサー率27% (4737/17069)
下記の「繰り上がりがあるときの」ロジックを考えてみられては。 下記(2)の下からの繰り上がりを考えに入れてないのでは。(下記でdeleteとかA(i)としているのは仮想の表現で、リストの場合RemoveItemです。セルの削除等の場合も念頭に入れているため) 5つアイテムがあったとして、 (1)後ろ(下と言いますか)から、3つ削除するときは、 上から5番目削除、次に上から4番目削除、次に上から3番目削除・・となります。iは5,4,3・・・です。 for i=5 to 3 step -1 a(i).delete next i (2)先(上と言いますか)から、3つ削除する時は、 まず上から1番目削除、「下から繰り上がってくるので」、2番が1番に繰り上がってくるので、次も1番を削除すればよい。次も同じ。 for i=1 to 3 a(1).delete next i
お礼
説明ありがとうございました。 プログラミングの奥の深さを新ためて実感しました。 まだまだ、勉強不足です。 本当にありがとうございました。m(__)m
お礼
hersheさん、とても理解しやすい説明ありがとうございます。 おかげさまで理解できました。 リストを前から、判定してしまうと、 インデックス値(iの値)がずれてしまったために 判定処理が飛ばされてしまうんですね。 リストに最後の値がないにもかかわらず、リストの内容を取得しようとして いるためにエラーが出ることがとても理解できました。 後ろから判定をすると全ての値を効率よく(インデックス値をずらすことなく)、 判定できるんですね。 また、前からの処理での削除方法ありがとうございます。 本当に勉強になりました。 iの値を引いてあげる点と、現時点でのインデックス値(iの値)を判定して あげる処理がポイントだと分かりました。 本当に、分かりやすい説明ありがとうございました。m(__)m