Excelで大量の売上データをひとつのシートで管理していると、「月ごとに分けて整理したい」という場面がよく出てきます。手動でコピー&ペーストするのは時間がかかり、ミスも発生しやすいです。
この記事では、1つのシートにある日付付きデータを月ごとのシートに自動で振り分けるマクロを解説します。
データを月ごとにシート分割するには?
A列に日付が入った「元データ」シートを読み込み、日付の年月(yyyymm)をシート名にして月別シートに自動振り分けします。シートが存在しない月は自動で新規作成されます。
Sub SplitDataByMonth()
Dim sws As Worksheet
Dim tws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim m_name As String
' 元のシートを設定
Set sws = ThisWorkbook.Sheets("元データ")
' 最終行を取得
lastRow = sws.Cells(sws.Rows.Count, 1).End(xlUp).Row
' ループでデータを月ごとに処理
For i = 2 To lastRow
' A列の日付から年月を取得(例:202501)
m_name = Format(sws.Cells(i, 1).Value, "yyyymm")
' 月ごとのシートが存在するか確認
On Error Resume Next
Set tws = ThisWorkbook.Sheets(m_name)
On Error GoTo 0
' シートがなければ新規作成
If tws Is Nothing Then
Set tws = ThisWorkbook.Sheets.Add
tws.Name = m_name
End If
' 該当行を月別シートにコピー
sws.Rows(i).Copy tws.Rows(tws.Cells(tws.Rows.Count, 1).End(xlUp).Row + 1)
' 変数をリセット(次のループで誤検知しないため)
Set tws = Nothing
Next i
MsgBox "データの分割が完了しました!"
End Sub
コードのポイントを理解するには?
Format(日付, "yyyymm")
日付値を「202501」のような年月の文字列に変換します。これをシート名として使います。
On Error Resume Next〜On Error GoTo 0
指定した名前のシートが存在しない場合、Sheets(m_name) はエラーになります。On Error Resume Next でそのエラーを一時的に無視し、tws Is Nothing で「シートがなかった」かどうかを判定しています。
Set tws = Nothing
ループの最後に変数をリセットしておかないと、次の行で別の月を処理するときに前回のシートが残ったままになって誤判定が起きます。必ずリセットしましょう。
特定の列だけコピーするには?
行全体ではなく、A列(日付)とB列(金額)だけを月別シートにコピーしたい場合は Resize を使います。
' A列とB列(2列分)だけコピーする
sws.Cells(i, 1).Resize(1, 2).Copy _
tws.Cells(tws.Cells(tws.Rows.Count, 1).End(xlUp).Row + 1, 1)
Resize(1, 2) は「1行・2列分」の範囲を表します。コピーしたい列数に合わせて数値を変えてください。
まとめ
Format(日付, "yyyymm")で日付を年月文字列に変換してシート名に使うOn Error Resume Next〜tws Is Nothingでシートの存在確認と自動作成を行う- ループの末尾に
Set tws = Nothingを入れて変数を毎回リセットする - 特定の列だけコピーするには
Resize(1, 列数)を使う - 月別整理・レポート作成・チーム共有など定期的なデータ整理業務に大きく役立つ
よくある質問
月ではなく担当者や部門ごとにシート分割することはできますか?
できます。m_name = Format(日付, "yyyymm") の部分を m_name = sws.Cells(i, 2).Value のように担当者名や部門名が入っている列に変えるだけで同じ仕組みが使えます。
分割先のシートにヘッダー行も入れたいのですが、どうすればいいですか?
シートを新規作成したタイミング(If tws Is Nothing Then のブロック内)で sws.Rows(1).Copy tws.Rows(1) を実行するとヘッダー行をコピーできます。
実行するたびに月別シートにデータが追記されてしまいます。毎回クリアして実行したい場合はどうすればいいですか?
マクロの先頭で既存の月別シートを削除してから実行する処理を追加します。Application.DisplayAlerts = False で確認ダイアログを非表示にしてからシートを削除し、最後に True に戻すと自動削除できます。
A列の日付がテキスト形式で入力されている場合は動きますか?
テキスト形式の日付には Format 関数が正しく機能しない場合があります。その際は CDate(sws.Cells(i, 1).Value) で日付型に変換してから Format を適用してください。
大量データ(1万行以上)で実行すると遅い場合はどうすればいいですか?
マクロの先頭に Application.ScreenUpdating = False と Application.Calculation = xlCalculationManual を追加し、末尾で元に戻すと処理速度が大幅に改善します。
動画で学びたい方へ
「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。
VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。



