【コピペで使える】VBAで指定したフォルダ内のファイル名を一覧で取得してシートに書き出す方法②

VBA

今回は、前回投稿した、サンプルコードの解説をしていきたいと思います。
まだ、投稿を見ていない方は下記のURLからご覧ください!

サンプルコード

Sub ListFilesWithDetails()
    Dim folderPath As String
    Dim ws As Worksheet
    Dim i As Long
    Dim sheetName As String
    Dim ans As VbMsgBoxResult
    
    ' フォルダ選択ダイアログ
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "フォルダを選択してください"
        If .Show <> -1 Then Exit Sub
        folderPath = .SelectedItems(1)
    End With
    
    ' シート名の入力
    sheetName = InputBox("出力先のシート名を入力してください", "シート名指定", "ファイル一覧")
    If sheetName = "" Then Exit Sub
    
    ' すでにシートが存在するか確認
    On Error Resume Next
    Set ws = Worksheets(sheetName)
    On Error GoTo 0
    
    If Not ws Is Nothing Then
        ans = MsgBox("シート「" & sheetName & "」はすでに存在します。上書きしますか?", vbYesNo + vbExclamation)
        If ans = vbNo Then Exit Sub
        Application.DisplayAlerts = False
        ws.Delete
        Application.DisplayAlerts = True
    End If
    
    ' 新しいシート作成
    Set ws = Worksheets.Add
    ws.Name = sheetName
    
    ' ヘッダー
    ws.Cells(1, 1).Value = "ファイル名"
    ws.Cells(1, 2).Value = "フルパス"
    ws.Cells(1, 3).Value = "更新日時"
    ws.Cells(1, 4).Value = "サイズ(KB)"
    i = 2

    ' ファイル一覧取得
    Call GetFilesRecursive(folderPath, ws, i)
    
    ' 表の整形
    ws.Columns("A:D").AutoFit
    MsgBox "完了しました!", vbInformation
End Sub

Sub GetFilesRecursive(ByVal folderPath As String, ByRef ws As Worksheet, ByRef rowIndex As Long)
    Dim fso As Object, folder As Object, file As Object, subFolders As Object, subF As Object
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set folder = fso.GetFolder(folderPath)
    
    ' ファイル一覧取得
    For Each file In folder.Files
        ws.Cells(rowIndex, 1).Value = file.Name
        ws.Cells(rowIndex, 2).Value = file.Path
        ws.Cells(rowIndex, 3).Value = file.DateLastModified
        ws.Cells(rowIndex, 4).Value = Round(file.Size / 1024, 1)
        rowIndex = rowIndex + 1
    Next
    
    ' サブフォルダも再帰的に処理
    Set subFolders = folder.SubFolders
    For Each subF In subFolders
        GetFilesRecursive subF.Path, ws, rowIndex
    Next
End Sub

解説

Dimとは

VBA(Visual Basic for Applications)における Dim は、「変数を宣言する」ためのキーワードです。
Dim「Dimension(ディメンション)」 の略で、もともとは配列の次元を宣言する意味合いがありましたが、現在では 変数を宣言する一般的な構文として使われています。

Dim 変数名 As データ型

→ 型が指定されていない場合、Variant型(すべての型を扱える型)として扱われます。

ただし、型を明示する方がエラーを防ぎやすく、処理も高速になるため、基本的には As 型 を付けることが推奨されます。

フォルダ選択のダイアログ

' フォルダ選択ダイアログ
With Application.FileDialog(msoFileDialogFolderPicker)
    .Title = "フォルダを選択してください"
    If .Show <> -1 Then Exit Sub
    folderPath = .SelectedItems(1)
End With

With Application.FileDialog(msoFileDialogFolderPicker)

  • Application.FileDialog(...)ファイルやフォルダの選択ダイアログを開く機能。
  • msoFileDialogFolderPicker はその中でも フォルダを選ぶ専用のダイアログ
  • With ... End With 構文は、同じオブジェクトに対して複数の操作をするのに使います。

.Title = "フォルダを選択してください"

  • ダイアログのタイトル(上部に表示される文字)を設定しています。

If .Show <> -1 Then Exit Sub

  • .Showダイアログを表示して、ユーザーが[OK]を押したかどうかを調べます。
  • -1 はユーザーが [OK] を押した ことを意味します。
  • <> -1 は「OKを押していない」= [キャンセル] を押したという意味。
  • その場合は Exit Sub によって 処理を中断して終了します。

folderPath = .SelectedItems(1)

  • ユーザーが選んだ フォルダのパスを取得しています。
  • .SelectedItems(1) は、ユーザーが選んだ最初のフォルダのパス
  • その結果を folderPath という変数に代入します
    (※この変数は事前に Dim folderPath As String と宣言されている必要があります)。

シート名の入力

' シート名の入力
sheetName = InputBox("出力先のシート名を入力してください", "シート名指定", "ファイル一覧")
If sheetName = "" Then Exit Sub

sheetName = InputBox(...)
これは、ユーザーに文字入力を求めるダイアログ(InputBox)を表示するコードです。

  • InputBox は、文字入力をユーザーから受け取るための標準関数。
  • ユーザーが入力した結果は sheetName という変数に代入されます。
    (※事前に Dim sheetName As String と宣言されていることが前提です)
  • 引数: InputBox(プロンプト, タイトル, デフォルト値)
引数説明
プロンプト入力ボックスのすぐ上に表示される説明テキスト
タイトル入力ボックスのウィンドウのタイトルバーに表示されるテキスト
デフォルト値入力欄にあらかじめ表示されている初期値(ユーザーが編集可能)

If sheetName = "" Then Exit Sub

  • 「ユーザーが何も入力せずにOKを押した」または「キャンセルを押した」場合を処理しています。
  • sheetName = "" なら、入力が空だったという意味。
  • その場合 Exit Sub によって、その後の処理を実行せずにマクロを終了させます。

シートの存在確認

' すでにシートが存在するか確認
On Error Resume Next
Set ws = Worksheets(sheetName)
On Error GoTo 0

On Error Resume Next

  • VBAでエラーが発生しても処理を止めずに次の行へ進むように設定する命令です。
  • たとえば存在しないシート名で Worksheets(sheetName) を参照すると、通常はエラーになってマクロが止まります。
  • それを防ぐために、この行で一時的にエラー無視モードにするわけです。

Set ws = Worksheets(sheetName)

  • Worksheets(sheetName) は、指定されたシート名に該当するワークシートを取得します。
  • Set ws = ... により、結果をオブジェクト変数 ws に代入します
    (※事前に Dim ws As Worksheet が必要)。
  • もしその名前のシートが存在しなければ、エラーが発生しますが、上の On Error Resume Next によってマクロは止まらず進みます。
  • 存在しなかった場合、ws には Nothing が入ります。

On Error GoTo 0

  • これは「エラー無視モードを解除して、通常のエラー処理に戻す」という命令です。
  • これ以降にエラーが起きたら、再びマクロは止まるようになります。

シートの上書き確認

If Not ws Is Nothing Then
    ans = MsgBox("シート「" & sheetName & "」はすでに存在します。上書きしますか?", vbYesNo + vbExclamation)
    If ans = vbNo Then Exit Sub
    Application.DisplayAlerts = False
    ws.Delete
    Application.DisplayAlerts = True
End If

If Not ws Is Nothing Then

  • ws(ワークシートオブジェクト)が何かしら存在している(Nothingではない)場合」、つまり 該当のシートがすでに存在する場合 に処理を行う条件文

ans = MsgBox("シート「" & sheetName & "」はすでに存在します。上書きしますか?", vbYesNo + vbExclamation)

  • MsgBox でユーザーに確認メッセージを表示
  • 表示内容は "シート「○○」はすでに存在します。上書きしますか?" という文章です。(sheetNameを埋め込み)。
  • vbYesNo + vbExclamation は、
    • 「はい」「いいえ」の選択肢があるボタン
    • 「注意」アイコンを表示
  • ユーザーの回答(「はい」または「いいえ」)は変数 ans に代入されます。

If ans = vbNo Then Exit Sub

  • ユーザーが「いいえ(No)」を選んだ場合は処理を中断(Exit Sub)します。
  • つまり、既存シートを上書きしたくない場合はそこで終了。

Application.DisplayAlerts = False

  • Excelの警告ダイアログを非表示にする設定です。
  • これをしないと、シート削除時に「本当に削除していいですか?」の確認メッセージが出て止まってしまいます。

ws.Delete

  • ws(存在しているシート)を削除します。
  • 警告メッセージを出さずに強制的に削除されます。

Application.DisplayAlerts = True

  • 警告ダイアログの表示設定を元に戻します。
  • 以降の処理では警告メッセージが通常通り表示されるようになります。

まとめ

今回は、各コードがどのような動きをしているのかを解説しました!
Excelを触れたことがある方は多くいると思うのですが、簡単な処理でも良いので、VBAで何かできるようにしておくと格段に作業効率も上がります。

全ての書き方を覚える必要はなく、○○を実現したいから、こういうコードを書くのだと理解していくことで自由にカスタマイズもできるようになると思います。

私自身もまだまだ調べながらサンプルを作成していますが、動くものが作れることが楽しい♪という気持ちを大事に勉強しています。
ぜひ皆さんも実際に書いたり、サンプルを動かしたりしてみてください!

別投稿で、CSVファイルの内容をExcelに転記する方法も紹介しています!

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