VBAで区切った文字数分の行を挿入して、一覧を作成する方法をご紹介したいと思います。
どのようなケースに対する処理かと言いますと、1つの項目に対し「レッド・ブルー・グリーン」など1つのセルに複数の文字列が、繋がって入力されているセルを分解して、区切られた文字数分の行を追加して一覧を作成したい時に使用します。
データの前処理をする際に実際に直面した内容でしたので、実務的な内容になっています。
具体的な例をもとに説明していきます。
最適化されたロジックではないかもしれませんので、あくまでも手法の1つとして参考にしてください。
行の基本的な操作については「行の選択、取得、追加(挿入)、削除」をご覧ください。
1.使用するデータと処理後のデータ
まずは使用する処理前のデータと、今回の処理を行った後のデータについてです。
見て頂ければ大体の内容がわかるかと思います。
処理前のデータ
下の図のように、カラー項目が1つのセルに大量に色が「・」で区切られて入力されています。
もしこれが何かしらのマスタとなっていた場合は、とてもじゃないですが汎用性がありません。
処理後のデータ
今回の処理を行ってカラーをすべて区切り、区切った文字数分の行を挿入して一覧にしています。
10行程度ですと手動でも対応できるかもしれませんが、これが数百行になるだけでも手動では厳しい作業になります。
2.処理をするコード
それでは実際に処理をするVBAについてご紹介したいと思います。
実際のコードはそんなに複雑でもなく、長くもないです。
サンプルコード
上記の図の処理を行った実際のコードです。
Sub Sample1()
Dim i As Long
Dim n As Long
Dim MaxRow As Long
Dim MyStr As String
Dim temp As Variant
Dim AddRow As Long
'最終行を取得する
MaxRow = Cells(Rows.Count, 1).End(xlUp).Row
'行を挿入する場合は下から
For i = MaxRow To 2 Step -1
'分解したいセルを指定する
MyStr = Cells(i, 2)
',で区切って変数に格納する
temp = Split(MyStr, "・")
'区切った要素数を取得する
AddRow = UBound(temp)
'行挿入の際に要素数0だとエラーになるので判定する
If AddRow > 0 Then
'要素数分行挿入する
Range("A" & i + 1).Resize(AddRow).EntireRow.Insert
End If
'要素数分ループして基準となる項目を反映して、区切った文字列を入力する
For n = 0 To AddRow
Cells(i + n, 1) = Cells(i, 1)
Cells(i + n, 2) = temp(n)
Next n
Next i
End Sub
コードの説明
基本的には行挿入は逆から行います。
コメントにも記載していますが、簡単にですが説明です。
「MaxRow = Cells(Rows.Count, 1).End(xlUp).Row」で行数が増えても対応できるように、最終行を取得します。
「For i = MaxRow To 2 Step -1」で最終行から項目の下の2行目まで下から上にループします。
Step-1とすることでカウントアップを-1ずつ行えます。
「MyStr = Cells(i, 2)」で区切りたいセルを変数に格納します。
変数に格納せず直接セルを参照しても可能です。
「temp = Split(MyStr, “・”)」で格納した文字列を「・」で区切ります。
もし区切り文字に統一がない場合は、手動でもVBAでも区切り文字を置換で統一すると区切り漏れがなくなります。
「AddRow = UBound(temp)」で区切った要素数を取得して、行挿入時の行数を取得します。
「If AddRow > 0 Then」で要素数が0以上か判定していますが、6行のブラックのみのような要素が1つの場合は区切った場合要素が0になりますので、次の行挿入時にエラーになってしまいます。
「Range(“A” & i + 1).Resize(AddRow).EntireRow.Insert」で行挿入を行います。
『 Range(“A” & i + 1) 』部分で基準となる行の1つ下に挿入します。
「 Resize(AddRow) 」で追加したい行数を先ほど取得した、要素数を指定して要素数分行挿入します。
「For n = 0 To AddRow」で要素数分ループして追加した行に基準の文字列と、区切った文字列を各行に反映します。
行挿入は大量に行うと処理時間が長くなりますので、「Application.ScreenUpdating = False」で画面更新を停止することで処理速度を早くする事が出来ます。