2025年11月9日日曜日

【VBA】フォルダー内のファイル一覧を読み込み、EXCELでファイル名を修正後に上書きするプログラム

  モーツアルトのリッピングデータを整理するために、フォルダー内のファイル名の一覧を取得するVBAプログラムを作成する事にしました。
 今回のファイル名には、英語、ドイツ語、イタリア語、ラテン語なんかが混在していて、そのままではどんな曲なのか判らないのです。
 結局、混在したファイル名を日本語に翻訳することにしたのです。
 これまでは、フォルダーのファイルを直接書き換えていたのですが、しばしばファイルシステムがエラーを起こして止まってしまいます。
 そこで、ファイル一覧をテキストで取得し、それを書き換えて、プログラムで直接書き換えようと思います。

 パソコンのOSが「MS-DOS」だった頃は、「リダイレクト機能(パイプ機能)」でフォルダーのファイル一覧を取得していたのです。
 「windows11」でも、「コマンドプロンプト」は使えるので、リダイレクトも使えそうですが、フォルダー階層が深くなると、コマンド入力が面倒に思えます。

 手元のパソコンにEXCELがインストールしてあるので、久しぶりにVBAでフォルダー内のファイル一覧の取得とファイル名の書き換えを自動で行うプログラムを作成してみることにしました。
   
     VBAってしばらく使ってなかったので(5~6年程前に退社した関係で)、中々にVBAに関する記憶が戻ってきません。
 比較的に簡単なコードのハズなのですが、結局5~6時間ほど費やしてしまいました。

 最終的に、コードはこうなりました。

**************************************************
  Option Explicit

Sub フォルダーを指定してファイル一覧を作成()            ' 指定フォルダのファイル一覧をシートに書き出す()

' ******************************フォルダーの指定
  MsgBox "ファイル一覧を取得するフォルダーを指定してください"
’*******************************
    Dim TgtfolderPath As Variant
        With Application.FileDialog(msoFileDialogFolderPicker)
        .Show
        TgtfolderPath = .SelectedItems(1)
        End With

' ********************************** シート名の作成
    Dim StrCnt As Integer
    Dim NewSheetName As String

       StrCnt = InStrRev(TgtfolderPath, "\", , vbTextCompare)      '¥の位置を探す        
        NewSheetName = Strings.Mid(TgtfolderPath, StrCnt)
            If Len(NewSheetName) > 21 Then
                NewSheetName = Left(NewSheetName, 21)
                Else
            End If        
        NewSheetName = GetTimeTxt(NewSheetName)
        NewSheetName = FileNameNGReplace(NewSheetName)
  
' ******************************* 出力するシートを2番目のシートとして作成
    Dim TopSheetName As String
        TopSheetName = Worksheets(1).Name

        Worksheets.Add After:=Worksheets(TopSheetName)
        ActiveSheet.Name = NewSheetName  

'*******************************全てのファイル名の取得  
    Dim FileName As String
    Dim R As Long
    
    FileName = Dir(TgtfolderPath & "\" & "*.*")   '*********全てのファイル名を取得
    R = 1
    Do While FileName <> ""
        ActiveSheet.Cells(R, 1) = FileName
        ActiveSheet.Cells(R, 2) = TgtfolderPath & "\" & FileName
        FileName = Dir()
        R = R + 1
    Loop    
   '*********************   
    MsgBox "終了しました"
    
End Sub

'時間をテキストで取得(フォルダー作成時に使う関数)

Public Function GetTimeTxt(ByVal Mytxt As String) As String
    Dim A As Variant
    A = CDate(Time)
    GetTimeTxt = Mytxt & CStr(A)       
End Function

'禁則文字列を削除(フォルダー作成時に使う関数)
Public Function FileNameNGReplace(sFileName As String) As String
    Dim TmpStr As String     
        TmpStr = sFileName
        TmpStr = Replace(TmpStr, "\", "")
        TmpStr = Replace(TmpStr, "/", "")
        TmpStr = Replace(TmpStr, ":", "")
        TmpStr = Replace(TmpStr, "*", "")
        TmpStr = Replace(TmpStr, "?", "")
        TmpStr = Replace(TmpStr, """", "")
        TmpStr = Replace(TmpStr, "<", "")
        TmpStr = Replace(TmpStr, ">", "")
        TmpStr = Replace(TmpStr, "|", "")
        TmpStr = Replace(TmpStr, "[", "")
        TmpStr = Replace(TmpStr, "]", "")
        FileNameNGReplace = TmpStr
    
End Function
’**************************************

 ファイル一覧の取得に対し、最初は「VBAのFileSystemObject」を使ったのですが、何故か画像ファイルが取得できませんでした。
 そう言えば、このプログラムを作成する前は、フォルダーのファイルを直接書き換えていたのですが、どんどんパソコンの調子が悪くなり、動作がおかしくなる事がありました。
 ファイル名の変更を付け付けなく成ったり、入力した文字列が消えてしまったり・・・。
 原因を色々と調べてみると、ファイル名の文字数が多いのが原因の様でした。
 今回のプログラムで、一部のファイルの名前が取得できなかった原因でもあるようです。
 VBAの問題なのか、或いは「ファイルアロケーションシステム」の所為の可能性もあります。
 

 たまには頭の体操と考えて、こんな遊びも良いですね。


 2025/11/10 追記
 次に、ファイル名を直接変更するプログラムを作成してみました。
 ファイル名が異常に長かったり、ファイルシステムが使えない文字があったりして、手こずりました。

 「EAC」でピッキング時に使ったデータベースから取得したファイル名に、見慣れない文字などが含まれていりして、ファイルを書き込む時にエラーが出ること判明しました。
 どうも、ラテン語?みたいな感じです。(よく知らないのでツッコミはなしです)

 まあそれでもファイル自体が消えてしまう事は無いので、エラーが出た場合だけ、直接ファイル名を修正してもう一度走らせれば良いので、このまま進めることにしました。 

******************************************
Option Explicit
Sub フォルダー内のファイル名をリストに従って書き換え()
 '************************** Sheetの指定 
 Dim TgtSheetName As String
 Dim MyAns As VbMsgBoxResult
 
    If Worksheets.Count = 1 Then
        MsgBox "一覧リストがありません"
        Exit Sub
    End If
 '************************* 
    TgtSheetName = Worksheets(2).Name    
' ************************* 確認用メッセージボックスを表示する
    MyAns = MsgBox(TgtSheetName & " に対して処理を実行しますか?", vbYesNo + vbQuestion, "確認")
    If MyAns = vbNo Then
        MsgBox "操作をキャンセルしました。", vbInformation, "情報"
        Exit Sub
    End If
'  ************************** アクティブシートの最終行を取得
  Worksheets(TgtSheetName).Activate   
    Dim xlLastRow As Long       'Excel自体の最終行
    Dim LastRow As Long         '最終行
    Dim MyRow As Long
'  **************************
    With ActiveSheet
        xlLastRow = Cells(Rows.Count, 1).Row  'Excelの最終行を取得
        LastRow = Cells(xlLastRow, 1).End(xlUp).Row   'D列の最終行を取得
    End With    
 ' ****************** ファイル名の文字数をチェック
    Dim WordCNT As Long    
        With ActiveSheet
            For MyRow = 1 To LastRow
                WordCNT = Len(Cells(MyRow, 2).Value)
                If WordCNT > 256 Then
                    MsgBox MyRow & "行の文字数が、256より多いので、処理できません" & "値= " &                     WordCNT
                Exit Sub
            End If
        Next
    End With  
' ************************** 最終行まで処理を繰り返す 
  Dim FullOldName As String
  Dim FullPath As String
  Dim NewName As String
  Dim FullNewName As String
  Dim MyCnt As Integer  
        With ActiveSheet  
        For MyRow = 1 To LastRow        
                NewName = Cells(MyRow, 1).Value
                FullOldName = Cells(MyRow, 2).Value
               '*********************************** Pathの切り取り
               MyCnt = InStrRev(FullOldName, "\", , vbTextCompare)
               FullPath = Left(FullOldName, MyCnt)
               FullNewName = FullPath & NewName            
                Name FullOldName As FullNewName 'ファイル名の変更
        Next    
    MsgBox "処理が完了しました。"    
    End With
End Sub
***********************************

  シート(1)に、コマンドボタンを作成しましたので、操作は簡単です。














     考えてみると、excelを使うということは、文字列の置換等の機能が使えるので、直接ファイル名を一つ一つ時間をかけて書き換える必要がなくて便利だろうと想像できます。
 明日からこれを使ってファイル名整理したいと思います。

 追記: 時々エラーが出るので、一部のプログラムを修正しました。

0 件のコメント:

コメントを投稿