[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『コードをまとめたい』(八家)
VBA覚えたての初心者です。
よろしくお願いいたします。
ある一行において、
その行に目的のセルがあればメッセージボックスが表示させ、
5行分だけ下がって、
再度、同様の処理を20回分したい・・とします。
とりあえず、3行分ほどはできました。
:::::::::::::::::::::::::::::::
Sub ボタン6_Click()
Dim i As Long For i = 5 To 32 If Cells(9, i) = Cells(1, 1).Value Then msg = MsgBox(Cells(8, 2)) End If Next i
Dim t As Long For t = 5 To 32 If Cells(14, t) = Cells(1, 1).Value Then msg = MsgBox(Cells(13, 2)) End If Next t
Dim s As Long For s = 5 To 32 If Cells(19, s) = Cells(1, 1).Value Then msg = MsgBox(Cells(18, 2)) End If Next s
End Sub
:::::::::::::::::::::::::::::::
ただ、20個分もコードを書くのはいかがなものかと考え、これをどうかしてもう少しまとめられないかと考えたところ、
offset と do loop という関数があると知りました。
何とか書き換えましたが全く動きません。
何がダメなのか教えていただけないでしょうか。
以下自作コード
:::::::::::::::::::::::::::::::
Sub ボタン6_Click()
Dim i As Long
Do t = 0 For i = 5 To 32 If Cells(9, i).Offset(t) = Cells(1, 1).Value Then msg = MsgBox(Cells(8, 2).Offset(t)) Exit Do Else Exit Do End If Next i t = t + 5 Loop
End Sub
< 使用 Excel:Excel2019、使用 OS:Windows10 >
ちょっと...良く見てないのでこれで意味合いが 合っているか確認してください。
19行目までの範囲を対象にしてあるので 残りは調整してください。
Sub Sample() Dim i As Long, j As Long Dim msg As VbMsgBoxResult For i = 5 To 32 For j = 9 To 19 Step 5 If Cells(9, i) = Cells(1, 1).Value Then msg = MsgBox(Cells(j - 1, 2)) End If Next j Next i End Sub (あみな) 2022/03/13(日) 01:19
>一番最初の処理する行に該当のセルがない場合、なにも起動しません
これならどうかな?
Sub Sample() Dim i As Long, j As Long Dim msg As VbMsgBoxResult For i = 5 To 32 For j = 9 To 19 Step 5 If Cells(j, i).Value = Cells(1, 1).Value Then msg = MsgBox(Cells(j - 1, 2)) End If Next j Next i End Sub
(あみな) 2022/03/13(日) 01:42
後は、わかると思うので頑張ってちょだいね。^^
(あみな) 2022/03/13(日) 01:51
If Cells(9, i).Offset(t) = Cells(1, 1).Value Then の成立の如何にかかわらず Exit Do で抜けてしまうことが原因でしょう。
されたいことが不明なので、形式的に整えただけですが、 こんな形の「入れ子」のループになるのでは?
Sub ボタン6_Click() Dim k As Long Dim i As Long Dim msg For k = 9 To 9 + 5 * 19 Step 5 For i = 5 To 32 If Cells(k, i) = Cells(1, 1) Then msg = MsgBox(Cells(k - 1, 2)) ''Exit For '一つでも一致したら警告出力なら、直ぐに抜ければよいかも。 End If Next i Next End Sub # なお、一致するものがあるかどうかだけなら、 # MATCH関数とか、COUNTIF関数とかを使うかもしれませんねえ。
(γ) 2022/03/13(日) 05:57
おはようございます。 (八家)さん、見に来てください!! ^^;
えっ?何かってですよね? 先に結論から言いますと、(γ)さん書いてくださったループ処理が正です。 (γ)さん、ありがとうございます。
なにかって言いますと…二重ループの基本?の走らせ方は 横方向が先で、縦は後になると思うのですが 私が適当で^^;…その〜どっちからでもいいじゃん的な考えで あ、すいません。言ってる事がわからないですよね?
えと、二重ループには、内側ループと外側ループがありまして 書き方によって横に先に走らせるか、縦に走らせるかを決めることが できるのです。
実際の処理は一瞬なので人間さんの目には見えないですが 一つのセルに背景色を付けながら処理すると理解できます。 今回の、(八家)さんの場合は横が正なので(きっと)と思います。
IF文をコメントアウトして下記のコードを実行すると 走り方がわかるので19行目までで試してください。
Sub 列方向優先チェック() Dim i As Long, j As Long, x As Long Dim msg As VbMsgBoxResult For i = 5 To 32 For j = 9 To 19 Step 5 ''If Cells(j, i).Value = Cells(1, 1).Value Then Cells(j, i).Interior.Color = RGB(175, 238, 238) msg = MsgBox(Cells(j - 1, 2)) ''End If Next j Next i End Sub
Sub 行方向優先チェック() Dim i As Long, j As Long, x As Long Dim msg As VbMsgBoxResult For j = 9 To 19 Step 5 For i = 5 To 32 ''If Cells(j, i).Value = Cells(1, 1).Value Then Cells(j, i).Interior.Color = RGB(175, 238, 238) msg = MsgBox(Cells(j - 1, 2)) ''End If Next i Next j End Sub
(あみな) 2022/03/13(日) 07:42
よく見に来たでありんす^^
デバッグ Debug.Print(変数)もしっかりして頑張ってね。
(あみな) 2022/03/13(日) 11:02
コメントありがとうございました。
■以下、余談です。(お急ぎの方は、そのままスキップしてください)
話は、配列を行方向に処理するか、列方向に処理するかの順序に関するものです。
VBAの配列は、列優先順序のメモリーレイアウトを利用していると思います。 つまり、行列(例えば2次元配列)はメモリー上に 1 5 9 2 6 10 3 7 11 4 8 12 といった数値をつけた位置の順番にメモリー上に管理されているものと思われます。 (メモリーはむろん一次元です)
動的配列のRedim Preserveなどで、「最後の次元に沿ってしか大きさを変更できない」というのは、 このメモリーレイアウトが原因となっているわけです。
動的配列と固定配列のメモリーレイアウトは同じであると仮定すると、 上の"列優先順序"で配列にアクセスしたほうが、連続した位置のメモリーを扱うことになるので、 速度的にも有利なはずです。
実験してみました。 縦横1000要素からなる二次元配列に、1000個の要素からなる一次元配列を (c)縦に配置して全体に繰り返して埋める処理を100回実行 (r)横に配置して全体に繰り返して埋める処理の100回実行 の時間を計測すると、 (c)は1.97秒、(r)は2.20秒と、(c)は約9割の時間で済みます。(10回の平均値) (もちろん出来上がりの配列は異なりますが、処理時間にのみ注目しています)
(なお、私の別の処理系(これも列優先順序のルールに従います)で同じ実験をすると、 (c)0.0741秒 (r)0.1846秒と、(c)は(r)の約4割の時間で済みました。)
ですから、理屈からいうと、ループは、速度面だけから言えば、 For j = 1 To n For i = 1 To n mat(i, j) = ary(i) Next Next のように列方向を優先するのが有利ということになります。
しかし、(今回の例のように)ユーザーの目的が、、 上の行から始めて、順次横方向で比較を行い、 次の行に処理を進める、 といったものであれば、速度のことはさておいて、 そうした処理をそのままコード化する必要があるものと思います。
列優先と行優先の速度の話は余り目にしたことがなかったので、 参考のためにメモしてみました。
■【追記】ワークシート上の計算順序について。 VBAのヘルプによると、 > Rangeオブジェクトには、CalculateRowMajorOrderというメソッドがあり、 > これは、セルごとに、左上隅から右下隅まで、行優先順に指定された範囲を計算します。 > これは、Excel2000以前のバージョンで範囲を計算するために使用されるプロセスと同じです。 ということは、現在のExcelのワークシート計算は上記の行優先ではなく、 デフォルトでは、列優先順序で計算がされている、ということのようです。
(γ) 2022/03/13(日) 18:46
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.