Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


17049 / 76732 ←次へ | 前へ→

【65143】Re:リストボックスでの履歴表示について
発言  kanabun  - 10/4/19(月) 1:56 -

引用なし
パスワード
   ▼のだめ さん:
>しかし何故?という部分が勉強も兼ねて知りたいので
>rirekiの不具合というのを教えていただければ嬉しいです。
>
>rireki_clickの
>cells(行,12) = rireki.value
>がおかしいのですが
>(activecell.value = rireki.valueでもおかしい)
>何故か一つ前の選択セル値が代入され
>選択したものが二つ新たに重複して追加されます。
>
>この原因を究明したいのでお力を貸していただければ幸いです。


それは Step実行してみれば分かります。
新規Bookを作成し、その「Sheet2」の[L3]以降に
以下のようなSourceList があったとします。
L3  Jan
L4  Feb
L5  Mar
L6  Apr
L7  May
L8  Jun
L9  Jul
L10 Aug
L11 Sep
L12 Oct

UserFormから値を選んで代入するシートは このリストのあるSheet2 ではないので
このままではデバッグしにくいので、Sheet1の [L3]以降に Sheet2のL列を
参照する数式を埋め込みます。
L3: =Sheet2!L3
のように。

また、Sub rireki_Click() 内のコードを 以下のように簡単化します。
変更点
(1)Public変数 「行」を使わず、アクティブセルへの代入とする。(ダブル
  クリックされたセルが J列の5行目以降という判定は ダブルクリックさ
  れたシートのほうですでにやっているので )
(2)リストボックス rirekiの何行目がClickされたかは 一行づつシートの
  RowSourceを調べなくても、ListBox の何行目がClickされたか
  すなわち rireki.ListIndex から分かる。これを ClickRow とする。
(3)ClickRowから2行目まで セルをひとつづつ下方へシフトするのは
  For 〜 Next Loop のほうが速いし読みやすい。

これでも、同じ不具合が発生します。

Private Sub rireki_Click()
  Dim ClickRow As Long
  Debug.Print rireki.Value; rireki.ListIndex
  ActiveCell.Value = rireki.Value '<-- ●この行にブレークポイント
  
  ClickRow = rireki.ListIndex + 1 'リストの元データ範囲内の行Index
  Dim i As Long
  Dim r As Range
  Set r = WS2.Range("L3").Resize(10)
  For i = ClickRow To 2 Step -1
    'ひとつ上のセル値をCopy
    r.Item(i).Value = r.Item(i - 1).Value '▲セルの値を変更
  Next
  r.Item(1).Value = rireki.Value
  
  'Me.Hide
End Sub

最初の行↓
  Debug.Print rireki.Value; rireki.ListIndex
に、ブレークポイントを置いて、
シートSheet1 のJ列でダブルクリックして、rirekiリストの 「Apr」を
Clickしてみます。
rireki リストから 4つめの「Apr」を選ぶと、
ダブルクリックしたセルに「Apr」を代入して、
プログラムの実行は一時停止します。
これ以降は [F8]キーで 一行づつStep実行していきます。
そうすると
>    'ひとつ上のセル値をCopy
>    r.Item(i).Value = r.Item(i - 1).Value '▲セルの値を変更
のところで、L列が
RowSource範囲の
1行目  Jan
2:   Feb
3:   Mar
4:   Mar  <------ 上のデータがCopyされる
5:   May
6:   Jun
   ・・・
のように、4行目の値が変わった途端、プログラムの実行は

> Private Sub rireki_Click()
に戻っていることが分かります。
これは RowSourceのリンク先のシートのセルの値が変わったので、
また新たなClickイベントが発生したということです。

ブレークポイントでStopしたとき
2回目のときの rireki.Value は「Mar」になっています。
プログラムでそうしたからです。
>  r.Item(i).Value = r.Item(i - 1).Value '▲セルの値を変更

2回目の時のFor〜Next Loop による セル値のシフトは
2行目までうまく行きます。これはListIndexが3 で、その
ListIndexに対応するセルの値に今度は変更が無く
「Mar」のままだからです。
で、プロシージャ最後の
RowSource範囲の1行目にrireki.Valueを代入して
>  r.Item(1).Value = rireki.Value
一旦終了するかのように見えます。
1: Mar
2: Jan
3: Feb
4: Mar
5: May
・・・

ところが、不思議なことに、Hideした後にも
3度目のイベントが発生して、プログラムの実行は
プロシージャの振り出しに戻って実行が続きます。
これはどうしてかというと、(たぶん) 「Mar」という
リスト項目があるListIndex が 3から 0(先頭)へ
移動したためです。2回目の時は ListIndex=3 の内容が
変化したため Click Event が発生しましたが、こんどは
ListIndexが変化したため またもや Eventが発生したと
いうことです。

ActiveCellにまた「Mar」を書き込み(ただし、ListIndex=0
つまり リストの先頭行の値を、です)、For〜Nextの
Nextを実行し、、、、
結局、ほんとに終わるまで、イミディエイト・ウィンドウを
みると、
Apr 3
Mar 3
Mar 0
Mar 0
Mar 0
Mar 0
Mar 0
Mar 0
Mar 0
Mar 3
Mar 3
Jan 0
Jan 0
Jan 0

回ものイベント処理を実行していることが分かります。

のだめ さんもそちらのデータで 上に書いたDebugを
実際にやって 確かめてみてください。
RowSourceを使うと 元シート更新されるとき、思わぬ
副作用がある、ということが、お分かりになると思います。
0 hits

【65124】リストボックスでの履歴表示について のだめ 10/4/17(土) 23:21 質問
【65126】Re:リストボックスでの履歴表示について kanabun 10/4/18(日) 9:54 発言
【65134】Re:リストボックスでの履歴表示について kanabun 10/4/18(日) 15:03 発言
【65142】Re:リストボックスでの履歴表示について のだめ 10/4/18(日) 23:08 発言
【65143】Re:リストボックスでの履歴表示について kanabun 10/4/19(月) 1:56 発言
【65150】Re:リストボックスでの履歴表示について のだめ 10/4/19(月) 21:24 お礼

17049 / 76732 ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free