【5分でVBA学習】(&ツール提供) マクロ初心者から次のステージへ！「For…Next」による繰り返し処理 ～Excelフィルタリングツール コード解説 #8～

# 1. はじめに
ＡＲアドバンストテクノロジ株式会社（ＡＲＩ）の鈴木タクヤです。
>全ての存在は滅びるようにデザインされている。
生と死を繰り返す螺旋に・・・・・・
私達は囚われ続けている。
（後略）

これは私の好きなゲーム[「NieR:Automata」](https://www.jp.square-enix.com/nierautomata/ "NieR:Automata | SQUARE ENIX")（ニーア オートマタ；開発はプラチナゲームズ、販売はスクウェア・エニックス）の冒頭の語りです。このゲームはエイリアンによる侵略で月に追われた人類のために、主人公の __「2B」__（トゥービー）というアンドロイドが、様々な葛藤を抱えながら地球奪還に向けた戦争に身を投じていくスタイリッシュなアクションRPGです。この記事の執筆時点で全世界800万本以上売れているらしいのでご存じの方もいると思いますが、もうすぐこのゲームを原作としたアニメ第2クールが始まるので、個人的には楽しみです。

それはそうと・・・
今回はExcelフィルタリングツールのソースコード解説第8回です。



（ツールの詳細については以下の記事を、「Excelフィルタリングツール解説シリーズ」タグの記事一覧については以下の記事下部「5. 解説記事のリンク」をご参照ください。）

https://qiita.com/TakuyaSuzuki/items/75789a1cf0b3a7c31c0b

__[解説第7回](https://qiita.com/TakuyaSuzuki/items/a38b2356d823a67f87ea "【【5分でVBA学習】マクロの記録の限界を越えた自動化の第一歩！「Ifステートメント」の使い方（後編） ～Excelフィルタリングツール コード解説 #7～")__ は「Ifステートメント」の解説後編ということで、ブール型やブール演算子（論理演算子）についての解説でしたが、今回のテーマは「For…Nextステートメント」による繰り返し処理です。

これを使えるようになれば、「Excelを用いた業務をマクロで自動化する」という、あなたにとっての __「To-Be」__（理想の姿）に近づくこと請け合いです。

# 2. For…Nextステートメントとは
繰り返し（ループ）処理を記述する際に使用する以下の構文を「For…Nextステートメント」と呼びます。

```vb:For…Nextステートメント（ [ ]内は省略可能 ）
    For ループカウンタ = 初期値 To 最終値 [Step 加算値]
        '～何かしらの処理～
        [Exit For]
        '～何かしらの処理～
    Next [ループカウンタ]

```
はじめの `For` と `Next` の間の処理が繰り返されます。「ループカウンタ」は変数、「初期値」「最終値」「加算値」は数値もしくは変数で指定します。「加算値」は省略した場合「1」となります。
`Exit For` は省略可能ですが、使用する場合そこに到達すると繰り返し処理を抜け、`Next` の次の行に飛びます。主に __[前々回](https://qiita.com/TakuyaSuzuki/items/2bd2c757be640f252b89 "【5分でVBA学習】マクロの記録の限界を越えた自動化の第一歩！「Ifステートメント」の使い方（前編） ～Excelフィルタリングツール コード解説 #6～")__ 、 __[前回](https://qiita.com/TakuyaSuzuki/items/a38b2356d823a67f87ea "【5分でVBA学習】マクロの記録の限界を越えた自動化の第一歩！「Ifステートメント」の使い方（後編） ～Excelフィルタリングツール コード解説 #7～")__ と解説した「Ifステートメント」と併用されます。

例えば以下の例をご覧ください。

```vb:For…Nextステートメント使用例
    For i = 1 To 3
        Cells(1, i) = i
    Next i
```
`Cells()` は __単一の__ セルを表します。（複数形だけど。）
`Cells(1, 2)` で「1行2列目のセル」つまり「B1セル」を表します。

上の使用例ではループカウンタである変数 `i` の値は初期値 `1` から始まり、加算値を省略しているので処理を繰り返すごとに1ずつ増え、`i` が最終値 `3` を超えるまで処理を繰り返します。ここで繰り返される `Cells(1, i) = i` は __[前回](https://qiita.com/TakuyaSuzuki/items/a38b2356d823a67f87ea "【5分でVBA学習】マクロの記録の限界を越えた自動化の第一歩！「Ifステートメント」の使い方（後編） ～Excelフィルタリングツール コード解説 #7～")__ 登場した `Range()` と似た使い方をしていますが、「1行 __i__ 列目のセルの値に __i__ を設定する」という意味になります。つまりこれを実行した場合、表示しているシートが以下のようになります。
（「1行 __1__ 列目」が __1__、「1行 __2__ 列目」が __2__、「1行 __3__ 列目」が __3__。i = 3 までで繰り返し終了。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2566746/3c24fe79-2f53-dd21-9fb1-3d6ee590fe6a.png)


今回のテーマから逸れますが、 `Range()` と `Cells()` の使い分けについては以下が参考になります。

https://excel-ubara.com/excelvba1/EXCELVBA311.html#google_vignette



::: note
ループカウンタはVariant型（明示的にデータ型を宣言しない）よりも、整数のInteger型やLong型にすると処理が若干速くなるようです。
:::

https://learn.microsoft.com/ja-jp/office/vba/language/concepts/getting-started/making-faster-fornext-loops

 [__Excelフィルタリングツール__](https://qiita.com/TakuyaSuzuki/items/75789a1cf0b3a7c31c0b "【ツール提供】Excelユーザなら全員使える?! Excelフィルタリングツール") の中では「For…Next」を、例えばFunctionプロシージャ `checkFormat` で使用しています。
```vb:Excelフィルタリングツールより抜粋
    Dim startingPositionOfRowNo As Integer              '数字の開始位置が先頭から何文字目かを格納する変数を定義
    Dim i As Integer, j As Integer                      'ループ処理用変数を定義
    '2文字目以降は1文字ずつ英字か数字か確認
    For i = 2 To wordCount
        If Mid(cellReference, i, 1) Like "[0-9]" Then
            startingPositionOfRowNo = i                 '数字部分（行番号）開始が先頭から何文字目かを保持
            Exit For
        ElseIf Not Mid(cellReference, i, 1) Like "[A-Z]" Then   '数字じゃなくて英字でもなければエラー
            Call showFormatErrorMessage(i)
        End If
    Next i
```
これは変数 `cellReference` に代入されたセル番地（C7, AB12など）を表す文字列の入力誤りがないかを確認する処理の一部です。変数 `wordCount` は文字数を表しています。

この前の処理で既に文字列の先頭が英字であることを確認しているので、ループカウンタ `i` は `2` から始まり、2文字目から順に1文字ずつ `i` 文字目を確認していきます。
英字であれば次のループ、数字が出てきたら変数 `startingPositionOfRowNo` に `i` の値を代入し `Exit For`でループを抜けます。数字が出てくる前に英字以外（記号など）が見つかった場合にはSub プロシージャ `showFormatErrorMessage` を呼び、 `i` 文字目でエラーになったとメッセージボックスで表示します。
↓表示例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2566746/7a3eb2b5-8f12-dad6-4032-46f2d3b12b6b.png)

__Mid関数__ `Mid(文字列, x, y)` は、`文字列` の `x` 文字目から `y` 文字を返す関数で、例えば`Mid("NieR:Automata", 6, 4)` は「Auto」（6文字目からの4文字）になります。

https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/mid-function

また以前も登場した __`Like`__ は演算子の一つで、文字列のパターンマッチングを行います。一致すればTrue、不一致ならFalseを返します。パターンマッチングには文字のリストやワイルドカードが使用できます。例えば、`[0-9]`は0から9までの数字1文字、`[A-S]` はA, B, ～Sまでの英字1文字、`?` は任意の1文字・・・などです。 `"2B" Like "[0-9]?"` はTrue、`"A2" Like "?[A-Z]"` はFalseになります。

https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/like-operator

# 3. おわりに
以上、「For…Next」の解説でした。
Ifによる条件分岐と繰り返し処理は「マクロの記録」機能ではどうやっても登場しないと思うので、これらをマスターすればかなり多くの手作業を自動化できます。

Excel VBAの繰り返し処理は他にもありますが、まずは基本となる「For…Next」を押さえておきましょう。

そして今回のおまけですが、ここまで読んでいただいたお礼として、ちょっとしたツールを提供します。次回はこのおまけツールにも登場する、「For __Each__…Next」について解説します。

# 4. おまけ；【ツール提供】A1セル自動選択ツール
## 4-1 ツールの説明
同僚と共有するExcelのファイルを開いたとき、各シート中途半端なセルが選択されていてイラっとしたことはありませんか？また、自分が編集したファイルを保存する際、シートが大量にあるとA1セルに戻すのが面倒だと感じませんか？

そんな貴方にこのツール。実行すれば、全シートA1セルが選択され、先頭のシートが表示されます。ファイルを開いた際や、保存する前に使用してみてください。職場のギスギス感が若干改善される・・・かもしれません。

## 4-2 使用方法
ツール導入の流れは概ね[__【ツール提供】Excelユーザなら全員使える?! Excelフィルタリングツール__ の __「3-1 VBAコードのコピー&ペースト」__](https://qiita.com/TakuyaSuzuki/items/75789a1cf0b3a7c31c0b#3-1-vbaコードのコピーペースト "3-1 VBAコードのコピー&ペースト") と同じです。
適当な「マクロ有効ブック(*.xlsm)」の標準モジュールに[__以下のソースコード__](#4-3-ツールのソースコード)をコピペしてください。

使用時には、ソースコードをコピペした「マクロ有効ブック(*.xlsm)」を開き、A1セルを選択したいExcelファイルのウィンドウを選択した状態で「開発」タブの「マクロ」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2566746/4eb1d28b-fd89-95f6-ebf3-f246eafa376a.png)

「マクロの保存先」のプルダウンから「開いているすべてのブック」かソースコードをコピペした「マクロ有効ブック(*.xlsm)」のファイル名（キャプチャでは「汎用マクロ.xlms」）を選択し、マクロ名「～selectA1」を選択し、「実行」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2566746/a5cdde68-f7d3-2a32-7951-69f441fee517.png)

:::note
上の画面の「オプション」ボタンを押下すると、自作のマクロにショートカットキーを設定することもできます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2566746/3a99a439-4f7d-6389-f279-013d0e56faea.png)
:::

一瞬で全シートA1セルが選択され、一番左のシートが表示されます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2566746/26b02002-5193-ca5b-b364-69e59811eb5b.png)

:::note warn
A1セルは選択したいけどシートの移動は要らない・・・という場合は、ソースコードの `Worksheets(1).Activate` をコメントアウト（行の先頭にシングルクォート「'」を付与）してください。
:::

## 4-3 ツールのソースコード

```vb:A1セル自動選択ツール
'A1セル自動選択ツール

Sub selectA1()

    Dim ws As Worksheet
    
    '各シートのA1セルを選択
    For Each ws In ActiveWorkbook.Worksheets
        ws.Activate
        ws.Cells(1, 1).Activate
    Next
    
    '一番左のシートを選択
    Worksheets(1).Activate

End Sub
```

# 5. 参考文献
こちらはMicrosoftの公式ドキュメントです。

https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/fornext-statement

こちらは私がものすごくお世話になっている「エクセルの神髄」という解説サイト。より深く学習を進めたい方は是非。

https://excel-ubara.com/excelvba1/EXCELVBA316.html#google_vignette