VBAでシートを指定行数ごとに分割して複数ファイルへ保存する
マクロブックのアクティブシート(元シート)にあるデータを以下の条件で新しいファイルを作成
- 「元シート」の一行目をヘッダー行として新しいファイルにコピーする
- 新しいファイル名は、「NewFile_」(定数で指定)の後に、連番を追加
- 新しいファイルの保存先は、マクロブックと同じフォルダ
- 一つのファイルの最大行は1000行(定数で指定)
- B列に入っている値が一つ上の行と同じの場合は二つのファイルに分かれないようにする (コピーする列を繰り上げるなど)
以下がマクロです。
Private Sub CopyDataToNewFiles()
Const maxRows As Long = 1000
Const newFileName As String = "NewFile_"
Dim newWb As Workbook
Dim ws As Worksheet, newWs As Worksheet
Dim newRow As Long, newFileNum As Long
Dim lastRow As Long, currentRow As Long
Dim newFileMake As Boolean: newFileMake = True
Dim currentStartRow As Long
' アクティブシートを指定
Set ws = ThisWorkbook.ActiveSheet
' 最終行を取得
lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row
' 新しいファイルにコピーするための変数を初期化
'newFileNum = 0
' データをコピー
For currentRow = 2 To lastRow
' ファイルを新作
If newFileMake Then ' 新しいファイルの作成フラグ
If Not newWb Is Nothing Then
' 保存して閉じる
newWb.Close SaveChanges:=True
End If
newFileMake = False
' 新しいブックを作成
Set newWb = Workbooks.Add
Set newWs = ActiveSheet
' ヘッダー行をコピー
ws.Rows(1).Copy Destination:=newWs.Rows(1)
' 新しいファイルを保存
newFileNum = newFileNum + 1
newWb.SaveAs ThisWorkbook.Path & "\" & newFileName & Format(newFileNum, "0") & ".xlsx"
newRow = 2 ' 新ファイルの行数
currentStartRow = currentRow ' コピー元先頭行
End If
' 一つのファイルの最大行が1000行+b列に入っている値が一つ上の行と違う場合は新しいファイルを作成
' 最後の行の時も実行
If (newRow >= maxRows And ws.Cells(currentRow, 2).Value <> ws.Cells(currentRow + 1, 2).Value) _
Or currentRow = lastRow Then
newFileMake = True ' 新しいファイルの作成フラグ
' 複数行をコピー
ws.Rows(currentStartRow & ":" & currentRow).Copy Destination:=newWs.Rows("2:" & newRow)
End If
newRow = newRow + 1 ' 新ファイルの行数
Next currentRow
' 保存して閉じる
newWb.Close SaveChanges:=True
' 完了メッセージ
MsgBox newFileNum & "個のファイルを作成しました。"
End Sub元データの例
例えば次のようなデータがあるとします。
| 商品コード | 得意先 | 商品名 |
|---|---|---|
| 1 | A社 | 商品1 |
| 2 | A社 | 商品2 |
| 3 | A社 | 商品3 |
| 4 | B社 | 商品4 |
| 5 | B社 | 商品5 |
| 6 | C社 | 商品6 |
| 7 | C社 | 商品7 |
| 8 | C社 | 商品8 |
| 9 | D社 | 商品9 |
| 10 | D社 | 商品10 |
ここでは説明用に最大行数を5行とします。
単純に5行で分割した場合
NewFile_1.xlsx
| 商品コード | 得意先 | 商品名 |
|---|---|---|
| 1 | A社 | 商品1 |
| 2 | A社 | 商品2 |
| 3 | A社 | 商品3 |
| 4 | B社 | 商品4 |
| 5 | B社 | 商品5 |
NewFile_2.xlsx
| 商品コード | 得意先 | 商品名 |
|---|---|---|
| 6 | C社 | 商品6 |
| 7 | C社 | 商品7 |
| 8 | C社 | 商品8 |
| 9 | D社 | 商品9 |
| 10 | D社 | 商品10 |
この場合は問題ありません。
B列の値が途中で分割されそうな場合
例えば次のようなデータです。
| 商品コード | 得意先 | 商品名 |
|---|---|---|
| 1 | A社 | 商品1 |
| 2 | A社 | 商品2 |
| 3 | A社 | 商品3 |
| 4 | A社 | 商品4 |
| 5 | A社 | 商品5 |
| 6 | A社 | 商品6 |
| 7 | B社 | 商品7 |
| 8 | B社 | 商品8 |
| 9 | C社 | 商品9 |
最大行数を5行に設定すると、本来は5行目で分割されます。
しかしA社のデータが続いているため、
NewFile_1.xlsx
| 商品コード | 得意先 |
|---|---|
| 1 | A社 |
| 2 | A社 |
| 3 | A社 |
| 4 | A社 |
| 5 | A社 |
| 6 | A社 |
NewFile_2.xlsx
| 商品コード | 得意先 |
|---|---|
| 7 | B社 |
| 8 | B社 |
| 9 | C社 |
となります。
つまり、
B列の値が変わるタイミングまで分割を延期
しています。
マクロの処理の流れ
① アクティブシートを取得
Set ws = ThisWorkbook.ActiveSheetマクロブックで現在表示されているシートを処理対象とします。
② B列の最終行を取得
lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).RowB列の最終データ行を取得します。
③ 新しいブックを作成
Set newWb = Workbooks.Add
Set newWs = ActiveSheet分割先となる新規ブックを作成します。
④ ヘッダー行をコピー
ws.Rows(1).Copy Destination:=newWs.Rows(1)元シートの1行目を新しいブックへコピーします。
これにより全ての分割ファイルに見出し行が付きます。
⑤ ファイル名を付けて保存
newWb.SaveAs _
ThisWorkbook.Path & "\" & _
newFileName & _
Format(newFileNum, "0") & _
".xlsx"作成されるファイル名は、
NewFile_1.xlsx
NewFile_2.xlsx
NewFile_3.xlsxのようになります。
⑥ 分割タイミングを判定
If (newRow >= maxRows And _
ws.Cells(currentRow, 2).Value <> _
ws.Cells(currentRow + 1, 2).Value) _
Or currentRow = lastRow Thenここがこのマクロの重要な部分です。
以下の条件を両方満たした時に分割します。
- 指定行数に達した
- 次行のB列の値が異なる
そのため、
A社
A社
A社
A社
A社
A社の途中では分割されません。
⑦ ファイルを保存して閉じる
newWb.Close SaveChanges:=True分割ファイルを保存し、自動的に閉じます。
実行結果
例えば5000行のデータを処理すると、
NewFile_1.xlsx
NewFile_2.xlsx
NewFile_3.xlsx
NewFile_4.xlsx
NewFile_5.xlsxのような複数ファイルが自動生成されます。
各ファイルにはヘッダー行が付き、B列の同じ値のデータは別ファイルに分割されません。
まとめ
このマクロの特徴は次のとおりです。
- 指定行数ごとにExcelファイルを分割
- ヘッダー行を自動コピー
- 連番付きファイル名で保存
- B列の同一データを分断しない
- 大量データの分割やシステム連携に便利
CSV出力やシステム取込用のデータ作成で特に役立つマクロです。


