ForとIfのネスト
ForとIfのネストこそがVBAの要点
VBA習得で最も肝心なものは、For文とIf文を確実に習得することです。
For文とIf文の基本をしっかりと覚え、
そして、
For文とIf文をネストさせるプログラミング技術を習得してください。
For~Nextステートメントは、繰り返し処理
If~End Ifステートメントは、条件分岐
つまり、
条件により分岐しつつ繰り返し処理を行う。
マクロVBAによる自動化の大部分が、For繰り返しとIf条件分岐によって記述されるという事です。
以下の表で解説していきます。
上表の、昨対比を計算し、昨対比が100%未満の場合は文字を赤色にします。
考え方を順に解説していきます。
第1に考える事・・・大外の繰り返しを作成
エクセル表の多くは(多くと言うより基本としては)、縦に可変となるデータが連なります。
第1に考えることは、この縦のデータ処理の繰り返しになります。
3行目から14行目まで処理する繰り返しだけを書きました。
細部の処理など気にせずに、とにかくこれだけ書いてしまいましよう。
最終行の14は、
Cells(Rows.Count, 1).End(xlUp).Row
このように、最初からかければより良いですが、
長い文があると。目がちらついて理解しづらい場合は、
このように、最初は固定数値で書いておいて、
全体が出来上がってから、
14
↓
Cells(Rows.Count, 1).End(xlUp).Row
と置き換えすれば良いのです。
第1に考えることは、この縦のデータ処理の繰り返しになります。
Sub sample() Dim i As Long For i = 3 To 14 Next End Sub |
3行目から14行目まで処理する繰り返しだけを書きました。
細部の処理など気にせずに、とにかくこれだけ書いてしまいましよう。
Cells(Rows.Count, 1).End(xlUp).Row
このように、最初からかければより良いですが、
長い文があると。目がちらついて理解しづらい場合は、
このように、最初は固定数値で書いておいて、
全体が出来上がってから、
14
↓
Cells(Rows.Count, 1).End(xlUp).Row
と置き換えすれば良いのです。
第2に考える事・・・1支店だけを作成
3支店の繰り返しを考えたいところですが、ここで手が止まる人が多いのではないかと思います。
思いますというより、実際にここで手が止まる人を多く拝見してきました。
そこで今回は、まずA支店だけの処理を考えてみましょう。
D3セル(A支店の1月)の計算を考えましょう。
Cells(3, 4) = Cells(3, 3) / Cells(3, 2)
D3セルだけなら、これで良いですよね。
では、Forの中に入れて、行数に変数iを使うようにします。
Cells(3,
この3が行数なのですから、
Cells(i,
このように書き直せば良いことが分かります。
これを実行すれば、A支店の昨対比だけが計算されます。
思いますというより、実際にここで手が止まる人を多く拝見してきました。
そこで今回は、まずA支店だけの処理を考えてみましょう。
Cells(3, 4) = Cells(3, 3) / Cells(3, 2)
D3セルだけなら、これで良いですよね。
Cells(3,
この3が行数なのですから、
Cells(i,
このように書き直せば良いことが分かります。
Sub sample() Dim i As Long For i = 3 To 14 Cells(i, 4) = Cells(i, 3) / Cells(i, 2) Next End Sub |
これを実行すれば、A支店の昨対比だけが計算されます。
第3に考える事・・・昨対比の判定
3支店の繰り返しは後回しにしたので、
先に、昨対比が100%未満の場合は文字を赤色にします。
D列の昨対が100%未満(つまり1未満)の場合、
つまり、
If文で1未満かを判定し、1未満の場合にフォントの色を赤色にします。
フォントの色を赤色にするVBAは、
セル.Font.Color = VbRed
これを実行すれば、A支店の昨対比だけが計算され、
昨対100%未満が赤色になります。
先に、昨対比が100%未満の場合は文字を赤色にします。
つまり、
If文で1未満かを判定し、1未満の場合にフォントの色を赤色にします。
フォントの色を赤色にするVBAは、
セル.Font.Color = VbRed
Sub sample() Dim i As Long For i = 3 To 14 Cells(i, 4) = Cells(i, 3) / Cells(i, 2) If Cells(i, 4) < 1 Then Cells(i, 4).Font.Color = vbRed End If Next End Sub |
これを実行すれば、A支店の昨対比だけが計算され、
昨対100%未満が赤色になります。
第4に考える事・・・3支店の繰り返し
最後に、後回しにしていた3支店の繰り返し処理を追加します。
3支店(3回)の繰り返しは、
このVBA自体は問題なく書けるでしょう。
問題は、実際の列数は、
A支店:2,3,4
B支店:5,6,7
C支店:8,9,10
となっていることです。
変数cは、1,2,3と変化します。
これを、2,5,8と変化させたいのです。
(c - 1) * 3 + 2
このような計算式で求まるのですが、ちょっと難しい感じがします。
少し詳しく解説すると、
(変数 - 1) * 1データの列数 + 最初の列位置
これが書ければ、もちろんこれで良いのですが、
今回は、少し違う方法で書いてみましょう。
3支店の処理ですが、
変数を1~3ではなく、昨年の列位置の数値で変化させます。
これで、変数cは、
2,5,8
と変化することになります。
昨年は、c
今年は、c + 1
昨対比は、c + 2
という事になります。
3支店(3回)の繰り返しは、
Dim c As Long For c = 1 To 3 Next |
このVBA自体は問題なく書けるでしょう。
問題は、実際の列数は、
A支店:2,3,4
B支店:5,6,7
C支店:8,9,10
となっていることです。
これを、2,5,8と変化させたいのです。
(c - 1) * 3 + 2
このような計算式で求まるのですが、ちょっと難しい感じがします。
少し詳しく解説すると、
(変数 - 1) * 1データの列数 + 最初の列位置
これが書ければ、もちろんこれで良いのですが、
今回は、少し違う方法で書いてみましょう。
変数を1~3ではなく、昨年の列位置の数値で変化させます。
Dim c As Long For c = 2 To 8 Step 3 Next |
これで、変数cは、
2,5,8
と変化することになります。
昨年は、c
今年は、c + 1
昨対比は、c + 2
という事になります。
第5に考える事・・・3支店の繰り返しを全体の中に組み込む
第3までに出来たVBAコードに、第4のFor~Nextを組み込みます。
さて、どこに入れるかです。
第3までに出来たVBAコード
このVBAコードは、
・縦に繰り返し
・計算
・昨対比判定
このような順になっています。
これを、
・縦に繰り返し
・横に繰り返し
・計算
・昨対比判定
このように変更します。
ネストを追加した時は、必ずTabでインデントを正しくしておきましょう。
マクロVBAが正しく動かないという相談者の多くが、このインデントがぐちゃぐちゃになっています。
インデントが乱れていたのでは、思考が乱れてしまいます。
ここまで出来たら、後は列数の数値を変数に置き換えれば完成です。
昨年は、2 → c
今年は、3 → c + 1
昨対比は、4 → c + 2
これで一応の完成です。
さて、どこに入れるかです。
Sub sample() Dim i As Long For i = 3 To 14 Cells(i, 4) = Cells(i, 3) / Cells(i, 2) If Cells(i, 4) < 1 Then Cells(i, 4).Font.Color = vbRed End If Next End Sub |
このVBAコードは、
・計算
・昨対比判定
これを、
・横に繰り返し
・計算
・昨対比判定
Sub sample() Dim i As Long Dim c As Long For i = 3 To 14 For c = 2 To 8 Step 3 Cells(i, 4) = Cells(i, 3) / Cells(i, 2) If Cells(i, 4) < 1 Then Cells(i, 4).Font.Color = vbRed End If Next Next End Sub |
ネストを追加した時は、必ずTabでインデントを正しくしておきましょう。
マクロVBAが正しく動かないという相談者の多くが、このインデントがぐちゃぐちゃになっています。
インデントが乱れていたのでは、思考が乱れてしまいます。
今年は、3 → c + 1
昨対比は、4 → c + 2
Sub sample() Dim i As Long Dim c As Long For i = 3 To 14 For c = 2 To 8 Step 3 Cells(i, c + 2) = Cells(i, c + 1) / Cells(i, c) If Cells(i, c + 2) < 1 Then Cells(i, c + 2).Font.Color = vbRed End If Next Next End Sub |
これで一応の完成です。
最後に考える事・・・最後の仕上げ
最終行の14を、自動の最終行取得に変更します。
必要に応じて、
シート指定や、メッセージの表示を追加します。
Withを使う場合は、
Cellsの先頭に付ける.(ピリオド)の漏れに注意してください。
Sub sample() Dim i As Long Dim c As Long For i = 3 To Cells(Rows.Count, 1).End(xlUp).Row For c = 2 To 8 Step 3 Cells(i, c + 2) = Cells(i, c + 1) / Cells(i, c) If Cells(i, c + 2) < 1 Then Cells(i, c + 2).Font.Color = vbRed End If Next Next End Sub |
必要に応じて、
シート指定や、メッセージの表示を追加します。
Sub sample() Dim i As Long Dim c As Long With Worksheets("Sheet1") For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row For c = 2 To 8 Step 3 .Cells(i, c + 2) = .Cells(i, c + 1) / .Cells(i, c) If .Cells(i, c + 2) < 1 Then .Cells(i, c + 2).Font.Color = vbRed End If Next Next End With MsgBox "終了" End Sub |
Withを使う場合は、
Cellsの先頭に付ける.(ピリオド)の漏れに注意してください。
目指すべきVBAの書き順・・・VBAが上達したら
ForとIfのネストに慣れてきたら、
以下の手順でVBAを書けるように練習しましょう。
これは、あくまで理想論です。
今回の例題であれば、上から順に書くこともできますが、
もっと複雑な処理のVBAを書く場合、上から順に全てを書くことはほぼ無理な事です。
複雑なVBAを作るときは、試行錯誤しながら、
上に行ったり下に行ったりしながら、少しずつ書き足していくことでVBAを完成させます。
以下の手順でVBAを書けるように練習しましょう。
Sub sample() Dim i As Long Dim c As Long With Worksheets("Sheet1") End With End Sub |
Sub sample() Dim i As Long Dim c As Long With Worksheets("Sheet1") For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row Next End With End Sub |
Sub sample() Dim i As Long Dim c As Long With Worksheets("Sheet1") For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row For c = 2 To 8 Step 3 Next Next End With End Sub |
Sub sample() Dim i As Long Dim c As Long With Worksheets("Sheet1") For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row For c = 2 To 8 Step 3 .Cells(i, c + 2) = .Cells(i, c + 1) / .Cells(i, c) If .Cells(i, c + 2) < 1 Then End If Next Next End With End Sub |
これは、あくまで理想論です。
今回の例題であれば、上から順に書くこともできますが、
もっと複雑な処理のVBAを書く場合、上から順に全てを書くことはほぼ無理な事です。
上に行ったり下に行ったりしながら、少しずつ書き足していくことでVBAを完成させます。
ForとIfのネストをスムーズに書けるようになれば、自在にマクロVBAを書き進められるようになります。
まずは、
ForとIfのネストの習得に注力してVBA学習を進めてみてください。