Excel活用

CSVデータから必要な列だけをコピーするマクロの作り方③【任意の列のコピー:Forの二重ループと条件分岐】

さて、前回まででコピペの方法、Forを使った繰り返し処理について見てきました。

今回はいよいよCSVデータから必要な列だけをコピーするマクロの本丸、「任意の列をコピーする方法」について見ていきましょう!

任意の列をコピーするステップ

事前準備

1.コピー元のデータ(input_sheet)

2.コピー対象列のリスト(選択列シート)

3.コピー先シート(output_sheet)※今は白紙の状態

選択列シートをもとに、input_sheetからコピーしてoutput_sheetに貼り付けます。

これをマクロの作業として書くと・・・

  1. 選択列リストの各項目を、コピー元データの列名と総当たり照合
  2. 選択列リストの列名とコピー元データの列名が一致したとき、
  3. コピー元データの列をコピーしてoutput_sheetに貼り付ける

ここでのポイントは①で、選択列とコピー元の列名の総当たりで照合しているの分かります?

これがどういうことかというと、横軸と縦軸の二重で繰り返し処理を行っていますよね。

前回の記事では単純な繰り返し処理でしたので、ここではやや複雑な繰り返し処理が行われていることになります。

なので、まずはForによる繰り返し処理を二重について見ていきましょう。

Forの二重処理

ちょうどよい例題がこちら。

(問題)次の九九の表を、下記のようにマクロを使って埋めてください。

これを、前回の内容だけで書くとこうなります。

Sub 九九()

Dim i As Long

For i = 1 To 9
    Cells(2, i + 1).Value = Cells(2, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(3, i + 1).Value = Cells(3, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(4, i + 1).Value = Cells(4, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(5, i + 1).Value = Cells(5, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(6, i + 1).Value = Cells(6, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(7, i + 1).Value = Cells(7, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(8, i + 1).Value = Cells(8, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(9, i + 1).Value = Cells(9, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
    Cells(10, i + 1).Value = Cells(10, 1).Value * Cells(1, i + 1).Value
Next

End Sub

1の段から順番に9の段までの掛け算の結果を各セルにセットするわけですが・・・

め・ん・ど・く・さ・い!!

ですよね。

こんなめんどくさいことできません。

で、書いている内容を見てみると、一部しか違わないことが分かります。

For i = 1 To 9
Cells(2, i + 1).Value = Cells(2, 1).Value * Cells(1, i + 1).Value
Next

For i = 1 To 9
Cells(3, i + 1).Value = Cells(3, 1).Value * Cells(1, i + 1).Value
Next

・・・

このように、赤字のところしか変わりません。

であれば、ここもFor~Nextで繰り返し処理すればいいのです。

なので答えはこうです。

Sub 九九2()

Dim i As Long '横軸
Dim j As Long '縦軸

For j = 1 To 9
    For i = 1 To 9
        Cells(j + 1, i + 1).Value = Cells(j + 1, 1).Value * Cells(1, i + 1).Value
    Next
Next

End Sub

めちゃくちゃすっきりしましたね。

これで、1段から9段までの掛け算を実行するマクロが出来上がりです。

ちなみにこの挙動を動画にするとこんな感じです。

ここでは処理ごとにコンマ1秒待て、という指示を入れてます。

・・・
For j = 1 To 9
    For i = 1 To 9
        Cells(j + 1, i + 1).Value = Cells(j + 1, 1).Value * Cells(1, i + 1).Value
        Application.Wait [Now() + "00:00:00.1"]
  Next
Next
・・・

ここまで来たらあと少しです。

次に任意の列をコピーするマクロの書き方を見てみましょう。

任意の列をコピーするマクロの書き方

改めて各シートの関係を確認しておきます。

次からVBAの記述を見ていきます。

変数宣言と指定

Dim i As Long 'コピー元列数
Dim j As Long 'コピー元行数
Dim k As Long 'コピーリスト行数
Dim l As Long 'コピー先列インデックス

i = Sheets(1).Cells(1, Columns.Count).End(xlToLeft).Column
j = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row
k = Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row
l = 1

まずは変数宣言から。

今回は4つの変数を使います。

それぞれ意味は上記の通りで、宣言と定義を行っています。

ちなみに、コピー先インデックスについては1列目からスタートのため、「1」としています。

各列のコピーと貼り付けの繰り返し

各列のコピー・貼り付けを繰り返すにはこのように書きます。

For i = 1 To i
  Range(Sheets(1).Cells(1, i), Sheets(1).Cells(j, i)).Copy Sheets(3).Cells(1, l)
  l = l + 1
Next

Rangeを使ってSheets(1)の列を選択してコピーし、Sheets(3)に貼り付けます。

それを、For~Nextで列数の分だけ繰り返しています。

ここでのポイントは「l=l+1」ですね。

この式を入れることで、次のiの時に使うlを再指定しています。

iが1の時は1列目を選択してコピーしてSheets(3)の1(=l)列目に貼り付け、lに1を加算して2とした状態でi=2に移ります。

とりあえず、これで列をコピーして貼り付けることができました。

これだけではいらない列もコピーしますので、要る列だけコピーする方法、つまり条件分岐について見ていきます。

条件分岐する方法

考え方はこうです。

選択列(1)に対して列名が一致するとき、その列をコピーして貼り付け、一致しないときは何もしない。そして選択列(2)へいく。

まさにこのイメージです。

考え方は九九の段をマクロで書いたのと同じです。

で、条件分岐するときの書き方がこちら。

IF 条件式 Then
  条件を満たす時の処理(なければ省略可)
Else
  条件を満たさないときの処理(なければ省略可)
End If

実際に書くとこうです。

For k = 1 To k ’コピーリストの行インデックス
    For i = 1 To i ’コピー元の列インデックス
        If Sheets(1).Cells(1, i).Value = Sheets(2).Cells(k, 1).Value Then
            Range(Sheets(1).Cells(1, i), Sheets(1).Cells(j, i)).Copy Sheets(3).Cells(1, l)
            l = l + 1 ’GOTO次の列
        Else
            ’※条件を満たさないときは処理なし
        End If
    Next
Next

次、まとめます。

まとめ

変数宣言と定義、条件判定とコピー処理の記述をまとめます。

Sub 列コピー()

Dim i As Long 'コピー元列数
Dim j As Long 'コピー元行数
Dim k As Long 'コピーリスト行数
Dim l As Long 'コピー先列インデックス

i = Sheets(1).Cells(1, Columns.Count).End(xlToLeft).Column
j = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row
k = Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row
l = 1

For k = 1 To k
    For i = 1 To i
        If Sheets(1).Cells(1, i).Value = Sheets(2).Cells(k, 1).Value Then
            Range(Sheets(1).Cells(1, i), Sheets(1).Cells(j, i)).Copy Sheets(3).Cells(1, l)
            l = l + 1           
        End If
    Next
Next

End Sub

これで、input_sheetから選択列シートでした列名の列のみをoutput_sheetにコピーするマクロの完成です。

最後に

いかがだったでしょうか。

ポイントはこの3点。

  1. 選択列リストとインプットデータの列の照合をFor~Nextの二重ループで処理すること。
  2. IF関数で条件判定して一致の場合にコピー処理すること。
  3. output_sheetの列インデックスを条件を満たす場合のみカウントアップするようにすること

この3点を踏まえて作ると比較的簡単に作れるのではないでしょうか。

次回は列選択のためのユーザーフォームの作り方について書いていきます。

ここまで読んでいただき、ありがとうございました!