Excel VBA でプログラミングする際に、繰り返し処理を行うことが多いです。
繰り返し処理を行う方法として「For 文」と「Do 文」がありますが、これらをどう使い分ければ良いか? という疑問が湧いてくることがあるかと思います。
ケースバイケースなので一概には言えませんが、自分としてはざっくりと言えば
「あらかじめデータの数が分かっているときは For 文、データの数が分からないときは Do 文」
でいいと思っています。
1、データの数が分かっている場合の For 文
例えば、次の4月~3月の1年間の各月の「売上高」と「売上原価」の金額から年間の原価率、利益率を計算してメッセージボックスに表示させてみたいと思います。
一度作ったマクロは後々使いまわす前提で考えます。
一年間の月数は毎年変わらないので、売上高と売上原価のデータ数はそれぞれ12個とあらかじめ分かっています。
そのような場合 For 文を使ってプログラミングすれば良いでしょう。
VBA コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Sub calc() Dim Uriage As Double '売上高の年間合計' Dim Urigen As Double '売上原価の年間合計' Dim Genkaritsu As Double '原価率' Dim Riekiritsu As Double '利益率' Uriage = 0 Urigen = 0 '12ヶ月分の売上高、売上原価を合計↓' For i = 1 To 12 Uriage = Uriage + Cells(i + 4, 4) Urigen = Urigen + Cells(i + 4, 5) Next i Genkaritsu = Application.Round(Urigen / Uriage, 3) '原価率の計算' Riekiritsu = 1 - Genkaritsu '利益率の計算' MsgBox "原価率=" & Genkaritsu & vbCrLf & "利益率=" & Riekiritsu End Sub |
実行するとメッセージボックスが出て、原価率、利益率が表示されます。
コード説明
For 文を使っている箇所は以下↓
1 2 3 4 5 6 |
For i = 1 To 12 Uriage = Uriage + Cells(i + 4, 4) Urigen = Urigen + Cells(i + 4, 5) Next i |
i を 1 から 12 まで1つずつ増やしていきます。
Uriage = Uriage + Cells(i + 4, 4)
の部分では、売上高合計を計算しています。
i が 1の場合、セル「D5」(Cells(5, 4))の値を足す
i が 2の場合、セル「D6」(Cells(6, 4))の値を足す
・
・
・
i が 12の場合、セル「D16」(Cells(16, 4))の値を足す
という具合にです。
原価率の計算は四捨五入して小数点以下第3位まで計算しています。
Genkaritsu = Application.Round(Urigen / Uriage, 3) ‘原価率の計算’
2、データの数が分からない場合の Do 文
さて、上記のような場合と違って毎回データの数が分からないようなケースもあります。
例えば、会計上の仕訳数は月によって異なります。
次のように B列に日付を6桁(2018年8月1日であれば 180801)で表示し
C列に借方科目コード
D列に貸方科目コード
E列に金額
F列に摘要
が並べられている場合を考えてみます。
一番上のデータは5行目です。
データの一番下は 62行目です。
データは 5行目~62行目で計 58個あることが分かります。
貸方コード 612 の科目名は「売上高」とします。
さて、このデータを使って売上高(貸方科目コードが 612)の金額を合計してメッセージボックスに表示してみたいと思います。
VBA コードは後々も同じものを使う前提で考えます。
For 文を使って計算することもできますが、今月はデータ数がたまたま 58個だったというだけで次の月も同じだとは限りません。
今回は For 文で i を 1 から 58 まで変化させることになりますが、別の月だと i の上限が 58 とは限りません(まず違います)。
ですので月ごとに i の上限を書き換えなければならなくなってしまいます。
毎回データの数を数えるのもどうなかと。。
今回のようなケースでは Do 文を使った方が良いのです。
Do 文を使った VBA コードを書くと次のようになります。
VBA コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Sub calc2() Dim Uriage As Double '売上高の年間合計' Uriage = 0 i = 5 'i の初期値 データは5行目から始まる' '日付のデータがある限り(空白ではない限り)処理を繰り返す↓' Do While Cells(i, 2) <> "" If Cells(i, 4) = 612 Then Uriage = Uriage + Cells(i, 5) Else End If i = i + 1 'i を1つ増加させる' Loop MsgBox "売上高=" & Uriage & "円" End Sub |
実行するとメッセージボックスが出て、売上高が表示されます。
コード説明
Do 文を使っている箇所は以下↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
i = 5 'i の初期値 データは5行目から始まる' '日付のデータがある限り処理を繰り返す↓' Do While Cells(i, 2) <> "" If Cells(i, 4) = 612 Then Uriage = Uriage + Cells(i, 5) Else End If i = i + 1 'i を1つ増加させる' Loop |
最初に i=5 とデータが始まる行番号を i に入れています。
*Do 文を使う際には最初に i を指定しておかなければいけません。
Do While Cells(i, 2) <> “”
上記部分で、Cells(i, 2) が空白でない限り、Do と Loop の間に書いた処理を続けることを指示しています。
そして、Loop の前で i=i+1 と入れてiを1つ増やす必要があります。
*これを忘れると空白の判定を行っている Cells(i, 2) は常に同じセル Cells(5, 2) のままとなり、無限ループになってしまいます。
Do 文を使う際の注意点
今回のようなケースで Do 文を使う際には、データの最初の行から最後の行までの間に空白行を作らないようにしなければいけません。
空白行を入れると
Do While Cells(i, 2) <> “”
の部分で Cells(i, 2) が空白になったと判定されてループが終了してしまい、その行より下のデータを読まなくなってしまいます。
なお、For 文を使う場合には、空白があっても処理を続けることができます。
3、まとめ
繰り返し処理を行う場合、どのようなケースであっても工夫を凝らせば For 文、Do 文のどちらでも対応は可能だと思います。
ただ、どちらを使うかのざっくりとした判断基準としては冒頭でも述べた
「あらかじめデータの数が分かっているときは For 文、データの数が分からないときは Do 文」
で良いでしょう。
編集後記
昨日(8/28)は法人の期中の処理の後、新規で対応させて頂く一般社団法人の資料確認を行いました。
また、先日受験した生命保険の一般課程試験は合格していました。
次は 10月に専門課程試験です。