VBAのFor文の使い方です.

構文

For文は処理を反復するのに用いられます.
A列の1行目〜10行目に入力する例は次の通りです.

Sub For文の一例
Dim i As Long
For i = 1 To 10
Cells(i, 1) = "このセルは" & i & "行目"
Next
End Sub

iカウンタで,いま何回目の処理を行っているかを数えています.
この増えていく数字を利用して,処理したいセルの位置を自動的にずらしていくというのが最も多い使われ方です.
この例では初期値の1に始まり,10までカウンタが1ずつ増加していきます.

  • 1回目の処理なら,Cells(i, 1)Cells(1, 1)のセルを表します.
  • 2回目の処理なら,Cells(i, 1)Cells(2, 1)のセルを表します.
  • 10回目の処理なら,Cells(i, 1)Cells(10, 1)のセルを表します.

For文の一例

問題
  1. 1行目〜50行目を処理したいとき,どのように書けばよいでしょうか?
  2. 2行目〜10行目を処理したいとき,どのように書けばよいでしょうか?
  3. 1列目〜10列目を処理したいとき,どのように書けばよいでしょうか?
応用(一定範囲のレコードの処理)

作業集約時にある作業者のレコードを201行目〜250行目に差し込みましたが,C列の数値(金額)が千円単位であるのを忘れて1円単位で入力してしまったと報告を受けました.
For文を使って修正するには,どのように記述すればよいですか?
切り上げ・切り捨ては無視して構いません.

応用(リスト項目)

A2セルからA10セルに入力されている文言を<li></li>で囲んでください.(HTMLで箇条書き等のリスト項目を意味します.リスト項目群をさらに<ol></ol>で囲めば連番のついた箇条書き—オーダード・リスト—になり,<ul></ul>で囲めば連番のない箇条書き—アンオーダード・リスト—になります.)

ステップ

上述の例ではStepが省略されています.
本来は

Sub For文の一例
Dim i As Long
For i = 1 To 10 Step 1
Cells(i, 1) = "このセルは" & i & "行目"
Next
End Sub

という形です.

Step 1はカウンタを1つ刻みで増加させることを意味しています.
しかしながら,多くのVBAマクロは1行ずつ何かを処理するので1がデフォルトの値として設定されており,Step 1であれば省略しても構いません.

問題

1行飛ばしで処理したい場合,どこを変えればよさそうでしょうか?

応用(2行ペアのスプレッドシート)

1, 2行目,3, 4行目…というように2行ごとでペアになった,100行のスプレッドシートがあります.
全データがA列のみに入っているのですが,偶数行目のデータを奇数行目のB列にコピーできますか?
(こうした後で偶数行目を削除すれば,1行1レコードへときれいに纏められます.)

置換

置換にはReplace関数を用います.
Excelで行う置換をVBAで書くと,次のようになります.

入力セル = Replace(加工する文章, "置換前文言", "置換後文言")

例えば,A1セルにフットサルと入力されているなら,

Sub 置換の例()
Cells(2, 1) = Replace(Cells(1, 1), "フット", "お")
End Sub

とすることでA2セルに置換後のおサルという文言を入力します.

置換の例

問題

A1セルのフットサルを直接A1セルでおサルへと置き換えるには,どのようにしたらよいでしょうか?

応用(範囲置換)

A列1〜100行目に「QRコード」と入っている場合,商標に抵触する可能性があるので全て「二次元コード」にするようにとの指示が出ました.
処理できますか?

応用(相対パス)

相対パス(./xxx.html等)で記述されたWebサイトのファイル群が,あるxlsxファイルのA列に整理されています.
これまでカレントディレクトリ直下に置かれていた画像のファイル群(120行目〜200行目)は数が多かったため,カレントディレクトリと同じ階層にimgという名前でディレクトリを作ってまとめました.
xlsxファイル中に記載された相対パスも書き換えたいと思いますが,どのように処理すればよいですか?

不要文言の除去

ある文言を空白に置換することで,不要な文言を除去することができます.
例えば,

Sub 置換を利用した不要文言の除去
Cells(2, 1) = Replace(Cells(1, 1), "トル", "")
End Sub

とすると,A1セルから「トル」という文言を消し去ったテキストをA2セルに入力することができます.

置換によってトルことができる

問題

たぬき&こけし&くない&おとり暗号があるので,置換してください.

たたこおそおおこおくろたたこおたくおくそくたおこたたこたたろたたおくここおおくたくたひたここたるこおおくおくたおこここくおくおくねたおたくのおくくこじこたくくかくたくおんたおたたくくたこ

セル内改行

セル内での改行はvbLfで表します.
これはVisual Basicで改行コードがLFのものという意味の定数です.Windowsの改行コードは通常CRLFであり,セル内改行は特殊な改行となっています.

Sub セル内改行のある入力例()
Cells(1, 1) = "上の段" & vbLf & "下の段"
End Sub

vbLfはダブルクオートで囲みません.
文字列ではなく,セル内改行が格納された変数のようなものだと考えてください.

セル内改行の入力例

応用(改行タグ)

D列2行目〜20行目の各行に,あるブログの各ページ記事が入っており,それゆえセル内には改行があります.
各記事を再利用したいので,セル内改行を<br>に置換してください.(<br>はHTMLファイルで改行を意味します.)

挿入と削除

セルの挿入

For文のページの一番最初のマクロを実行したところから説明を始めます.
マクロを再掲しましょう.

Sub For文の一例
Dim i As Long
For i = 1 To 10
Cells(i, 1) = "このセルは" & i & "行目"
Next
End Sub

この状態からスタート

A1セルから下へセルを挿入するには次のように書きます.

Sub 下へのセル挿入()
Cells(1, 1).Insert Shift:=xlDown
End Sub

セルを挿入する例

Shift:=xlDownShift:=xlToRightとすると右側にシフトします.
このShiftオプションを設定しない場合には勝手にセルの挿入方向を決める仕組みなので,思わぬ方向にシフトしてしまうかもしれません.
バグの原因となるので,必ず設定するようにしましょう.

なお,英語の一般動詞のように「〜する」という処理を施すものをVBAではメソッドといいます.ここではA1セルを主語として,動詞にあたるInsertメソッドで,挿入するという動作を表現しています.動作に対して副詞句を作るのがオプションです.VBAでは各オプションをオプション名:=設定値の形式で指定します.ここでは「挿入する」という動作に対し,「下へ向かって」という副詞句を与えています.

セルの削除

For文のページの一番最初のマクロを実行したところに戻りましょう.
セルを削除したい場合には,次のようにします.

Sub 上へのセル削除()
Cells(1, 1).Delete Shift:=xlUp
End Sub

セルを削除する例

Shift:=xlUpShift:=xlToLeftとすると左側にシフトします.

For文との組み合わせ

セルを次々に挿入もしくは削除するという手作業は大変面倒なので,For文と組み合わせて処理するのは効果的です.
しかし,この処理は,知らないとハマるポイントがあります.

問題
  1. 上から下に連続で5行削除しようとする次のコードで,1〜5行目が削除できないことを確認してください.
Sub 上から下に削除する誤った例()
Dim i As Long
For i = 1 To 5
Cells(i, 1).Delete Shift:=xlUp
Next
End Sub

上から下に削除すると望む結果にならない

  1. 1行ずつ処理しては停止するVBEのコマ送り機能ステップインを使い,Excelの動きを確認しましょう.

VBEはデバッグ(=バグの除去)を行うための機能をいくつか提供しており,ステップインはそのうちの一つです.マクロを進めて特定のポイント(ブレークポイント)で停止する機能や,進行中のマクロの変数を書き換えたりする機能が存在します.

デバッグのためにステップイン機能を使う

対策

カウンタで指定しながら行や列の挿入/削除を行うときには,Step -1で外側から(行なら下から上,列なら右から左に向かって)処理せねばなりません.

問題

次のコードで1〜5行目が削除できることを確認してください.

Sub 下から上に削除する正しい例()
Dim i As Long
For i = 5 To 1 Step -1 '初期値にも注意しよう!
Cells(i, 1).Delete Shift:=xlUp
Next
End Sub

下から上に削除すると望んだ結果になる

For文での各行の処理

For文を2つ組み合わせることで,一定の範囲の各セルに処理を施すことができます.

A1〜B3セルに同じ文言を入れてみましょう.
A1〜A3セルに同じ文言を入れる,B1〜B3セルに同じ文言を入れると考えれば,2つFor文を作ればいいことが分かります.

Sub 愚直に書いた範囲処理()

Dim i As Long

For i = 1 To 3
Cells(i, 1) = "文言"
Next

For i = 1 To 3
Cells(i, 2) = "文言"
Next

End Sub

iは使い回すので、Dim i As Longは1回しか書かなくて構いません(し、2回書いても「もう宣言されてるよ」と、2回目はエラーになってしまいます)。

For文を2回繰り返して書く例

2列の処理をまとめるには

同じ処理をまとめるのがFor文です。
上の2つのFor文を、For文でまとめてしまいましょう。

違うのは列のところだけですから、For文

Dim j As Long

For j = 1 To 2
'まとめた処理
Next

を使って列をまとめます.

すると,

Sub ネストで範囲処理をコンパクトにまとめる()

Dim i As Long
Dim j As Long

For j = 1 To 2
For i = 1 To 3
Cells(i, j) = "文言"
Next
Next

End Sub

となります。
このように構文の中に構文が入った形を、ネスト(入れ子)と言います。

For文に限らず、コードが読みにくくなるためネストは深くしすぎないようにしてください。

ネストするとコンパクトになる

なお、ijは両方とも整数なので、変数の宣言はDim i, j As Longとまとめても構いません。もし個別に変数の型を宣言したいなら、Dim i As Long, str As Stringといった具合に書くことができます。

問題

A1〜D5セルに文言を入れるネストを作ってみてください。

次回

「〜のときにだけ」繰り返すということができたら一層便利ですね。
次回は条件を設定するためにIf文を扱います。