Excel VBA ツール作成サンプル 売上を自動集計する(完全自動編)

ExcelVBA-実用編

1記事1ツールをVBAで作るサンプルシリーズ3です。

今回はサンプルシリーズ1のツール作成サンプルで作成したツールを、完全自動化します。

決まった時間に毎日自動でデータが集計されるツールは、普段の仕事においてこれ以上にない効率化ではないでしょうか。

指定されたフォルダに自動(もしくは手動)で格納される、という条件が発生しますが、1度設定してしまえば、自分が休みの日でも自動で出力してくれますので、非常に楽です。

サンプルシリーズ1の詳細は「売上を自動集計する」をご覧下さい。

また、サンプルシリーズ1を高速化したシリーズ2は「売上を自動集計する(高速編)」をご覧下さい。

今回も過去に書いた記事で掲載した内容で作れるツールなっています

シリーズ3のポイントです。

  • タスクスケジューラで自動実行
  • 複数ファイルを1フォルダで管理
  • Bat、VBS、VBAを使用する
  • 処理済みの読み込みファイルを移動する

1.ツールを作る上で大事なこと

ツールを作るには、ある程度ツールの設計を考える必要があります。

簡単なツールであれば設計を飛ばして作成しても問題ありませんが、複雑なツールになるほど設計は大事になります。

そして、ツールは1つ1つのパーツを作り、組み立てていくことで出来上がります。

各パーツを作るときに、必ずいくつかの選択肢が発生しますので、作りたいツールに合わせた選択をしていきます。

選んだ選択によって、必ず新しい「運用ルール」が発生します。

運用や保守などを考慮しつつ、プロセスを構築するのも大事です。

2.今回使うサンプルデータ

今回は次のような注文日、注文番号、商品、単価、販売数量、売上金額の1か月分のデータ300行を使用します。

3.ツールの最終アウトプットと設計(プロセス)を考える

今回は「毎日決まった時間に、決まった形式のファイルを読み込んで、集計をして、決まったフォルダに別ファイルとして集計結果を出力する」というツールを作成します。

いきなり完成系のツールを作り始めるのではなく、まずは最終的にどのようなアウトプットを目標としているかを考えます。

そして、そのアウトプットを実現するための設計(プロセス)を考えたいと思います。

最終的なアウトプット

本当の最終は「別ファイルで保存」ですが、ここではどのように集計するかを考えます。

シリーズ1を使いますので、今回も「日別」、「商品別」の2種類の売上集計をしたいと思います。

売上と一緒に「販売数量」も一緒に集計したいと思います。

全体設計

最初は大まかで構いませんので全体設計を考えます。

今回はタスクスケジューラでBatファイルを起動して、VBscriptファイルを起動してからExcelVBAファイルを起動します。

管理するフォルダを作成する

今までと違うところはExcelVBAファイルBatファイルVBscriptファイル、そして読み込むためのファイルを格納するフォルダが必要となります。

そのため、管理が煩雑にならないために、専用フォルダを作成してそのフォルダで管理します。

今回はCドライブ直下に「Sampleシリーズ」というフォルダを作成します。

各ファイルはここに格納していきます。

その中にさらに読み込み用のファイルを格納するための「データ格納」フォルダを作成します。

また、処理済みの読み込み用ファイルを処理後に移動するための「処理済み」フォルダも作成します。

4.コードを書く

各ファイルはZipに圧縮したものを最後にダウンロードできます。

Batファイル

下記サンプルコードのBatファイルを作成したら、管理用に作成したフォルダに格納します。

詳細は「 タスクスケジューラでマクロを自動実行する 」をご覧ください。

メモ帳で構いませんので、エディタを開いて下記Sampleコード記述します。

名前を付けて保存」する際に拡張子を「.txt」から「.bat」に書き換えて保存します。

拡張子の選択には「.bat」は出てこないので、手で入力します。

Batファイルはパスの部分は「¥マーク」で良く、「””」ダブルクォーテーションでくくる必要ありません。

作成したVBSファイルのパスやファイル名は便宜書き換えてください。

今回は「Auto.bat」というファイル名で保存します。

cscript C:\Sampleシリーズ\Auto.vbs

VBscriptファイル

下記サンプルコードのBatファイルを作成したら、管理用に作成したフォルダに格納します。

詳細は「 タスクスケジューラでマクロを自動実行する」をご覧ください。

メモ帳で構いませんので、エディタを開いて下記Sampleコード記述します。

「名前を付けて保存」する際に拡張子を「.txt」から「.vbs」に書き換えて保存します。

こちらも同様に、拡張子の選択に出てこないので、手で入力します。

また、開きたいExcelファイルを指定しなおすには「“C:/Sample/Book1.xlsm”」の部分をフルパスのファイル名で便宜変更してください。

また、パスの「¥」マークはすべて「 / 」で記載してください。

今回は「Auto.vbs」というファイル名で保存します。

' Excel起動
Set oXlsApp = CreateObject("Excel.Application")
oXlsApp.Application.Visible = true
oXlsApp.Application.Workbooks.Open("C:/Sampleシリーズ/自動売上集計.xlsm")

ExcelVBAファイル

ExcelVBAは「ファイル読み込み」「集計」「ファイル出力保存」「読み込む用ファイルを移動」「ファイルOpen時実行」の5つに分けてコードを作成します。

ファイル読み込み

ファイルの読み込みは自動で行いたいので、ファイル指定で読み込みます。

Sub Sample1()

Dim Filename    As String
Dim ShCount     As Long

ShCount = ThisWorkbook.Worksheets.Count

If Dir("C:\Sampleシリーズ\データ格納\読み込み用データ.xlsx") <> "" Then

    Filename = Dir("C:\Sampleシリーズ\データ格納\読み込み用データ.xlsx")

    Workbooks.Open "C:\Sampleシリーズ\データ格納\読み込み用データ.xlsx"
    
    Worksheets(1).Copy after:=ThisWorkbook.Worksheets(ShCount)
    
    Workbooks(Filename).Close savechanges:=False
    
    ActiveSheet.Name = "データ"
    
    'データをチェックする
    With ActiveSheet
    
        '項目が注文日/注文番号/商品/単価/販売数量/売上金額であることが条件
        If Not (.Cells(1, 1) = "注文日" And _
            .Cells(1, 2) = "注文番号" And _
            .Cells(1, 3) = "商品" And _
            .Cells(1, 4) = "単価" And _
            .Cells(1, 5) = "販売数量" And _
            .Cells(1, 6) = "売上金額") Then
            
            Application.DisplayAlerts = False
            .Delete
            Application.DisplayAlerts = True
            
            MsgBox "集計できないデータ形式です。"
            
            End
            
        End If
    
    End With
    
Else

    MsgBox "ファイルがありません。"
    End
End If

End Sub
集計

集計部分のコードです。

こちらは「ツール作成サンプル 売上を自動集計する」の目次「集計するコード」そのまま使用しています。

Sub Sample2()

    Dim MaxRow1     As Long
    Dim MaxRow2     As Long
    Dim i           As Long
    Dim ImpWS       As Worksheet
    Dim OutWS       As Worksheet
    Dim DateDic     As Object
    Dim ItemDic     As Object
    Dim myVal       As Variant
    Dim DateKey     As Variant
    Dim ItemKey     As Variant
    
    Const title1    As String = "日別売上"
    Const title2    As String = "商品別売上"
    
    Application.ScreenUpdating = False
    
    Set DateDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    Set ItemDic = CreateObject("Scripting.Dictionary") 'Dictionaryをセット
    
    Set ImpWS = Worksheets("データ")
    
    Worksheets.Add after:=Worksheets(Worksheets.Count)
    ActiveSheet.Name = "集計結果"
    Set OutWS = Worksheets("集計結果")
    
    With ImpWS
        
        MaxRow1 = .Cells(Rows.Count, 1).End(xlUp).Row
        
        '■■日付のリスト作成■■
        For i = 2 To MaxRow1
            
            myVal = .Cells(i, 1)
        
            If Not DateDic.exists(myVal) Then
    
                DateDic.Add myVal, ""
            
            End If
        
        Next i
        
        DateKey = DateDic.keys
        
        '■■商品のリスト作成■■
        For i = 2 To MaxRow1
            
            myVal = .Cells(i, 3)
        
            If Not ItemDic.exists(myVal) Then
    
                ItemDic.Add myVal, ""
            
            End If
        
        Next i
        
        ItemKey = ItemDic.keys
           
    End With
    
    With OutWS
    
        '■■アウトプット作成■■
        .Cells(2, 2) = title1
        .Cells(3, 2) = ImpWS.Cells(1, 1)
        .Cells(3, 3) = ImpWS.Cells(1, 5)
        .Cells(3, 4) = ImpWS.Cells(1, 6)
        .Cells(2, 6) = title2
        .Cells(3, 6) = ImpWS.Cells(1, 3)
        .Cells(3, 7) = ImpWS.Cells(1, 5)
        .Cells(3, 8) = ImpWS.Cells(1, 6)
        
        For i = 0 To UBound(DateKey)
        
            .Cells(i + 4, 2) = Format(DateKey(i), "yyyy/mm/dd")
        
        Next i
        
        .Cells(i + 4, 2) = "総計"
        
        For i = 0 To UBound(ItemKey)
        
            .Cells(i + 4, 6) = ItemKey(i)
        
        Next i
        
        .Cells(i + 4, 6) = "総計"
        
        '■■集計する■■
        MaxRow2 = .Cells(Rows.Count, 2).End(xlUp).Row
        
        For i = 4 To MaxRow2 - 1
        
            .Cells(i, 3) = Application.WorksheetFunction.SumIf _
            (Range(ImpWS.Cells(2, 1), ImpWS.Cells(MaxRow1, 1)), .Cells(i, 2), Range(ImpWS.Cells(2, 5), ImpWS.Cells(MaxRow1, 5)))
            
            .Cells(i, 4) = Application.WorksheetFunction.SumIf _
            (Range(ImpWS.Cells(2, 1), ImpWS.Cells(MaxRow1, 1)), .Cells(i, 2), Range(ImpWS.Cells(2, 6), ImpWS.Cells(MaxRow1, 6)))
        
        Next i
        
        .Cells(MaxRow2, 3) = Application.WorksheetFunction.Sum(Range(.Cells(4, 3), .Cells(MaxRow2 - 1, 3)))
        .Cells(MaxRow2, 4) = Application.WorksheetFunction.Sum(Range(.Cells(4, 4), .Cells(MaxRow2 - 1, 4)))
        
        '■■装飾する■■
        Range(.Cells(3, 2), .Cells(MaxRow2, 4)).Borders.LineStyle = xlContinuous '罫線
        Range(.Cells(3, 2), .Cells(3, 4)).Interior.Color = RGB(64, 64, 64) '背景色
        Range(.Cells(3, 2), .Cells(3, 4)).Font.Color = RGB(255, 255, 255) '文字色
        Range(.Cells(3, 2), .Cells(3, 4)).HorizontalAlignment = xlCenter '中央揃え
        
        '■■集計する■■
        MaxRow2 = .Cells(Rows.Count, 6).End(xlUp).Row
        
        For i = 4 To MaxRow2 - 1
        
            .Cells(i, 7) = Application.WorksheetFunction.SumIf _
            (Range(ImpWS.Cells(2, 3), ImpWS.Cells(MaxRow1, 3)), .Cells(i, 6), Range(ImpWS.Cells(2, 5), ImpWS.Cells(MaxRow1, 5)))
            
            .Cells(i, 8) = Application.WorksheetFunction.SumIf _
            (Range(ImpWS.Cells(2, 3), ImpWS.Cells(MaxRow1, 3)), .Cells(i, 6), Range(ImpWS.Cells(2, 6), ImpWS.Cells(MaxRow1, 6)))
        
        Next i
        
        .Cells(MaxRow2, 7) = Application.WorksheetFunction.Sum(Range(.Cells(4, 7), .Cells(MaxRow2 - 1, 7)))
        .Cells(MaxRow2, 8) = Application.WorksheetFunction.Sum(Range(.Cells(4, 8), .Cells(MaxRow2 - 1, 8)))
        
        '■■装飾する■■
        Range(.Cells(3, 6), .Cells(MaxRow2, 8)).Borders.LineStyle = xlContinuous  '罫線
        Range(.Cells(3, 6), .Cells(3, 8)).Interior.Color = RGB(64, 64, 64)  '背景色
        Range(.Cells(3, 6), .Cells(3, 8)).Font.Color = RGB(255, 255, 255)  '文字色
        Range(.Cells(3, 6), .Cells(3, 8)).HorizontalAlignment = xlCenter   '中央揃え
        
        .Columns.AutoFit
        
    End With
    
    Application.DisplayAlerts = False
        ImpWS.Delete
    Application.DisplayAlerts = True
    
    Application.ScreenUpdating = True

End Sub
ファイル出力保存

ファイルの出力保存はダイアログボックスではなく、フォルダを指定して自動保存を行います。

保存するフォルダを指定して、「Move」でシートごと移動させます。

「集計結果日付(yyyy_mm_dd-hh-mm-ss)」でファイル名を指定して保存します。

Sub Sample3()

    Dim Filename    As String
    Dim SaveFolder  As String
    Dim OutWS       As Worksheet
    
    Set OutWS = Worksheets("集計結果")
    
    SaveFolder = "C:\Sampleシリーズ\"
    
    With OutWS
    
        .Move
        ActiveWorkbook.SaveAs _
        Filename:=SaveFolder & "集計結果" & Format(Now(), "yyyy_mm_dd-hh-mm-ss"), _
        FileFormat:=xlWorkbookDefault
        ActiveWorkbook.Close
        
    End With
    
End Sub

読み込み用ファイルを移動する

処理した読み込み用ファイルは次回の集計時に邪魔になりますので、処理後に移動しておきます。

移動時にファイル名を「読み込み用データ日付(yyyy_mm_dd-hh-mm-ss)」と変更しています。

詳細は「FileSystemObjectでファイルを移動」をご覧ください。

最後に「.Close」で自身のExcelVBAファイルを閉じます。

※ブックは閉じますが、Excelのアプリケーションは閉じません。

Sub Sample4()

Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")

On Error GoTo ErrLabel
    
    FSO.MoveFile Source:="C:\Sampleシリーズ\データ格納\読み込み用データ.xlsx", _
                        Destination:="C:\Sampleシリーズ\処理済み\読み込み用データ" & _
                        Format(Now(), "yyyy_mm_dd-hh-mm-ss") & ".xlsx"
                        
    
    With ThisWorkbook
    .Save
    .Close
    End With
    
    Exit Sub
    
ErrLabel:

    MsgBox Err.Description
    End

End Sub

ファイルOpen時実行

前回まではボタンを設置して、ボタンを押したら実行されるようにしていましたが、今回はファイルを開いたら自動実行されるようにします。

そのためには「ThisWorkbook」モジュールにSample1~3のコードを読み出すコードを書きます。

「 ThisWorkbook」モジュール?? というかたは、次の画面のThisWorkbookをWクリックして、Workbookを選択してください。

自動でOpenが最初に選択されると思いますので、そこに次のコードをコピペしてください。

プロシージャ名は「Workbook」の「Open」を選択したら自動で記述されます。

Private Sub Workbook_Open()

    Call Sample1
    Call Sample2
    Call Sample3
    Call Sample4
    
End Sub
タスクスケジューラの設定

こちらの詳細は「タスクスケジューラでマクロを自動実行する」を参照してください。

タスクスケジューラの設定は、Batファイルが出来ていないと設定できませんので、まず先に下記Batファイルを作成してください。

ファイルを指定して実行」で「taskschd.msc /s」を入力してタスクスケジューラを開きます。

基本タスクの設定」を選択 し、「タスク名を付ける」、「トリガーの設定」、「開始日と時間を設定する」、「操作するタスクの種類を選択」、「プログラムを選択する」の工程を設定します。

5.実行結果

実行前

実行前の管理用に作った「Sampleシリーズ」というフォルダ内は次のようになっていると思います。

読み込み用のデータ格納フォルダと、BatファイルをとVBSファイル、そしてExcelVBAファイルの構成になっています。

データ格納フォルダ内には「読み込み用データ.xlsx」というファイルが入っています。

実行後

タスクスケジューラが設定した時間になったら実行が開始されますが、試しに手動で実行してみます。

手動で実行する方法は、 タスクスケジューラ ライブラリを更新すると、先ほど設定したタスクが追加されているかと思いますので、右クリックすると実行が選択できます。

新しい集計結果のファイルが出力されています。

「処理済み」フォルダに今回読み込んだファイルが日付を付けたファイル名で移動されています。

データ格納フォルダにはファイルはありません。

6.注意事項

ここでは毎日読み込み用のファイルがあることを前提としているため、なかった場合や形式の違うデータが格納されていた場合は、MsgBoxで止まってしまいます。

そこを回避するような処理は組み込まれていませんので、便宜対応してください。

単純にエラーで止めたくない場合は各プロシージャのMsgboxをコメントアウトしてください

読み込むためのファイル名も固定で指定しているので、こちらも便宜変更が必要になります。

処理が終わったあとにファイルを移動する場合は次の記事をご覧ください。

また、Bat→VBS→VBAや格納用のフォルダ名等、各パスやファイル名は参照先を間違えやすいので注意してください。

7.サンプルコード

次のサンプルデータを格納したZipファイルを、Cドライブ直下に 解凍 してください。

デスクトップに設置しても動きません。

もし他の場所に解凍した場合は、手動でCドライブに移動してください。

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