【Excel VBA】データを別ブックに分割保存する処理(前半)

スポンサーリンク

10万行以上のデータを約100グループごとに分割して、グループ名をつけて別ブックに保存していくという結構な手間のかかる作業を一定期間ごとにやっています

現在は、この作業をVBAを使って自動で10分以内に完了させています
分割するための設定を「分割設定」シートにあらかじめ設定させておけば、次回からは「実行」ボタンをクリックするだけで自動的に作成してくれるようになっています

大分前のことなのですが、その時にどうやってVBAを書いていったのかを思い出しながら書いておきます。内容が結構盛沢山になりそうなので、1回では終わらないかもしれませんが・・・(^^;

グループごとのデータをフィルタを使って分割し別ブックに保存していく記事(前半)

スポンサーリンク

ロジックを検討する

はじめに分割前のデータについていろいろ検証してみました

・元データは改変してはいけない設定
元データ(対象ブック・シート)をコピーしてから使う
・元データのまま使っても、分割後のファイル名で保存すれば元データはそのまま
・元データには列のタイトルのほかに、表のタイトルや見出しなどがある場合が多い
 (しかもセルが結合されているケースが多い
・元データ表の最下部に注意書きなどのコメントが記入されていることがある
・分割方法は(データがランダムの場合)
 ①対象の項目列でソートしてから同一項目を選択して抜き出す方法
 ②フィルタで分割対象項目を絞って、対象以外を削除してしまう方法
 (でもソートしてから実行した方が速いはず)
元ブックには対象データシート以外のシートも存在している(説明書など)
・分割対象のシート(リスト)が複数シートある場合もあり
 (複数シートの分割も可能にしたい
「基本的なところはこんな感じ」

ロジックの検討

・処理の流れ(フローチャート)はこんな感じ

・データの抽出方法もいくつか考えられます
・まず思いつくのはソートして揃える方法ですよね
・でも、選んだのはフィルタを使う方法にしました
・フィルタで目的データ以外を抽出し、それを削除しちゃいます
・それから、フィルタを解除すれば目的データだけが残っているという方法です

重複のないリストを作成する方法の検討

・大量の列データからVBAで重複のないユニークリストをつくる主な方法は次のようなものです
 (ワークシート上で手作業でつくる方法は除いています)

・Dictionaryオブジェクト(連想配列)を使う方法
・Collectionオブジェクト を使う方法
・フィルタを使う方法
・フィルタオプション(AdvancedFilterのUnique:=True)を使う方法

Dictionaryオブジェクト(連想配列)を使ったコード

'重複しないリストを格納する (Dictionaryオブジェクト使用)
Sub Sample_Dictionary()
    Dim uDic As Object, i As Long, buf As String, uKeys As Variant
    Set uDic = CreateObject("Scripting.Dictionary")
    On Error Resume Next
    With Worksheets("Sheet1")
        For i = 1 To .Cells(1, 1).CurrentRegion.Count
            buf = Cells(i, 1).Value
            uDic.Add buf, buf
        Next
    End With
    uKeys = uDic.Keys   'Variant型の配列へ格納((0)は見出し)
    Set uDic = Nothing
End Sub

Collectionオブジェクト を使ったコード

'重複しないリストをuKeysに格納する(Collectionオブジェクト使用)
Sub Sample_Collection()
    Dim uKeys As New Collection 'Collectionオブジェクト
    Dim u As Long
    With Worksheets("Sheet1")
        On Error Resume Next   'データ重複エラーを無視する
        For u = 1 To .Cells(1, 1).CurrentRegion.Count
            uKeys.Add .Cells(u, 1).Value, .Cells(u, 1).Value 'uKeysに格納
        Next
        On Error GoTo 0
    End With
End Sub

フィルタを使ったコード

'重複しないリストを格納する(フィルタ使用)
Sub Sample_Filter()
    Dim uKeys As Variant
    With Worksheets("Sheet1")
        .Cells(1, 1).CurrentRegion.RemoveDuplicates Columns:=1, Header:=xlYes
        With .Cells(1, 1).CurrentRegion
            uKeys = .Resize(.Rows.Count - 1).Offset(1).Value '2次元配列になる
        End With
    End With
End Sub

フィルタオプション(Unique:=True)を使ったコード

'重複しないリストを格納する(フィルタオプションのUnique:=Trueを使用した例)
Sub sample_FilterOption()
    Dim LastRow As Long
    Dim uKeys As Range  
    With Worksheets("Sheet1")
        LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
        .Range(.Cells(1, 1), .Cells(LastRow, 1)).AdvancedFilter _
            Action:=xlFilterCopy, _
            CopyToRange:=.Cells(1, 2), _
            Unique:=True
        '一旦列に書き出してからオブジェクトに格納しなければならない
        LastRow = .Cells(.Rows.Count, 2).End(xlUp).Row
        Set uKeys = .Range(.Cells(1, 2), .Cells(LastRow, 2))
    End With
End Sub

どのコードを使うか検討した結果

【決定】Collectionオブジェクト を使ったコードに決めました!
【理由】扱いやすい
【コード全体の評価】どのコードも速度としては大差ありませんでした
・Dictionaryは配列に格納して使う
・フィルタを使った場合、2次元配列になる
・フィルタオプションの場合、一旦シートに書き出してから配列等に格納する手間
・Collectionオブジェクトが一番扱いやすいと思いました

まとめ

ここまでの「まとめ」と感想

データ表から同一種別データ毎に抽出して別ファイルに分割保存する方法の記事NO1
・分割前の元データについて検証した結果、いろいろなことがわかりました
・分かったことをもとに、処理の流れ(ロジック)を作成
・データ分割するための元となる「ユニークデータ」の作成方法を検討
・検討した結果「Collectionオブジェクト」を使うことに決定しました

次回の記事、そして今後は

今回の記事はいかがだったでしょうか。お役に立てたなら幸いです
次の記事は今回記事の続きです。しばしお待ちください(^^)
・データ表から同一種別データ毎に抽出して別ファイルに分割保存する方法NO2

【今後の記事内容はどうしようかなぁ・・・】
・ExcelからOutlook 2016でメールを送信する方法
・高速化した「VlookUp関数」のVBAでの活用法を再検討してみたいと思います
・その他「小ネタ」などなど・・・・・
・今後これらのどれかについて記事にしていきたいと思います。ご期待ください(^^)/

サンプルファイルをダウンロードできます(下記リンク先へ)ただし、今回記事については次回記事と合わせてアップします

今回記事については、コードをCOPYしてご利用ください
次回の記事とあわせてサンプルファイルをアップしますのでお待ちくださいm(_ _)m

記事で使用したサンプルファイルがダウンロードできるページを設置しています
こちら(このリンク先)からご利用ください