2014/05/24

【VBA】指定フォルダ配下のブックを操作するためのマクロテンプレート

日本のSEはExcelがだぁ~いすき!
だから、なんでもかんでもExcelを使うよ。

そんなとき便利なのが、指定フォルダ配下のブックを操作するVBAマクロ。

例えば、「データの集計」や「ヘッダ・フッタ・更新履歴の修正」などなど。

毎回そんなマクロ組んでいたら1日が終わってしまう。
Office2003までの「FileSearch」は何かと便利だった。
しかし、Office2007以降の「FileSystemObject」は何かと厄介。

詳しくは、以下のエントリーを参照してほしい。



ということで、そんなときに使えるVBAマクロのテンプレートを紹介する。




指定フォルダ配下のブックを操作する


メイン処理は以下の通り。
ブックのみの操作の場合は、44行目にロジックを追加する。
シートの操作をする場合は、48行目にロジックを追加する。

Option Explicit

'----------------------------------------------------------------
' メイン処理
'----------------------------------------------------------------
Sub Main()
    '-- 高速化・チラツキ防止
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    '-- 指定フォルダ配下のファイルリストを取得
    Dim fileList As Collection
    '-- フォルダパスとファイルの拡張子(""で全てのファイルが対象)を指定
    Set fileList = GetBookPaths("C:\作業フォルダ", "xlsx")
    
    '-- fileListのソート(必要に応じて)
    Set fileList = SortList(fileList, SortOrder.Asc)
    
    '-- ブックを開いてデータを読み込む
    Call ReadBooks(fileList)
    
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    Application.EnableEvents = True
End Sub


'----------------------------------------------------------------
' 【機能】ブックを開いてデータを読み込む
' 【引数】fileList: 対象ファイルのリスト
' 【戻値】なし
'----------------------------------------------------------------
Sub ReadBooks(fileList As Collection)
    Dim filePath As Variant
    Dim ws As Worksheet
    Dim bookName As String
    
    '-- ブックの操作
    For Each filePath In fileList
        Workbooks.Open Filename:=filePath
        bookName = ExtractNameFromPath(CStr(filePath))
        
        'TODO:ここにロジックを追加する
        
        '-- シートの操作
        For Each ws In Workbooks(bookName).Worksheets
            'TODO:ここにロジックを追加する
            Debug.Print bookName + ":" + ws.Name
        Next
        Workbooks(bookName).Close
    Next
End Sub


モジュールは以下の通り。(クラスにした方が良かったかも)
VBEの「プロジェクトエクスプローラ」から「標準モジュール」を追加して、そのままコピペ。

Option Explicit

'-- SortListに渡すオーダーを表す列挙体
Enum SortOrder
    Asc
    Desc
End Enum


'----------------------------------------------------------------
' 【機能】指定されたpath配下のファイルの絶対パスを取得し、Collectionに入れて返す
' 【引数】path      : 検索対象フォルダの絶対パス
'         selectExt : 取得する拡張子
' 【戻値】Collection: ファイルの絶対パス
'----------------------------------------------------------------
Function GetBookPaths(path As String, selectExt As String) As Collection
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    Dim fileList As New Collection
    
    '-- 指定フォルダのパスを取得し、再帰呼出によりサブディレクトリ内と検索する
    Dim folder As Variant
    Dim tmpFile As Variant
    For Each folder In fso.GetFolder(path).SubFolders
        '-- サブフォルダ内のファイルリストを設定する
        'HACK: もうちょっとなんとかならんかね?
        For Each tmpFile In GetBookPaths(folder.path, selectExt)
            fileList.Add Item:=tmpFile
        Next
        
    Next

    '-- ファイルパスを取得する
    Dim file As Variant
    For Each file In fso.GetFolder(path).Files
        If Not IsEmpty(selectExt) Or LCase(fso.GetExtensionName(file.path)) = selectExt Then
            '-- 指定された拡張子のみ、ファイルリストに加える
            fileList.Add file.path
        End If
    Next
    
    Set GetBookPaths = fileList
End Function



'----------------------------------------------------------------
' 【機能】listをorder通りに並び替えて返す
' 【引数】list      : ソートしたいリスト
'         order     : リストの並び順(SortOrderのAsc/Desc)
' 【戻値】Collection: ソートしたリスト
'----------------------------------------------------------------
Function SortList(list As Collection, order As SortOrder) As Collection
    Dim ado As Object
    Set ado = CreateObject("ADODB.Recordset")
    
    '-- FILENAMEという名前でフィールドを作成
    ado.Fields.Append "FILENAME", 200, 300, 32
    ado.Open
    
    '-- 受け取ったlistをadoに登録する
    Dim path As Variant
    For Each path In list
        ado.AddNew
        ado.Fields(0) = path
        ado.Update
    Next
    
    '-- 指定されたorderによりソートを行う
    Select Case order
        Case SortOrder.Asc
            ado.Sort = "FILENAME ASC"
        Case SortOrder.Desc
            ado.Sort = "FILENAME DESC"
    End Select
    
    '-- ソートされたado.Filedsを戻り値sortedListに設定する
    Dim sortedList As Collection
    Set sortedList = New Collection
    
    ado.MoveFirst
    Do Until ado.EOF
        '-- CStrで文字列型にしないとRecordsetが格納されてしまう
        sortedList.Add CStr(ado.Fields(0))
        ado.MoveNext
    Loop
    
    ado.Close
    Set ado = Nothing
    
    Set SortList = sortedList
End Function


'----------------------------------------------------------------
' 【機能】絶対パスからファイル名を抽出する
' 【引数】path  : ファイル名を抽出したいパス
' 【戻値】String: ファイル名
'----------------------------------------------------------------
Function ExtractNameFromPath(path As String) As String
    '-- 絶対パスからファイル名直前の"\"の位置を取得
    Dim pos As Integer
    pos = InStrRev(path, "\") + 1
    ExtractNameFromPath = Mid(path, pos)
End Function





以上

0 件のコメント :

コメントを投稿