マクロ(Excel VBA)を習得する上で、繰り返し処理は最初なかなか理解ができず「挫折しやすいポイント」です。
ただ、この繰り返し処理に慣れれば、マクロ(Excel VBA)を使ってできることの幅は大きく広がります!
繰り返し処理には、上記の記事の中で説明した「For 文」以外に「Do 文」を使う方法もあります。
今日は、この「Do 文」について説明したいと思います。
1、For 文を使うケースと Do 文を使うケースの違い
「For 文」と「Do 文」、両方とも繰り返し処理に使い、だいたいの場合においてどちらを使っても目的を達成することはできます。
ただ、それぞれ次のように使い分けることが多いです。
●For 文 データの数がはっきりしている場合
●Do 文 データの数が不明な場合
For 文を使ったコードの一例を示します。
例えば、下のシートのように常にA列 A1~A10 にかけて数値が入力されている場合において、B列 B1~B10 にA列の数値の2倍を出力する処理を VBA を使って行う場合を考えてみます(実際このような場合には、四則演算の数式を入れ込むだけで簡単に計算できますが、敢えて VBA を使いますね)。
VBE(エディタ)を開いて(Alt + F11)、標準モジュールに下のコードを入力して実行(VBE を開いた状態で F5 を押せば実行)してみましょう!
1 2 3 4 5 6 7 |
Sub Test() For i=1 To 10 Cells(i,2)=2 * Cells(i, 1) Next i End Sub |
*セルの指定は、Cells(行数, 列数)のように記述します。Cells(1, 1)はセル「A1」、Cells(2, 1)はセル「A2」、Cells(10, 1)はセル「A10」を表します。
すると、マクロが実行されてB列にA列の数値を2倍した数値が出力されます。
さて、このケースではA列のデータの数が10個(A1~A10)とはっきり分かっています。
For 文は、For と Next で囲まれた部分に処理を書き込みます。
「For i=1 To 10」と記述することによって、i を 1から10まで「1、2、3、4・・・」と1つずつ増加させていくことを意味します。
———————–
For i=1 To 10
処理X
Next i
———————–
iが1のときに処理X を行い、それが終わったら「Next i」によって、次のi(i=2)に進みます。
そしてiが2のときにまた処理X を行います。
以後iが3、4・・・と1つずつ増えながら処理X を行います。
*なお、例えば「For i=1 To 11 Step 2」のように最後に「Step 2」と書いた場合には、iが1から11まで1、3、5、7・・・と2つ飛びに数値を増加させていきます。「Step ○○」という記述が無い場合には、1つずつ数値を増加させるということです。
このように、常にA列(A1~A10)にデータが入力されていると分かっているような場合、例えA列(A1~A10)の数値が置き換わったとしても、上記の For文を使ったコードを実行することによって、目的とする計算を行うことができます。
例えば、A列の数値が下のように置き換わった場合(データ数はA1~A10 の10個で変わらない)には、それに合わせてB列の数値を計算することができます。
このように、データの数がはっきり分かっている場合において、繰り返し処理を行いたいときは For文を使うのが適しているのです。
2、Do 文の使い方
さて、Do 文の使い方について説明したいと思います。
Do文は、次のように記述します。
————————————
i=1
Do While Cells(i,1) <>“”
処理X
i=i+1
Loop
————————————
上記のコードによって、Cells(i,1) が 「””(空白)」でない間(While Cells(i,1) <>“”)は、処理X を行った後に i を 1つ増やして(i=i+1)、同じ処理を繰り返します(Loop)。
まず、i=1でスタートします。
——————————–
i=1のときに、Cells(1,1)(つまりセル「A1」)が “”(空白)でなければ、処理X を行う
↓
iを1つ増やしてi=2にする( i=i+1 の記述によって)
↓
i=2のときに、Cells(2,1)(つまりセル「A2」)が “”(空白)でなければ、処理X を行う
↓
iを1つ増やしてi=3にする( i=i+1 の記述によって)
↓
i=2のときに、Cells(3,1)(つまりセル「A3」)が “”(空白)でなければ、処理X を行う
↓
・
・
・
i=n(いくつかは不明)のときに、Cells(n,1) “”(空白)となったら、処理を終了する(Do文から抜け出す)
——————————–
こういったことを行います。
ポイントになるのは、For 文の場合と異なりデータの数を指定していない点です。
上にi=n の場合に「Cells(i,1) <>“” 」の条件から外れて処理を終了するのですが、nがいくつかは指定していません。
データの数が毎回異なる場合に Do 文を使うのが適しています。
ある場合は、データ数が10個かもしれないし、またある場合にはデータ数が55個かもしれない、、、、などという場合。
Do文では、データ数を指定せずに、繰り返し処理の終わりを条件で指定します。
上記の場合だと、
「Cells(i,1)が空白でない場合は処理を継続する」
裏を返せば
「Cells(i,1)が空白になったら処理を終了する 」
ということになるのです。
3、科目コードを科目名に変換する
さて、一例として会計事務所の顧問先の会計データの勘定科目を取り上げたいと思います。
数値の「科目コード」を文字の「科目名」に変換するプログラムを作ってみます。
「科目コード⇒科目名 変換」という名前のシートの中で、科目コードを入力してマクロを実行すると科目名を抽出できるようにしたいと思います。
下の「科目コード⇒科目名 変換」 シートのセル「D5」に科目コードを入力して、マクロを実行するとセル「D6」に科目名を抽出します。
科目コードと科目名の関係は、「科目一覧」というシートの中に表が入っています。
「科目一覧」シートには、A列に科目コード、B列に科目名が並んでいます。
科目コードを入力した後にマクロを実行させると、「科目一覧」シートの中の表で入力した科目コードに一致するものを A列の中から探し出し、その科目コードに該当する科目名を引っ張り出します(VLOOKUP 関数を用いれば同じことができますが、敢えて VBA でDo 文を使います)。
「科目一覧」シートの中には、かなりの行数のデータ(科目コードと科目名)が入っており、また顧問先によってデータの行数が異なるものとします。
このような場合だと、For 文でデータの数を指定してコードを書くのには適していません。
A列を上から順番にデータがなくなるまで(空白になるまで)調べるために、Do 文を用いることにします。
VBE に下のコードを記述します。
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 Test() Dim Kamoku_Code '科目コード' Dim Kamoku_Mei '科目名' '「科目コード⇒科目名 変換」シートのセル「D5」に入力された科目名を読み込む' Kamoku_Code = Worksheets("科目コード⇒科目名 変換").Cells(5, 4) i = 1 '「科目一覧」シートのA列が空白でない限り科目コードが一致するデータを探す' Do While Worksheets("科目一覧").Cells(i + 7, 1) <> "" If Worksheets("科目一覧").Cells(i + 7, 1) = Kamoku_Code Then Kamoku_Mei = Worksheets("科目一覧").Cells(i + 7, 2) Else End If i = i + 1 Loop '「科目コード⇒科目名 変換」シートのセル「D6」に科目名を出力する' Worksheets("科目コード⇒科目名 変換").Cells(6, 4) = Kamoku_Mei End Sub |
「科目コード⇒科目名 変換」 シートのセル「D5」に科目コードを入力して、マクロを実行するとセル「D6」に科目名を抽出することができるようになりました。
さて、コードの中で肝となるのは Do文の部分です。
———————————–
Do While Worksheets(“科目一覧”).Cells(i + 7, 1) <> “”
If Worksheets(“科目一覧”).Cells(i + 7, 1) = Kamoku_Code Then
Kamoku_Mei = Worksheets(“科目一覧”).Cells(i + 7, 2)
Else
End If
i = i + 1
Loop
———————————–
「科目一覧」シートの A列の8行目以降にある科目コードが空白でない限りは、科目コードが変数「Kamoku_Code」と一致するか否か調べています。
そして、一致する場合には変数「Kamoku_Mei 」に同じ行のB列を入れています。
4、まとめ
Do 文の使い方について、For 文との違いを示しながら説明しました。
繰り返し処理は感覚が染みつくまで、少し時間がかかりますがExcel VBAを覚える上で必ず理解しなければならないポイントですのでFor 文とあわせて、覚えて頂きたいと思います。
———————————–
備忘録として、スプレッドシートで GAS(Google Apps Script)を使って While 文で同じことを実行できるコードを示しておきます。
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 28 29 30 31 |
function While_Test() { var Sheet = SpreadsheetApp.getActiveSpreadsheet(); var M_sheet = Sheet.getSheetByName('科目コード⇒科目名 変換'); '「科目コード⇒科目名 変換」シート' var K_sheet = Sheet.getSheetByName('科目一覧'); '「科目一覧」シート' var Kamoku_Code; '科目コード' var Kamoku_Mei; '科目名' var Kamoku_Cell; '科目名を出力するセル' var i; Kamoku_Code = M_sheet.getRange(5, 4).getValue(); i=1; while (K_sheet.getRange(i+7, 1).getValue() !=="") { '「!==」は厳密に等しくない場合を意味する 被演算子が等しくなくかつ/または同じ型でない場合に true を返します' if(K_sheet.getRange(i+7, 1).getValue() == Kamoku_Code){ Kamoku_Mei = K_sheet.getRange(i+7, 2).getValue(); break; } else{ } i++; } Kamoku_Cell = M_sheet.getRange(6, 4); '科目名を出力するセルをD6に指定' Kamoku_Cell.setValue(Kamoku_Mei); 'セルD6に科目名を出力' } |