【VBAリファレンス】VBA100本ノック38本目攻略:大量データを条件ごとに別シートへ自動振り分けする極意

スポンサーリンク

概要:ビジネス現場で頻出する「データ分割」の自動化

Excel業務において、一つの巨大なマスターシートから、特定の条件(担当者別、部署別、地域別など)に基づいてデータを抽出し、別々のシートや別ファイルに保存するという作業は、誰もが一度は経験するルーチンワークではないでしょうか。手作業で行えば、フィルターをかけ、コピーし、新しいシートを作成して貼り付ける……といった退屈でミスを誘発しやすい作業が続きます。「VBA100本ノック」の38本目である「1シートを複数シートに振り分け」は、まさにこの業務を効率化するための登竜門であり、VBAの実力を測る重要な指標となる課題です。本記事では、この課題を題材に、単に動くコードを書くだけでなく、大規模データにも耐えうる堅牢で再利用性の高いVBA構築の考え方を伝授します。

詳細解説:データの抽出とシート生成のロジック

この課題を解決するためのアプローチは大きく分けて二つあります。「フィルタオプション(AdvancedFilter)を使う方法」と「ループ処理で判定しながら転記する方法」です。

まず、最もパフォーマンスが高いのが「フィルタオプション」を使用する方法です。これは、特定の列のユニークなリスト(重複を除いたリスト)を抽出し、それらを順次条件としてフィルタリングを行う手法です。この手法のメリットは、VBA側で一行ずつデータを判定する必要がないため、数万行規模のデータであっても瞬時に処理が終わる点にあります。

一方で、初心者にとって理解しやすいのは「連想配列(Dictionary)」を用いた手法です。Dictionaryオブジェクトを使えば、キーに「振り分け条件(例:担当者名)」を格納し、アイテムに「対象となる行の集合」を保持させることで、効率的にデータを整理できます。今回の解説では、実務で最も汎用性が高い「Dictionaryでユニークリストを作成し、フィルタオプションで転記する」という、プロの現場で好まれるハイブリッドな手法を採用します。

サンプルコード:高速かつ堅牢な振り分け処理

以下に、データが入力されたシートから特定の列(今回はB列を想定)の値を基準にして、その値の名前が付いたシートにデータを振り分けるコードを示します。


Sub SplitDataToSheets()
    Dim wsMaster As Worksheet
    Dim wsNew As Worksheet
    Dim rngData As Range
    Dim dict As Object
    Dim key As Variant
    Dim lastRow As Long
    Dim i As Long
    
    ' 画面更新と自動計算を停止(高速化の鉄則)
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    Set wsMaster = ThisWorkbook.Sheets("Master")
    lastRow = wsMaster.Cells(wsMaster.Rows.Count, "A").End(xlUp).Row
    Set rngData = wsMaster.Range("A1").CurrentRegion
    
    ' Dictionaryでユニークなキー(振り分け条件)を取得
    Set dict = CreateObject("Scripting.Dictionary")
    For i = 2 To lastRow
        If Not dict.Exists(wsMaster.Cells(i, 2).Value) Then
            dict.Add wsMaster.Cells(i, 2).Value, Nothing
        End If
    Next i
    
    ' 振り分け実行
    For Each key In dict.Keys
        ' 既存シートがあれば削除(または処理をスキップする等の制御が必要)
        On Error Resume Next
        Application.DisplayAlerts = False
        ThisWorkbook.Sheets(key).Delete
        Application.DisplayAlerts = True
        On Error GoTo 0
        
        ' 新規シート作成
        Set wsNew = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
        wsNew.Name = key
        
        ' フィルタオプションで転記
        wsMaster.Range("D1").Value = wsMaster.Cells(1, 2).Value ' 検索条件列のタイトル
        wsMaster.Range("D2").Value = key ' 検索条件
        
        rngData.AdvancedFilter Action:=xlFilterCopy, _
            CriteriaRange:=wsMaster.Range("D1:D2"), _
            CopyToRange:=wsNew.Range("A1"), Unique:=False
            
        wsNew.Columns.AutoFit
    Next key
    
    ' 検索条件のクリアと後処理
    wsMaster.Range("D1:D2").ClearContents
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    
    MsgBox "データの振り分けが完了しました。"
End Sub

実務アドバイス:コードを「現場仕様」にするために

上記のコードは基本形ですが、実務で使うためにはいくつかの「守り」が必要です。

1. エラーハンドリングの徹底:
例えば、振り分け先となる「キー」に、シート名として使用できない文字(/や?など)が含まれている場合、コードはエラーで停止します。`Replace`関数を使用して、ファイル名やシート名として不正な文字をアンダースコアなどに置換する前処理を入れるのがプロの作法です。

2. データの更新頻度への対応:
「既存シートがあれば削除して作り直す」という処理は、データの完全性を担保する上では有効ですが、もしシートに個別のメモや書式設定がなされている場合は消えてしまいます。実務では「既存シートのデータをクリアして転記する」のか「新規作成する」のか、要件を明確にしましょう。

3. 計算負荷の管理:
`Application.ScreenUpdating = False` は必須です。これがないと、シートが生成されるたびに画面が激しく点滅し、処理速度が劇的に低下します。また、数式が多いシートを扱う場合は、`Calculation`を手動に切り替えることも忘れてはいけません。

4. データの構造を意識する:
`CurrentRegion`を使用していますが、データに空行が含まれていると正しく範囲を取得できません。データの入力規則を設けるか、`End(xlUp)`を適切に組み合わせて、確実に最終行を取得するロジックを心がけてください。

まとめ:VBAで自動化の先にある「価値」を生み出す

「1シートを複数シートに振り分ける」という作業は、単なる転記作業ではありません。これは「情報の加工・配布」という、組織の意思決定を支える重要なプロセスです。VBAでこのプロセスを完全に自動化できれば、人間は「振り分けられたデータを見て、どのような対策を打つか」という、より高次元の思考に時間を割くことができます。

VBA100本ノックの38本目は、単なる技術的な課題にとどまりません。コードを書くことで、組織の業務フローそのものを最適化するという「エンジニアリングの視点」を養う絶好のチャンスです。ぜひ、上記のサンプルコードをベースに、ご自身の業務環境に合わせてカスタマイズしてみてください。最初は小さな自動化から始まり、やがてはあなたの部署全体の業務が劇的に効率化される――それこそが、VBAを習得する最大の醍醐味です。迷わず挑戦し、自身のコードを磨き上げてください。あなたのVBAライフが、より豊かで生産的なものになることを応援しています。

タイトルとURLをコピーしました