1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Excel VBA 長すぎて扱えないファイルパスをショートパスに変換する

1
Last updated at Posted at 2024-10-31

はじめに

Windowsでは、ファイルパスが長すぎると(260文字以上?)、ファイル操作ができなくなる。
VBAでも同様で、ファイルパスが長すぎると、ファイル操作ができない。
そのため、ファイルパスをショートパスに変更し、扱えるようにしたい。

マクロ作成の経緯

File System Objectを使い、サブフォルダを含むフォルダ内のファイルを一括取得していた。
すると、フォルダ階層が深く、ファイルパスが長くなり、取得できないファイルがあった。
この長すぎるファイルパスにも対応する方法を模索した。

作成したマクロの概要

文字制限にひっかからないフォルダをショートパスに変換する方法を参考に作成した。
存在するフォルダまでフォルダ階層をさかのぼり、そのパスをショートパスに変換する。
変換したショートパスとその後ろ側のパスを繋げることで、扱えるパスに変換する。
これらの動作を実行する、Functionプロシージャを作成した。
渡したパスが存在しない場合、Functionプロシージャは空欄「””」を返す仕様とした。

動作手順

  1. 存在するフォルダになるまで、パスの最終要素を順番に切り取る
  2. 切り取ったパスの最終要素は後ろ側のパスとして、繋げて記録しておく
  3. 存在するフォルダを見つけたら、そのフォルダをショートパスに変換する
    (存在するフォルダを見つけられなかった場合、そのパスは存在しない)
  4. 変換したフォルダのショートパスと、記録しておいた後ろ側のパスを繋げる
    (後ろ側のパスが間違っている可能性があるので、完成したパスが存在するか確認する)

完成したマクロ

ショートパスに変換するFunctionプロシージャ

ChangeShortPath
'存在しないパスを渡した場合、空欄""を返す
Public Function ChangeShortPath(FullPath As String) As String

Dim Fso As Object
Dim TargetPath As String
Dim LastPath As String

   Set Fso = CreateObject("Scripting.FileSystemObject")
        
    TargetPath = FullPath
    
    '存在するフォルダまで遡って、存在するフォルダをショートパスに変換する
    Do Until Fso.FolderExists(TargetPath)
    
        'GetFileNameは、ファイルに限らず、最終要素を取り出す
        LastPath = "\" & Fso.GetFileName(TargetPath) & LastPath
        
        'GetParentFolderNameは最終要素のひとつ前の要素を取り出す
        TargetPath = Fso.GetParentFolderName(TargetPath)
        
        'TargetPathが空欄 = フォルダを最初まで遡っても存在しなかった ⇒ 存在しないパスであるため、終了
        If TargetPath = "" Then Exit Do
        
    Loop
    
    TargetPath = Fso.GetFolder(TargetPath).ShortPath & LastPath
    
    If Fso.FileExists(TargetPath) = False _
        And Fso.FolderExists(TargetPath) = False Then TargetPath = ""
    
    ChangeShortPath = TargetPath
    
    Set Fso = Nothing
    
End Function

File System Objectの各メソッドの注釈

  • File System Objectの「FolderExists」は、長すぎて扱えないパスの場合、Falseを返す
    また、ファイルパスの場合、フォルダではないので、Falseを返す
  • File System Objectの「GetFileName」は、ファイル名に限らず、最終要素を取り出す
    (ファイルパスではファイル名を、フォルダパスでは最終要素のフォルダを返す)
  • File System Objectの「GetParentFolderName」は最終要素のひとつ前の要素を取り出す
    (フォルダパスでは親フォルダを、ファイルパスではファイルのあるフォルダを返す)
  • 上記の特徴を活かし、ファイルパス・フォルダパスの両方に対応したマクロとなっている
     

使用例

使用例として、サブフォルダを含むフォルダ内のファイル一覧を作成するマクロを記載。

出力シートイメージ

スクリーンショット 2024-10-31 115557.jpg

作成コード

使用例
Public Sub SearchSubFolders_File()

Dim Fso As Object
Dim FolderPath As String
Dim ChangePath As String
Dim StartRow As Long
Dim FolderStartColumn As Long
Dim TargetSheet As Worksheet

    Set Fso = CreateObject("Scripting.FileSystemObject") 
    Set TargetSheet = ActiveSheet

    With TargetSheet
        .Range("A1").CurrentRegion.Offset(2).ClearContents
        FolderPath = .Range("B1").Value
        StartRow = .Range("A3").Row
        FolderStartColumn = .Range("C3").Column
    End With
    
    ChangePath = ChangeShortPath(FolderPath)
    
    If ChangePath <> "" Then
        Call FileSearch(TargetSheet, FolderPath, ChangePath, StartRow, FolderStartColumn, FolderStartColumn, Fso)
    Else
        MsgBox FolderPath & "は存在しません。"  
    End If

    Set Fso = Nothing
    
End Sub

Sub FileSearch(TargetSheet As Worksheet, FolderPath As String, ChangePath As String, outRow As Long, outColumn As Long, baseColumn As Long, Fso As Object)

Dim i As Long
Dim TargetFolder As Object
Dim TargetSubfolder As Object
Dim TargetFile As Object
Dim CurrentFolderPath As String

    Set TargetFolder = Fso.GetFolder(ChangePath)
    
    For Each TargetSubfolder In TargetFolder.SubFolders
        'フォルダを基準となる列から横にずらして出力することで、サブフォルダの階層を表現
        Call FileSearch(TargetSheet, FolderPath & "\" & TargetSubfolder.Name, ChangePath & "\" & TargetSubfolder.Name, outRow, outColumn + 1, baseColumn, Fso)  '再帰呼出
    Next TargetSubfolder
    
    With TargetSheet
        For Each TargetFile In TargetFolder.Files
            CurrentFolderPath = FolderPath
            '一番下の階層のフォルダから出力して、サブフォルダの階層を表現
            For i = outColumn To baseColumn Step -1
                .Cells(outRow, i).Value = Fso.GetBaseName(CurrentFolderPath)
                CurrentFolderPath = Fso.GetParentFolderName(CurrentFolderPath)   
            Next i 
            .Cells(outRow, 1) = FolderPath & "\" & TargetFile.Name
            .Cells(outRow, 2) = TargetFile.Name  
            outRow = outRow + 1 
    End With
    
    Set TargetFile = Nothing
    Set TargetSubfolder = Nothing
    Set TargetFolder = Nothing

End Sub

サンプルファイル保存先:

参考

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?