wrote :: 2005.01.18

トップページ > Excel > VBA > FileSystemObject > サンプルコード


サンプルコード

FileSystemObjectオブジェクトを使ったサンプルをご紹介します。
標準モジュールにコードをコピーすれば実行できるように書きますが、中には特定のファイルやフォルダが存在しないとエラーになるコードもありますので注意してください。
動作確認はExcel 2002/2003+Windows XP Homeで行っています。

01.指定したドライブの空き容量を表示する
02.使用可能な全ドライブの種類をワークシートに書き込む
03.連続番号の複数フォルダを作成する
04.次の連続番号フォルダを作成する
05.テンポラリフォルダに作業用ブックを保存する
06.マクロの挙動をログファイルに記録する
07.フォルダ内に存在する全「.xls」ファイルのベース名を取得する
08.サブフォルダの全ファイルサイズをグラフ化する
09.テキストファイルの行数を調べる
10.保存先のフォルダがなかったら作る



01.指定したドライブの空き容量を表示する


Sub Sample01()
    Dim FSO, DrvLetter As String, msg As String
    Set FSO = CreateObject("Scripting.FileSystemObject")
    DrvLetter = InputBox("容量を調べるドライブは?")
    If DrvLetter = "" Then
        Set FSO = Nothing
        Exit Sub
    End If
    If FSO.DriveExists(DrvLetter) Then
        With FSO.GetDrive(DrvLetter)
            msg = Format(.AvailableSpace / 1024, "#,##") & " KB"
        End With
    MsgBox DrvLetter & "ドライブの空き容量は、" & msg & "です。", vbInformation
    Else
        MsgBox DrvLetter & "ドライブは存在しません", vbExclamation
    End If
    Set FSO = Nothing
End Sub
※指定されたドライブが存在するかどうかを、FileSystemObjectオブジェクトのDriveExistsプロパティで判定しています。
UserFormのリストボックスなどでドライブを選択させてもいいですね。ここでは容量の単位をKBとしましたが、MBやGBにしたいときは、さらに1024で割ってください。
(ページの先頭へ戻る)


02.使用可能な全ドライブの種類をワークシートに書き込む


Sub Sample02()
    Dim FSO, Drv, cnt As Long, DrvType As String
    Set FSO = CreateObject("Scripting.FileSystemObject")
    ''全てのドライブを調べます
    For Each Drv In FSO.Drives
        cnt = cnt + 1
        Select Case Drv.DriveType
            Case 0:  DrvType = " 不明"
            Case 1:  DrvType = " リムーバブルディスク"
            Case 2:  DrvType = " ハードディスク"
            Case 3:  DrvType = " ネットワークドライブ"
            Case 4:  DrvType = " CD-ROM"
            Case 5:  DrvType = " RAMディスク"
        End Select
        ''シートに書き込みます
        ActiveSheet.Cells(cnt, 1) = Drv.DriveLetter
        ActiveSheet.Cells(cnt, 2) = DrvType
    Next Drv
    Set FSO = Nothing
End Sub

※アクティブシートのA列に「C」などのドライブ名、B列にドライブの種類を書き込みます。
(ページの先頭へ戻る)


03.連続番号の複数フォルダを作成する


Sub Sample03()
    Dim FSO, StartNum As Long, EndNum As Long, i As Long
    Set FSO = CreateObject("Scripting.FileSystemObject")
    ''C:\Workフォルダの存在を調べます
    If FSO.FolderExists("C:\Work\") = False Then
        MsgBox "C:\Workフォルダを作ってから実行してください", vbExclamation
        Set FSO = Nothing
        Exit Sub
    End If
    ''開始数字と終了数字をユーザーから受け取ります
    StartNum = Val(InputBox("連続番号フォルダの開始番号は?"))
    EndNum = Val(InputBox("連続番号フォルダの終了番号は?"))
    If StartNum = 0 Or EndNum = 0 Then Exit Sub
    ''連続番号フォルダを作成します
    ''同名フォルダが存在する場合のエラーを無視します
    On Error Resume Next
    For i = StartNum To EndNum
        FSO.CreateFolder "C:\Work\" & Format(i, "000")
    Next i
    MsgBox Format(StartNum, "000") & "から" & _
           Format(EndNum, "000") & _
           "のフォルダを作成しました", vbInformation
    Set FSO = Nothing
End Sub


※「001」「002」という連続番号のサブフォルダを、指定した数だけ作成します。作成する親フォルダはC:\Workです。存在しないときはメッセージを表示して処理を中止します。開始番号と終了番号のいずれかで[キャンセル]ボタンがクリックされると処理を中止します。すでに同名のフォルダがある場合はCreateFolderメソッドがエラーになりますが、無視して処理を続けています。
(ページの先頭へ戻る)


04.次の連続番号フォルダを作成する


Sub Sample04()
    Dim FSO, LargeNum As Long, Fil
    Set FSO = CreateObject("Scripting.FileSystemObject")
    ''C:\Workフォルダの存在を調べます
    If FSO.FolderExists("C:\Work\") = False Then
        MsgBox "C:\Workフォルダを作ってから実行してください", vbExclamation
        Set FSO = Nothing
        Exit Sub
    End If
    ''C:\Work内の全てのサブフォルダから最大番号を調べます
    For Each Fil In FSO.GetFolder("C:\Work\").SubFolders
        If LargeNum < Val(Fil.Name) Then LargeNum = Val(Fil.Name)
    Next Fil
    FSO.Createfolder "C:\Work\" & Format(LargeNum + 1, "000")
    MsgBox Format(LargeNum + 1, "000") & "フォルダを作成しました", vbInformation
    Set FSO = Nothing
End Sub
※上の続きみたいなもんです。「001」「002」という連続番号のサブフォルダが存在するとき、次の番号のサブフォルダを1つ作成します。
(ページの先頭へ戻る)


05.テンポラリフォルダに作業用ブックを保存する


Sub Sample05()
    Dim FSO, TempFolder As String, TempName As String
    Set FSO = CreateObject("Scripting.FileSystemObject")
    ''新しいブックを挿入します
    With Workbooks.Add
        ''作業用ブック名を生成します
        With FSO
            TempName = .GetSpecialFolder(2) & "\" & .GetBaseName(.GetTempName) & ".xls"
        End With
        ''挿入したブックに名前を付けて保存します
        .SaveAs TempName
        MsgBox .FullName & vbCrLf & "という名前で保存しました", vbInformation
    End With
    Set FSO = Nothing
End Sub
※新しいブックを開き、テンポラリフォルダにランダムな名前で保存します。
(ページの先頭へ戻る)


06.マクロの挙動をログファイルに記録する


Sub Sample06()
    Workbooks.Add
    Call WriteLog("新しいブックを開きました")
    Range("A1") = 123
    Call WriteLog("セルにデータを書き込みました")
    ActiveWorkbook.SaveAs "C:\Work\Report.xls"
    Call WriteLog("ブックを保存しました")
End Sub

Sub WriteLog(msg As String) Dim FSO, LOG Set FSO = CreateObject("Scripting.FileSystemObject") ''ログファイルがなければ作ります If FSO.FileExists("C:\Work\Report.log") = False Then FSO.CreateTextFile "C:\Work\Report.log" End If ''追記で開きます Set LOG = FSO.OpenTextFile("C:\Work\Report.log", 8) ''日時+タブ+メッセージを書き込みます LOG.WriteLine Now & Chr(9) & msg Set FSO = Nothing End Sub
※マクロ内の動作をログファイルに記録します。ログファイルはC:\Work\Report.logとし、存在しない場合は作成します。ログには日時と任意の文字列を書き込みます。日時と文字列の間はタブを挿入します。ログの書き込みは複数の箇所で行われるので、外部プロシージャとしました。
(ページの先頭へ戻る)


07.フォルダ内に存在する全「.xls」ファイルのベース名を取得する


Sub Sample07()
    Dim FSO, f, BaseNames() As String, cnt As Long, i As Long
    Set FSO = CreateObject("Scripting.FileSystemObject")
    For Each f In FSO.GetFolder("C:\Work\").Files
        If LCase(FSO.GetExtensionName(f.Name)) = "xls" Then
            cnt = cnt + 1
            ReDim Preserve BaseNames(cnt)
            BaseNames(cnt) = FSO.GetBaseName(f.Name)
        End If
    Next f
    If cnt = 0 Then
        MsgBox "xlsファイルはありません", vbExclamation
        Set FSO = Nothing
        Exit Sub
    End If
    For i = 1 To cnt
        Cells(i, 1) = BaseNames(i)
    Next i
    Set FSO = Nothing
End Sub

※「C:\Work」フォルダ内に存在する全「.xls」ファイルのベース名をアクティブシートに出力します。汎用的にするため、一度配列に格納しています。万が一「Book1.XLS」のように拡張子が大文字のファイルが存在したときのために、全ファイルの拡張子をGetExtensionNameメソッドを使って「xls」かどうか判定するとき、LCase関数でファイル名を小文字に変換しています。
(ページの先頭へ戻る)


08.サブフォルダの全ファイルサイズをグラフ化する


Sub Sample08()
    Dim FSO, f, cnt As Long
    Set FSO = CreateObject("Scripting.FileSystemObject")
    For Each f In FSO.GetFolder("C:\Tmp\").SubFolders
        cnt = cnt + 1
        Cells(cnt, 1) = FSO.GetFolder(f).Name
        Cells(cnt, 2) = FSO.GetFolder(f).Size
    Next f
    ''グラフの作成
    ActiveSheet.ChartObjects.Add(Range("C1").Left, Range("C1").Top, _
                                 Range("C1:G16").Width, Range("C1:G16").Height).Select
    With ActiveChart
        .ChartType = xl3DBarClustered
        .HasLegend = False
        .SetSourceData Source:=ActiveSheet.Range("A1").CurrentRegion
        .Location Where:=xlLocationAsObject, Name:=ActiveSheet.Name
        .Axes(xlCategory).ReversePlotOrder = True
    End With
    Range("A1").Activate
    Set FSO = Nothing
End Sub

※任意のフォルダのサブフォルダに保存されている全ファイルのサイズを取得してグラフ化します。上記のサンプルでは「C:\Tmp」フォルダを調べています。「C:\Tmp」フォルダには「Sub」「Sub2」「Work」「Work2」という4つのサブフォルダを作成し、適当なファイルを保存しました。マクロの後半はグラフを作るコードです。グラフのオプションなどはご自由に設定してください。ちなみに、私の環境で実行した結果はこちらをご覧ください。
(ページの先頭へ戻る)


09.テキストファイルの行数を調べる


Sub Sample09()
    Dim FSO, TargetFile As String
    TargetFile = Application.GetOpenFilename()
    If TargetFile = "False" Then
        Set FSO = Nothing
        Exit Sub
    End If
    Set FSO = CreateObject("Scripting.FileSystemObject")
    With FSO.OpenTextFile(TargetFile, 8)
        MsgBox Dir(TargetFile) & "は、" & .Line & "行あります。"
        .Close
    End With
    Set FSO = Nothing
End Sub

※TextStreamオブジェクトのLineプロパティは、ファイルに読み書きする行位置を返します。ファイルを追記モードで開くと書き込み位置が最終行に移動しますので、開いた直後のLineプロパティがファイルの行数になります。
(ページの先頭へ戻る)


10.保存先のフォルダがなかったら作る


Sub Sample10()
    Dim NewPath As String
    NewPath = InputBox("保存するフォルダのパスを入力してください" & vbCrLf & _
                       "例:C:\tmp\sub (必ずルートから)")
    ''[キャンセル]だったら終了
    If NewPath = "" Then Exit Sub
    ''親フォルダまでが存在するかチェックする
    Call CheckparentFolder(NewPath)
    ''サンプルのファイルを保存する
    If Right(NewPath, 1) <> "\" Then NewPath = NewPath & "\"
    Open NewPath & "Sample.txt" For Output As #1
        Print #1, Now()
    Close #1
End Sub

Sub CheckparentFolder(TargetFolder)
    Dim ParentFolder As String, FSO
    Set FSO = CreateObject("Scripting.FileSystemObject")
    ''調査対象フォルダの、親フォルダ名を取得する
    ParentFolder = FSO.GetParentFolderName(TargetFolder)
    If Not FSO.FolderExists(ParentFolder) Then
        ''親フォルダが存在しなかったら、
        ''親フォルダを新しい対象フォルダとして
        ''自分自身(Sub CheckparentFolder)を呼び出す
        Call CheckparentFolder(ParentFolder)
    End If
    ''新しいフォルダを作る
    FSO.CreateFolder TargetFolder
    Set FSO = Nothing
End Sub

※これは意外と奥が深い問題です。「C:\tmp\sub」というフォルダの存在を調べて、もし存在しなかったら作成したいわけですが「sub」ではなく「tmp」が存在しない可能性もあります。「C:\tmp」が存在しない場合は、FSO.CreateFolder "C:\tmp\sub" はエラーになります。そこで「対象フォルダの親フォルダが存在するかどうかを調べる」プロシージャを再帰的に呼び出して、存在するパスを見つけます。
なお、SHCreateDirectoryExというAPIを使うと、このように存在しない深いパスを一発で作成することができます。興味のある方はこちらをご覧ください。→「存在しないパスのフォルダを一発で作成する
(ページの先頭へ戻る)




[TextStreamオブジェクト]戻る← | →最初に戻る[はじめに]