データの取り込みと集計 (手作業での操作例と、それをVBAで。)

■ Excel豆知識53





53-7 何らかの抽出を行って取り込むデータを毎月1回取り込み作業を行う(VBA)
前回「①のそのまま取り込めるデータ」を「Aの毎月1回取り込み作業を行う」マクロを作成しましたが、
今回は取込データが「②の何らかの抽出を行って取り込むデータ」に変っただけで、取込のタイミング
は「毎月1回」で同じです。
なので、前回のコードを利用して、下記の手順の青字の分だけを変更したり追加したりします。

手順
1.  取込が初回かどうかを判断する。	
2.  インプットボックスで、対象年月西暦を6桁の数字で入力してもらう。
3.  2の数字を利用してCSVファイル名を変数に取得。
4.  そのファイルの存在を確認。
       存在しない場合にはメッセージを出してマクロを終了。
5.  そのファイルのデータが既に取り込まれていないかどうかを確認。
    取り込み済なら、メッセージを出してマクロを終了。
6. 「取込ファイル名」シートにファイル名を書き込む。
7. 該当するCSVファイルを開き、フィルタオプションで欲しいデータを「取込用」シートに抽出。
8. CSVファイルを閉じる。
9.  データを貯め込んでいる「Data」シートにデータを追加し、データ範囲に名前を設定。
10.「取込用」シートは項目行だけを残してデータをDelete。	
11. 1で初回と判断した場合には、ピボットテーブルを作成してねとメッセージを表示。
     初回でなければ、ピボットテーブルを更新。
12. 上書き保存
13. ピボットシートを選択してマクロを終了。
Option Explicit

Sub データ取込()
    Dim Nengetu As Long
    Dim FName As String
    Dim DataBk As Workbook
    Dim LastRow As Long
    Dim LR As Long, i As Long
    Dim myCriteria As Range, myCopyTo As Range
    Dim Kakunin As Boolean

    '初回の取り込みで、ピボットを作る必要があるかどうかを確認
    If Worksheets("Data").Cells(Rows.Count, 1).End(xlUp).Row = 1 Then
        Kakunin = True
    End If

    '抽出条件範囲を変数に入れる
    Set myCriteria = Worksheets("条件").Range("A1:A2")
    '抽出先の項目範囲を変数に入れる
    Set myCopyTo = Worksheets("取込用").Range("A1:E1")

    '項目行を残して前回データをクリア(ないはずだけど、一応。テストもあるので。)
    Worksheets("取込用").Range("A1").CurrentRegion.Offset(1).Clear

    '対象年月取得
    Nengetu = Application.InputBox _
            (prompt:="対象年月西暦を 6桁の数字で 201403 のように入力してください。" _
	    , Title:="対象年月は?", Type:=1)
    If Nengetu = 0 Then
        Exit Sub
    End If

    'CSVファイル名を変数に取得
    FName = Dir(ThisWorkbook.Path & "\CSV保存用\" & Nengetu & "Data.CSV")

    'ファイルの存在を確認
    If FName = "" Then
        MsgBox "取り込みファイルの準備がまだのようです。" & vbCrLf & "確認してください。"
        Exit Sub
    End If

    '既に取りこんでいないかどうかを確認
    With Worksheets("取込ファイル名")
        LR = .Cells(.Rows.Count, 1).End(xlUp).Row
        For i = 2 To LR
            If .Cells(i, 1).Value = FName Then
                MsgBox "そのファイルは取り込み済です。"
                Exit Sub
            End If
        Next i
        'ここに来るのはまだ取りこんでない場合なので、ファイル名を入力
        .Cells(LR + 1, 1).Value = FName
    End With

    Application.ScreenUpdating = False

    'CSVファイルをExcelブックとして開く
    Workbooks.Open Filename:=ThisWorkbook.Path & "\CSV保存用\" & FName
    Set DataBk = ActiveWorkbook

    'テスト用を除いたデータを取得

    'フィルタオプションで抽出
    DataBk.Worksheets(1).Range("A1").CurrentRegion.AdvancedFilter _
         Action:=xlFilterCopy, CriteriaRange:=myCriteria, CopyToRange:=myCopyTo, Unique:=False

    'CSVファイルを閉じる
    DataBk.Close SaveChanges:=False

    With Worksheets("Data")
        LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
        'データシートに項目行を除いて追加
        Worksheets("取込用").Range("A1").CurrentRegion.Offset(1).Copy Destination:=.Cells(LastRow + 1, 1)
        'データ範囲に名前を付ける(ピボットのデータソース)
        .Range("A1").CurrentRegion.Name = "集計用データ"
    End With

    '項目行を残して取込用データをクリア
    Worksheets("取込用").Range("A1").CurrentRegion.Offset(1).Clear

    Application.ScreenUpdating = True

    If Kakunin = True Then
        '初回の取り込みならピボットテーブルを作成してねとメッセージを。(余裕があればVBAにしてもいいですが。)
        MsgBox Nengetu & "のデータを取り込みました。" & vbCrLf & "「集計用データ」をデータソースにして" _
                                 & vbCrLf & "ピボットテーブルを作成してください。"
    Else
        'ピボットを更新(初回以降ピボットテーブルが無くてもエラーにはなりません。)
        '複数のピボットテーブルがあっても、これで一度に更新できます。
        ThisWorkbook.RefreshAll
        '取り込んだよのメッセージを。
        MsgBox Nengetu & "のデータを取り込みました。"
    End If

'    '上書き保存
'    ThisWorkbook.Save
'
'    Worksheets("ピボット").Select
End Sub


ここで中心になるのは「フィルタオプション」を使った抽出の部分です。

53-2で手作業でその抽出をやってみましたが、設定の作業が結構面倒でした。でも、VBAにしてしまうと
あっけないくらいのコードになります。こちらで手作業でやってみたフィルタオプションの設定をマクロ
の記録をしたのが下のコードです。
Sub Macro1()
'
' Macro1 Macro
'

'
    Workbooks("201301Data.csv").Sheets("201301Data").Range("A1:T388"). _
        AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Sheets("条件").Range( _
        "A1:A2"), CopyToRange:=Range("A1:E1"), Unique:=False
End Sub
上記コードの赤字の部分は、抽出元になるリスト範囲で、
DataBk.Worksheets(1).Range("A1").CurrentRegion と置き換えることが出来ます。
また、フィルタオプションの条件範囲と抽出範囲は、それぞれ下記のように変数に入れましたので、
    '抽出条件範囲を変数に入れる
    Set myCriteria = Worksheets("条件").Range("A1:A2")
    '抽出先の項目範囲を変数に入れる
    Set myCopyTo = Worksheets("取込用").Range("A1:E1")
CriteriaRange:=Sheets("条件").Range("A1:A2")CriteriaRange:=myCriteriaCopyToRange:=Range("A1:E1")CopyToRange:=myCopyToと置き換えることが出来ます。

手作業では抽出先のシートを選択した状態から作業を始める必要がありましたが、VBAでは
CopyToRange:=Worksheets("取込用").Range("A1:E1")のようにシートを指定することで、どのシートが
選択状態になっていても、その抽出先に抽出することが出来ます。

AdvancedFilterのExcelのヘルプが下図ですが、今回の抽出では、引数Action:=xlFilterCopyで、抽出
結果をリストと別の場所にコピーするように指定し、引数Unique:=Falseで重複するレコードも含めて
検索条件に一致するレコードすべてを抽出するように設定しています。

今回は利用しませんが、Unique:=Trueとすると重複するレコードを無視した抽出が出来ますので、これもフィルタオプ
ションの重要な利用価値だと思います。

今回の抽出は、元データをフィルタオプションを利用して、一旦「取込用」シートに取り込み、そのデー
タをデータを貯め込んでいる「Data」シートに追加します。
なので、前回53-6で直接「Data」シートに取り込みながら追加したのより、一手間余計になります。

7. 該当するCSVファイルを開き、フィルタオプションで欲しいデータを「取込用」シートに抽出。
8. CSVファイルを閉じる。
9.  データを貯め込んでいる「Data」シートに「取込用」シートのデータを追加し、データ範囲に名前を設定。
10.「取込用」シートは項目行だけを残してデータをDelete
という流れになりますので、下のようにしました。(一部変数の使用を戻しています。ここの説明だけです。)
    'CSVファイルをExcelブックとして開く
    Workbooks.Open Filename:=ThisWorkbook.Path & "\CSV保存用\" & FName
    Set DataBk = ActiveWorkbook

    'フィルタオプションで抽出
    DataBk.Worksheets(1).Range("A1").CurrentRegion.AdvancedFilter _
         Action:=xlFilterCopy, CriteriaRange:=myCriteria, _
                   CopyToRange:=Worksheets("取込用").Range("A1:E1"), Unique:=False

    'CSVファイルを閉じる
    DataBk.Close SaveChanges:=False

    With Worksheets("Data")
        LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
        'データシートに項目行を除いて追加
        Worksheets("取込用").Range("A1").CurrentRegion.Offset(1).Copy Destination:=.Cells(LastRow + 1, 1)
        'データ範囲に名前を付ける(ピボットのデータソース)
        .Range("A1").CurrentRegion.Name = "集計用データ"
    End With

    '項目行を残して取込用データをクリア
    Worksheets("取込用").Range("A1").CurrentRegion.Offset(1).Clear
なお、「抽出条件」と「抽出範囲」を変数に代入するコードにはブックの指定をしませんでしたので、CSVファイルを開く
前にそのコードを実行できるように、上のコードよりずっと上の位置に置きました。


これで「②の何らかの抽出を行って取り込むデータ」を「Aの毎月1回取り込み作業を行う」場合のコード
も出来ました。
次は①②のデータのそれぞれを「Bの複数のファイルをまとめて取り込む」場合について考えてみます。
ページTOPへ