フォルダ内のファイルのページ数を取得する

指定フォルダ内の Officeファイル のページ数を取得します。
結果はデスクトップに「ファイルリスト_yymmdd_hhmm.xlsx」という名前で出力されます。こんな感じです。

A1セル:指定したフォルダ
B列:階層
C列:サブフォルダ
D列:ファイル名(ページ数取得対象外のファイルも含め全てのファイル)
E列:ページ数
ページ数を取得できるファイルは次の通りです
・Excel : xls ,xlsx ,xlsm, xlsb
・Word : doc ,docx ,docm
・PowerPoint :ppt ,pptx ,pptm
F列:構成情報(見出し)
G列:ファイルサイズ(MB)

はじめにこちらの過剰書きをお読みいただくようお願いします。(長くてすみません)

  • ソース34行目にある通り、Excelで参照設定が必要なライブラリがあります。環境によって少し名前が異なりますが似た名前のがあるはずなので、探して設定をお願いします。
  • htmlにおいてソース上に「&amp」や「&quot」が混入してしまうことがあるため、本ページ上のソースをコピペせず、「ソースのダウンロード(txt)」ボタンをご利用ください。(私の利用する環境のバグに起因しており、解消方法をさぐっていますが、現状は根本対処ができておりません)
  • バージョン 2203 からマイクロソフトのマクロ実行に関する制限が厳しくなりました。
    a) マクロの実行時
    b) Excel VBAからWordやPowerPointのオブジェクト操作時
    の2つのタイミングで実行がブロックされます。
    a)は他のマクロでも同様の話であり、インターネットにかなり情報があるのでそちらを参照ください。
    b)については、Excelの[ファイル]-[その他]-[オプション]で、[トラストセンター]-[トラストセンターの設定]から[マクロの設定]画面で「VBAプロジェクトオブジェクトモデルへのアクセスを信頼する」にチェックをすることでエラーが回避できます。(ただしマイクロソフトの推奨するデフォルトのセキュリティレベルを下げることになりますので、その点ご理解の上実施ください)
  • 本処理では、ページ数を出すところまでですが、フォルダごとに集計する方法についてもこのページの下部に書いてあります。
  • 動作確認の上ご利用ください。Officeファイルは状態が多く、すべての場合にきちんと動くかの検証が難しいためです。私が利用する範囲でうまく動くことを確認しています。
  • 本ページは企業からのアクセスが多いですが、本コンテンツを利用したことにより生ずるいかなる損害についても一切の責任を負いかねますので、自己責任でご利用ください。
  • バグを発見した場合はフィードバックからご連絡ください。再現可能な範囲で善処します。

どこかの誰かがページ数を数えるという単純作業から解放されますように。Good luck!

ソース

ソースのダウンロード (txt)

Option Explicit
Option Base 1

Dim FilePaths()                 'ファイルパス

Sub フォルダ内のファイルのページ数を取得する()

'------------------------------------------------------------------------------
'フォルダ内のファイルのページ数を取得
' [対応形式] Excel, Word, PowerPoint の拡張子の一部
'
' [補足1] PDFはバージョン違いによる差異の考慮が多い点と、
'         最新では処理が冗長になってしまう点を踏まえ非対応
' [補足2] Excel2007/2010は下記バグ情報あり(詳細未確認)
'         Excel 2007 および Excel 2010 で Pages.Count プロパティを取得すると実際の印刷総ページ数と異なる値を取得する
'         https://support.microsoft.com/ja-jp/help/2439589
'
' [版数 変更履歴]
'  1.10  拡張子「xlsb」を追加
'        Excelのクローズ処理を修正
'        Excelで非表示シートが表示できない場合の処理を追加
'        項目の出力を一部変更(出力順変更、ページ数/フォルダを廃止)
'        結果を出力するExcelファイルにウィンドウ枠の固定、画面スクロール処理を追加
'        結果出力後、並び替え処理を追加(サブフォルダの並びが直観的でないため並び替え)
'  1.20  Word ApplicationのQuitが漏れていたため追加
'        画面スクロールの修正
'        サブフォルダ出力の判定を修正(仮想環境でフォルダ名が大文字だったり小文字だったりする対応)
'  1.30  PowerPointにスライド0がある場合の処理を追加
'  1.40  階層数の誤りを修正
'        Wordの保護文書は見出しを無視するように修正
'        その他軽微な修正
'------------------------------------------------------------------------------

    '参照設定が必要なライブラリ([ツール]-[参照設定]で設定しておく)
    'Microsoft ActiveX Data Objects 6.1 Library
    'Microsoft PowerPoint xx.x Object Library
    'Microsoft Word xx.x Object Library
    
    Dim StartTime As Date           '開始時刻
    StartTime = Now()               '開始時刻
    Dim EndTime As Date             '終了時刻
    
    Dim MsgRtn As String            'メッセージボックスの返り値
    
    Dim WSH As Variant              'WSH(Windows Scripting Host)
    Dim FSO As Object               'ファイルシステムオブジェクト
    Dim DefaultPath As String       'ファイルダイアログのデフォルト表示パス
    Dim strFolderPath As String     'ダイアログで指定されたフォルダパス
    Dim objFolder As Object         'フォルダオブジェクト
    Dim lngFileCount As Long        '処理するファイル数
                
    Dim intDepth As Integer         '階層数
    Dim i As Long
    Dim p As Long                   'スライドカウント用変数
    
    Dim xlsworkbook As Workbook     '開いたExcelファイル
    Dim sh As Variant               'シート(worksheet,chart)
    Dim shVisible As String         'シートの表示状態
    Dim ErrShVisible As Boolean     'シート表示エラー
    Dim strHiddenSheet As String    '非表示シートの場合に結果に表示する文字列
    Dim lngShPageCount As Long      'シートのページ数
    Dim lngPageCount As Long        'ファイル内のページ数

    Dim wordApp As Word.Application 'Word
    Dim wordDoc As Word.document    'Wordファイル
    
    Dim pptApp As PowerPoint.Application    'PowerPoint
    Dim pptPrs As PowerPoint.Presentation   'PowerPointファイル
    Dim lngFirstSlideNo As Long
    
    Dim xlsWorkbookOutput As Workbook               '結果を出力するExcelファイル
    Const strBaseName  As String = "ファイルリスト" '結果を出力するファイル名の固定文字列部
    Const strExtName As String = "xlsx"             '結果を出力するファイル名の拡張子
    Dim strDate As String                           '結果を出力するファイル名の日時部
    Dim strOutputFileName As String                 '結果を出力するファイル名
    Const intColHeadColer As Long = 12566463        '表見出しの色(グレー「白、背景 1、黒 + 基本色 25%」)
    Dim x As Long                                   '出力列
    Dim y As Long                                   '出力行
    Dim temp As Long                                '一時領域(デフォルトシート数)
    
    Dim strShPageDetail As String                   'Excelの場合シート名とページ数の詳細を出力
    Dim strWdListString As Variant                  'Wordの場合リスト見出し/PowerPointの場合各スライドのタイトル
    Dim rngList As Word.Range                       'Wordのリスト
    Dim rngListNext As Word.Range                   'Wordのリスト
                    
    '--------------------------------------
    '開始メッセージ
    '--------------------------------------
    MsgRtn = MsgBox("処理を開始しますか?" & vbCrLf & vbCrLf & _
                "ページ数を取得可能な拡張子は次の通りです。" & vbCrLf & _
                "Excel : xls ,xlsx ,xlsm, xlsb" & vbLf & _
                "Word  : doc ,docx ,docm" & vbLf & _
                "PowerPoint :ppt ,pptx ,pptm" & vbLf & vbLf & _
                "[注意]" & vbCrLf & _
                "上記拡張子のファイルを開いている場合は、閉じてから実行してください。", _
                vbOKCancel + vbInformation, Title:="開始")
    If MsgRtn = vbCancel Then Exit Sub
    
    '--------------------------------------
    'フォルダを取得
    '--------------------------------------
    'フォルダダイアログ
    Set WSH = CreateObject("WScript.Shell")
    DefaultPath = WSH.SpecialFolders("Desktop") & "\"   'デスクトップ。"\"まで入れる。
    With Application.FileDialog(msoFileDialogFolderPicker)
        .InitialFileName = DefaultPath      'デフォルトフォルダをデスクトップにする
        If .Show = True Then
            strFolderPath = .SelectedItems(1)
        End If
    End With
    'フォルダダイアログで「キャンセル」したので終了
    If strFolderPath = "" Then Exit Sub
    'フォルダ取得
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set objFolder = FSO.GetFolder(strFolderPath)
    
    '--------------------------------------
    '階層数の指定
    '--------------------------------------
    Do
        MsgRtn = InputBox("階層数を指定してください。" & vbCrLf & vbCrLf & _
                    "※指定したフォルダの階層を1として、何階層下まで取得するか指定します。デフォルトは1です。", _
                     "階層数の指定", 1)
        'キャンセル
        If MsgRtn = "" Then
            Exit Sub
        End If
        '数字
        If IsNumeric(MsgRtn) = True Then
            '0以下
            If MsgRtn <= 0 Then
                'もう1度入力
                MsgBox "1以上の数値を入力してください。", _
                    vbOKOnly + vbExclamation, Title:="エラー"
            '5以上
            ElseIf MsgRtn >= 5 Then
                intDepth = CInt(MsgRtn)
                MsgRtn = MsgBox(MsgRtn & " 階層が指定されました。ファイルが多い場合には時間がかかりますが、続行しますか?", _
                    vbOKCancel + vbInformation, Title:="5階層以上指定")
                If MsgRtn = vbOK Then
                    Exit Do
                End If
            'それ以外
            Else
                intDepth = CInt(MsgRtn)
                Exit Do
            End If
        '数字以外
        Else
            MsgBox "1以上の数値を入力してください。", _
                vbOKOnly + vbExclamation, Title:="エラー"
        End If
    Loop
    
    '--------------------------------------
    'ファイルリスト取得
    '--------------------------------------
    Erase FilePaths                     'ファイルリスト用変数を初期化
    'ファイルリスト取得を呼び出す
    GetFileList objFolder, intDepth, 0
    On Error Resume Next
    lngFileCount = UBound(FilePaths)    'ファイルが1つもない場合UBoundがエラーになる
    If Err.Number <> 0 Then
        '終了メッセージ
        MsgBox "指定されたフォルダにはファイルが1つもないので、終了します。", _
            vbOKOnly + vbExclamation, Title:="エラー"
        Exit Sub
    End If
    On Error GoTo 0

    '--------------------------------------
    '出力ファイル作成
    '--------------------------------------
    'カーソル砂時計表示
    Application.Cursor = xlWait
    '新規ブック作成
    temp = Application.SheetsInNewWorkbook
    Application.SheetsInNewWorkbook = 1
    Set xlsWorkbookOutput = Workbooks.Add
    Application.SheetsInNewWorkbook = temp
    'シート名
    xlsWorkbookOutput.ActiveSheet.Name = "ファイルリスト"
    'フォント
    xlsWorkbookOutput.Styles("Normal").Font.Name = "MS ゴシック"
    'ルートフォルダ名をA1に出力
    With xlsWorkbookOutput.ActiveSheet.Cells(1, 1)
        .NumberFormatLocal = "@"
        .Value = strFolderPath
    End With
    '列の幅・見出し設定
    x = 3
    y = 1
    xlsWorkbookOutput.ActiveSheet.Columns(1).ColumnWidth = 5
    xlsWorkbookOutput.ActiveSheet.Columns(2).ColumnWidth = 5
    xlsWorkbookOutput.ActiveSheet.Columns(3).ColumnWidth = 30
    xlsWorkbookOutput.ActiveSheet.Columns(4).ColumnWidth = 80
    xlsWorkbookOutput.ActiveSheet.Columns(5).ColumnWidth = 10
    xlsWorkbookOutput.ActiveSheet.Columns(6).ColumnWidth = 40
    xlsWorkbookOutput.ActiveSheet.Columns(7).ColumnWidth = 10
    xlsWorkbookOutput.ActiveSheet.Columns(8).ColumnWidth = 10
    xlsWorkbookOutput.ActiveSheet.Cells(x, 1) = "No"
    xlsWorkbookOutput.ActiveSheet.Cells(x, 2) = "階層"
    xlsWorkbookOutput.ActiveSheet.Cells(x, 3) = "サブフォルダ"
    xlsWorkbookOutput.ActiveSheet.Cells(x, 4) = "ファイル名"
    xlsWorkbookOutput.ActiveSheet.Cells(x, 5) = "ページ数"
    With xlsWorkbookOutput.ActiveSheet.Cells(x, 6)
        .Value = "構成情報"
        .AddComment
        .Comment.Visible = False
        .Comment.Text Text:="見出し等構成を知る補助情報。" & vbLf & _
                            "Excel:シート名,ページ数" & vbLf & "Word:リスト見出し" & vbLf & "PowerPoint:スライド番号,スライドタイトル" & vbLf & _
                            "Excelのシート名に[非表示]がついてるものは非表示シート"
        .Comment.Shape.ScaleWidth 2.5, msoFalse, msoScaleFromTopLeft
        .Comment.Shape.ScaleHeight 1.5, msoFalse, msoScaleFromTopLeft
    End With
    xlsWorkbookOutput.ActiveSheet.Cells(x, 7) = "サイズ(MB)"
    'サイズ(MB)の書式
    xlsWorkbookOutput.ActiveSheet.Columns("G:G").NumberFormatLocal = "0.00_ "
    '表見出しの背景色
    xlsWorkbookOutput.ActiveSheet.Range(Cells(x, 1), Cells(x, 7)).Interior.Color = intColHeadColer
    'ウィンドウ枠の固定
    xlsWorkbookOutput.ActiveSheet.Cells(x + 1, 1).Select
    ActiveWindow.FreezePanes = True
    '印刷設定
    Application.PrintCommunication = False
    With xlsWorkbookOutput.ActiveSheet.PageSetup
        .PrintTitleRows = "$1:$3"
        .CenterFooter = "&P"
        .Orientation = xlLandscape
        .Zoom = False
        .FitToPagesWide = 1
        .FitToPagesTall = False
    End With
    Application.PrintCommunication = True
    
    '--------------------------------------
    '出力ファイル保存
    '--------------------------------------
    strDate = Format(Now(), "_yymmdd-hhmm")
    strOutputFileName = strBaseName & strDate
    i = 0
    Do
        If FSO.FileExists(DefaultPath & "\" & strOutputFileName & "." & strExtName) = False Then
            Exit Do
        Else
            'ファイル名
            i = i + 1
            strOutputFileName = strBaseName & strDate & "_" & i
        End If
    Loop
    'ファイルを保存
    xlsWorkbookOutput.SaveAs Filename:=DefaultPath & strOutputFileName & "." & strExtName
    
    '--------------------------------------
    'ファイル拡張子ごとにページ数取得して出力
    '--------------------------------------
    For i = 1 To lngFileCount
        
        'ファイルを保存(入力20ファイルごとに出力ファイルを保存)
        If i Mod 20 = 0 Then
            xlsWorkbookOutput.Save
        End If
        
        'ステータスバー表示
        Application.StatusBar = Left(Format(i / lngFileCount, "0.0%") & " (" & i & "/" & lngFileCount & ") " & FilePaths(i), 125)
        DoEvents
        
        '初期化
        lngPageCount = 0
        strShPageDetail = ""
        strWdListString = ""
        
        '--------------------------------------
        '拡張子により場合分け
        '--------------------------------------
        Select Case LCase(FSO.GetExtensionName(FilePaths(i)))
        
        'Excelファイル
        Case "xls", "xlsx", "xlsm", "xlsb"
            On Error Resume Next    'ファイルが壊れていて開けないときetc
            'ファイルを開く(読み取り専用)
            Application.EnableEvents = False
            Application.Calculation = xlCalculationManual
            Set xlsworkbook = Workbooks.Open(FilePaths(i), UpdateLinks:=0, ReadOnly:=True)
            If Err.Number <> 0 Then
                On Error GoTo 0
                Err.Clear
            Else
                On Error GoTo 0
                For Each sh In xlsworkbook.Sheets
                    'ワークシートとグラフシートのページカウントに対応
                    If TypeName(sh) = "Worksheet" Or TypeName(sh) = "Chart" Then
                        '非表示シートの場合表示
                        shVisible = ""
                        strHiddenSheet = ""
                        ErrShVisible = False
                        If sh.Visible <> xlSheetVisible Then
                            shVisible = sh.Visible      '現在の表示状態
                            On Error Resume Next        '保護かかっているブック等でシート表示できないことがあるため回避
                            sh.Visible = xlSheetVisible '非表示シートを表示
                            If Err.Number <> 0 Then
                                ErrShVisible = True
                            End If
                            On Error GoTo 0
                            strHiddenSheet = "[非表示]"
                        End If
                        '表示できなかったシートの場合は0ページ
                        If ErrShVisible = True Then
                            lngShPageCount = 0
                        Else
                            lngShPageCount = sh.PageSetup.Pages.Count
                        End If
                        'シート数分のページを加算
                        lngPageCount = lngPageCount + lngShPageCount
                        'シート名とページ数
                        If strShPageDetail = "" Then
                           strShPageDetail = sh.Name & strHiddenSheet & "," & lngShPageCount
                        Else
                           strShPageDetail = strShPageDetail & vbLf & sh.Name & strHiddenSheet & "," & lngShPageCount
                        End If
                        If shVisible <> "" And ErrShVisible = False Then
                            sh.Visible = shVisible  '表示状態をもとに戻す
                        End If
                    End If
                Next sh
                'ファイルを閉じる
                Application.DisplayAlerts = False
                'シートの多いファイルで xlsWorkbook.Close がスルーされてファイルが閉じられないことがあっため
                '回避できた Workbooks のファイル名指定でのクローズに修正
                Workbooks(FSO.GetFilename(FilePaths(i))).Saved = True
                Workbooks(FSO.GetFilename(FilePaths(i))).Close SaveChanges:=xlDoNotSaveChanges
                Application.DisplayAlerts = True
                Application.Calculation = xlCalculationAutomatic
                Application.EnableEvents = True
            End If
            
        'Wordファイル
        Case "doc", "docx", "docm"
            Set wordApp = CreateObject("Word.Application")
            wordApp.Visible = True
            On Error Resume Next    'ファイルが壊れていて開けないときetc
            'ファイルを開いてページ数取得
            Set wordDoc = wordApp.Documents.Open(FilePaths(i), ReadOnly:=True)
            If Err.Number <> 0 Then
                On Error GoTo 0
                Err.Clear
                lngPageCount = 0
            Else
                On Error GoTo 0
                'ページ数
                lngPageCount = wordDoc.Content.Information(wdNumberOfPagesInDocument)
                '見出しを取得(保護されてない文書のみ)
                If wordDoc.ProtectionType = wdNoProtection Then
                    wordDoc.Activate
                    wordDoc.SelectAllEditableRanges
                    wordApp.ActiveWindow.Selection.Goto wdGoToHeading, wdGoToFirst          '最初の見出し
                    If wordDoc.Paragraphs.OutlineLevel = wdOutlineLevelBodyText Then    '1つも見出しがない
                    Else
                        Do
                            With wordApp.ActiveWindow.Selection
                                If .Range.ListFormat.ListString <> "" Then
                                    'リスト番号と見出し両方。区切り文字空白。末尾の改行をなしに置換
                                    If strWdListString = "" Then
                                        strWdListString = .Range.ListFormat.ListString & " " & Replace(.Paragraphs(1).Range.Text, vbCr, "")
                                    Else
                                        strWdListString = strWdListString & vbLf & .Range.ListFormat.ListString & " " & Replace(.Paragraphs(1).Range.Text, vbCr, "")
                                    End If
                                Else
                                    'リスト番号でない場合は出力しない
                                End If
                                Set rngList = .Range
                                Set rngListNext = .GoToNext(wdGoToHeading)
                                If rngListNext.End = rngList.End Then
                                    Exit Do
                                End If
                            End With
                        Loop
                    End If
                Else
                    strWdListString = ""   '保護文書は見出し空白
                End If
                'ファイルを閉じる
                wordDoc.Close SaveChanges:=False
            End If
            wordApp.Visible = False
            wordApp.Quit
            Set wordDoc = Nothing
            Set wordApp = Nothing
            Set rngList = Nothing
            Set rngListNext = Nothing
            
        'Power Pointファイル
        Case "ppt", "pptx", "pptm"
            Set pptApp = CreateObject("PowerPoint.Application")
            pptApp.Visible = True
            On Error Resume Next    'ファイルが壊れていて開けないときetc
            'ファイルを開いてページ数取得
            Set pptPrs = pptApp.Presentations.Open(FilePaths(i), ReadOnly:=True)
            If Err.Number <> 0 Then
                On Error GoTo 0
                Err.Clear
                lngPageCount = 0
            Else
                On Error GoTo 0
                lngPageCount = pptPrs.Slides.Count
                'スライドタイトル取得
                If pptPrs.PageSetup.FirstSlideNumber = 0 Then   '開始がスライド0のとき
                    lngFirstSlideNo = 1
                Else
                    lngFirstSlideNo = pptPrs.PageSetup.FirstSlideNumber
                End If
                For p = lngFirstSlideNo To pptPrs.Slides.Count
                    If pptPrs.Slides(p).Shapes.HasTitle Then    'スライドタイトルがあるか
                        If strWdListString <> "" Then
                            strWdListString = strWdListString & vbLf & pptPrs.Slides(p).SlideNumber & "," _
                                                & pptPrs.Slides(p).Shapes.Title.TextFrame.TextRange.Text
                        Else
                            strWdListString = pptPrs.Slides(p).SlideNumber & "," _
                                                & pptPrs.Slides(p).Shapes.Title.TextFrame.TextRange.Text
                        End If
                    End If
                Next p
                'ファイルを閉じる
                With pptPrs
                    .Saved = True
                    .Close
                End With
                Set pptPrs = Nothing
            End If
            pptApp.Quit
            Set pptApp = Nothing
        End Select
        
        '--------------------------------------
        '結果をExcelに出力
        '--------------------------------------
        '出力行
        x = x + 1
        If x Mod 10 = 0 Then
            xlsWorkbookOutput.Activate
            ActiveWindow.ScrollRow = x  '10行に1回スクロール(構成情報が多いと列が高くなる)
        End If
        
        'No
        xlsWorkbookOutput.ActiveSheet.Cells(x, y).Formula = "=ROW()-3"
        'フォルダ名(ルートフォルダは出力しない)
        xlsWorkbookOutput.ActiveSheet.Cells(x, y + 2).NumberFormatLocal = "@"
        If LCase(FSO.GetParentFolderName(FilePaths(i))) = LCase(strFolderPath) Then
            'xlsWorkbookOutput.ActiveSheet.Cells(x, y + 2) = ""
        Else
            xlsWorkbookOutput.ActiveSheet.Cells(x, y + 2) = Mid(FSO.GetParentFolderName(FilePaths(i)), Len(strFolderPath) + 2, Len(FSO.GetParentFolderName(FilePaths(i))) - Len(strFolderPath))
        End If
        'サブフォルダ名を元に階層(サブフォルダ名が正確に取得できないと階層数がおかしくなる)
        If xlsWorkbookOutput.ActiveSheet.Cells(x, y + 2) = "" Then
            'ルートフォルダは0
            xlsWorkbookOutput.ActiveSheet.Cells(x, y + 1) = 0
        Else
            'ルートフォルダ以外は「"\"の数+1」
            xlsWorkbookOutput.ActiveSheet.Cells(x, y + 1) = Len(xlsWorkbookOutput.ActiveSheet.Cells(x, y + 2)) - Len(Replace(xlsWorkbookOutput.ActiveSheet.Cells(x, y + 2), "\", "")) + 1
        End If
        'ファイル名
        xlsWorkbookOutput.ActiveSheet.Cells(x, y + 3).NumberFormatLocal = "@"
        xlsWorkbookOutput.ActiveSheet.Cells(x, y + 3) = FSO.GetFilename(FilePaths(i))
        'ページ数
        If lngPageCount = 0 Then
            xlsWorkbookOutput.ActiveSheet.Cells(x, y + 4) = ""
        Else
            xlsWorkbookOutput.ActiveSheet.Cells(x, y + 4) = lngPageCount
        End If
        '構成情報
        If strShPageDetail <> "" Then
            'Excelの場合のシート名とシートページ数
            xlsWorkbookOutput.ActiveSheet.Cells(x, y + 5) = strShPageDetail
        ElseIf strWdListString <> "" Then
            'Wordの場合リスト見出し/PowerPointの場合各スライドのタイトル
            xlsWorkbookOutput.ActiveSheet.Cells(x, y + 5) = strWdListString
        End If
        'サイズ(MB)
        xlsWorkbookOutput.ActiveSheet.Cells(x, y + 6).Formula = "=" & FSO.GetFile(FilePaths(i)).Size & "/1024/1024"
        
    Next i
    
    '並び替え(サブフォルダ、ファイル名で並び替え)
    xlsWorkbookOutput.ActiveSheet.Cells(3, 1).CurrentRegion.Sort key1:=Range("C4"), Order1:=xlAscending, key2:=Range("D4"), Order1:=xlAscending, Header:=xlYes
    xlsWorkbookOutput.Activate
    ActiveWindow.ScrollRow = 1
    'オートフィルタ
    On Error Resume Next
    xlsWorkbookOutput.ActiveSheet.Rows("3:3").AutoFilter
    On Error GoTo 0
    
    '--------------------------------------
    '終了
    '--------------------------------------
    'ステータスバー表示デフォルト
    Application.StatusBar = False
    'カーソル砂時計表示解除
    Application.Cursor = xlDefault
    
    'ファイルを保存
    xlsWorkbookOutput.Save
    
    'ウィンドウアクティブ
    AppActivate Application.Caption
               
    '終了メッセージ
    EndTime = Now()     '終了時刻
    MsgBox "終了しました。" & vbLf & vbLf & _
            "処理時間:" & Format(EndTime - StartTime, "hh:mm:ss") & vbLf & _
            "出力ファイル:" & DefaultPath & xlsWorkbookOutput.Name & vbCrLf & vbCrLf, _
            vbOKOnly + vbInformation, Title:="終了"
    
    'オブジェクトクリア
    Set WSH = Nothing
    Set FSO = Nothing
    Set objFolder = Nothing
    Set xlsworkbook = Nothing
    Set sh = Nothing
    Set xlsWorkbookOutput = Nothing
        
End Sub


Sub GetFileList(objFolder As Object, intDepth As Integer, lngFileCount As Long)

    '--------------------------------------
    'ファイルリスト取得(再帰呼び出し)
    ' 結果はモジュールレベル変数「FilePaths」に格納
    '--------------------------------------
    
    Dim objSubFolder As Object      'サブフォルダ
    Dim objFiles As Object          'ファイル
    Dim objF As Object              '変数
    Dim intNextDepth As Integer     '次の階層数
    Dim i As Long
    
    Dim FSO As Object               'ファイルシステムオブジェクト
    Set FSO = CreateObject("Scripting.FileSystemObject")
    
    Set objSubFolder = objFolder.subFolders
    Set objFiles = objFolder.Files
    intNextDepth = intDepth - 1

    'フォルダ配下
    'objSubFolder.Countがとれない特殊フォルダは配下ごと無視
    On Error Resume Next
    i = objSubFolder.Count
    If Err.Number = 0 Then
        If objSubFolder.Count > 0 Then
            For Each objF In objSubFolder
                If intNextDepth > 0 Then
                    '再帰呼び出し
                    GetFileList objF, intNextDepth, lngFileCount
                End If
            Next objF
        End If
    End If

    'ファイル
    If objFiles.Count > 0 Then
        For Each objF In objFiles
            If objF Is Nothing Then
                'システム系でNothingが返ってくることがあるので飛ばす
            ElseIf Left(objF.Name, 2) = "~$" Then
                '~$で始まる一時ファイルは後のページ数取得がエラーになるので飛ばす
            ElseIf Left(objF.Name, 1) = "$" Then
                '$で始まるファイルは後のページ数取得がエラーになるので飛ばす
            Else
                'ファイルカウント
                lngFileCount = lngFileCount + 1
                'ファイルパスを取得するための動的配列を定義
                If lngFileCount = 1 Then
                    ReDim FilePaths(lngFileCount)
                Else
                    ReDim Preserve FilePaths(lngFileCount)
                End If
                'ファイルパスを配列に格納
                FilePaths(lngFileCount) = objF
            End If
        Next objF
    End If

    Set objSubFolder = Nothing
    Set objFiles = Nothing
    Set objF = Nothing

End Sub

フォルダごとに集計する方法

簡単に書いておきます。Excel のピボットテーブルを使うとラクです。

  1. 「サブフォルダ」列を「¥」区切りで分割するため、「サブフォルダ」列の右に「サブフォルダ」階層分の空の列を追加しておく。
  2. 「サブフォルダ」列を[データ]-[区切り位置]区切り文字「¥」で分割する。
  3. 分割した列の見出しが空なので、見出しをつける「サブフォルダ2」、「サブフォルダ3」…等。(ピポットテーブルの仕様として列見出しが必要)
  4. 表範囲を [挿入]-[ピボットテーブル] に指定する。
  5. ピボットテーブルの「行」に「サブフォルダ」~「サブフォルダx」等を全て指定する。
  6. 「値」に「ページ数」を指定する。(自動的に「合計/ページ数」になると思いますが、合計になってなかったら▼で合計を選んでください)

上記は時間ができたらコードに含めようと思っています。

後記

自分が Office 使う範囲で困らない程度に作ってあります。
本当はPDFもページカウントに対応したかったのですが、コメントに書いてる通り厳しそうでした。インターネット上に、ファイルをバイナリで読み込んでページ数の位置を取得するコードがいくつかあったのですが、それだと正しいページがとれないことがありました(何の違いによるものなのか詳細未調査です。正しくとれる場合もありました)。最新PDFに対応したコードを公開してる人もいましたが、かなり長いソースで煩雑になりそうなため、入れるのを諦めました。

変更履歴
1.1 2021/07/22 バグ修正及び一部仕様変更しました。
1.2 2021/08/03 バグ修正及び一部仕様変更しました。
1.3 2021/08/05 バグ修正しました。
1.4 2021/10/09 バグ修正しました。

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