コピペで使えるVBA!ファイル名一括変更コード

VBA

フォルダにあるファイル名を一括で変更するVBAマクロを作った。

使い方としては複数のiPhoneから1つのPCに写真を移動させるとファイル名がたまに被る。

なのでファイルの先頭に使っている人の名前を入れたり、写真のファイル名を1から順番に整理したりする事ができる。

動きのイメージ

ローマ字からカタカナに変更したい場合。

こんな感じに一括で変更できる。

  • file1.txt → ファイル1.txt
  • file2.txt → ファイル2.txt

 

ファイルがあるフォルダへマクロのエクセルファイルを保存して使う。

ここに2つファイルがある。

マクロでエクセルに読み込む。
エクセルファイル自体も読み込まれているが変更後のファイル名を入れなければOK。

変更後のファイル名を入力

マクロでファイル名が一括変更される。

コードと解説

Option Explicit
Sub フォルダ内のファイル名をエクセルに貼り付ける()
    Const ファイル名開始行 As Long = 2
    Dim 検索フォルダ As String
    検索フォルダ = ThisWorkbook.Path
    
    Dim FSO, ファイルオブジェクト As Object
    Set FSO = CreateObject("Scripting.FileSystemObject")
    
    Dim ファイル一覧() As Variant, ループカウンタ As Long
    ループカウンタ = 0
    For Each ファイルオブジェクト In FSO.GetFolder(検索フォルダ).Files
        ReDim Preserve ファイル一覧(ループカウンタ)
        ファイル一覧(ループカウンタ) = ファイルオブジェクト.Name
        ループカウンタ = ループカウンタ + 1
    Next
    Dim ファイル数 As Long
    ファイル数 = FSO.GetFolder(検索フォルダ).Files.Count
    
    Const 処理列 As Long = 1
    Dim 入力セル As Range
    Set 入力セル = Range(Cells(ファイル名開始行, 処理列), Cells(ファイル名開始行 + ファイル数 - 1, 処理列))
    入力セル = WorksheetFunction.Transpose(ファイル一覧)
End Sub
Sub 変更する()
    Const 変更前列 As Long = 1, 変更後列 As Long = 2
    Call ファイル名変更処理(変更前列, 変更後列)
End Sub
Sub やっぱり戻す()
    Const 変更前列 As Long = 2, 変更後列 As Long = 1
    Call ファイル名変更処理(変更前列, 変更後列)
End Sub
Sub ファイル名変更処理(ByVal 変更前列 As Long, ByVal 変更後列 As Long)
    Const 開始行 As Long = 2
    Dim 最終行 As Long, フォルダパス As String
    最終行 = Cells(Rows.Count, 変更前列).End(xlUp).Row
    フォルダパス = ThisWorkbook.Path
    
    Dim FSO As Object
    Set FSO = CreateObject("Scripting.FileSystemObject")
    
    Dim ファイルフルパス, 変更前ファイル名, 変更後ファイル名 As String
    Dim R As Long
    For R = 開始行 To 最終行
        変更後ファイル名 = Cells(R, 変更後列)
        If 変更後ファイル名 = "" Then
            GoTo コンテニュー
        End If
        変更前ファイル名 = Cells(R, 変更前列)
        ファイルフルパス = FSO.BuildPath(フォルダパス, 変更前ファイル名)
        FSO.GetFile(ファイルフルパス).Name = 変更後ファイル名
コンテニュー:
    Next
End Sub
1行:コード内の変数宣言を強制させる。書かなくても動作する。
   これを消せば定数以外の宣言はしなくても動作する。
   とにかく動けばOKな時は消しておいて!

2行:タイトル
   これを実行するとエクセルのあるフォルダのファイル一覧がエクセルに記載される。

3行:変更しない変数(定数)を宣言。
   ファイル名を2行目から貼り付けたいので「2」を指定

4行:検索フォルダの変数を文字として宣言。
5行:マクロの書かれたエクセルファイルのフォルダを取得。
7行:オブジェクトを宣言。
   ファイルシステムを入れる「FSO」とファイルを入れる「ファイルオブジェクト」の2つ

8行:ファイルシステムオブジェクトを使う呪文。

10行:2次元配列とカウンタの変数を宣言。
    2次元配列として「ファイル一覧」を宣言するが何でも入るVariantにしておく。
    ファイルは何個あるのかわからないので、ここでは配列の要素数は指定しない。

11行:ループカウンタの変数を「0」にする。
    最初は0なので指定しなくてもいいけど、拡張していくとバグになりやすいので一応「0」を明言しておくといい。

12行:ここでの動作は大きく2つ
    FSO.GetFolder(検索フォルダ).Filesでフォルダ内のファイルを取得
    for Eachは複数ある要素分繰り返す処理。
    取得したファイルを1つずつ処理するために7行で宣言した「ファイルオブジェクト」に取得したファイルの内1つを入れる。

13行:ファイルを入れる2次元配列の要素数を指定する。
    ReDimは再宣言でPreserveは元の要素内容を保持してくれる。
    最初はループカウンタの「0」で再宣言する。要素0は1つの箱のイメージ
    2回目はループカウンタが「1」になっているので要素1は2つの箱のイメージ
    という感じでループするだけ箱が増えていく

14行:ファイルオブジェクトのNameプロパティにファイル名が入っているので配列の箱に入れる。

15行:1つ目の処理が終わったのでカウンタをプラス1する。

16行:Nextなので12行で指定したフォルダ内のファイルを次のファイルを指定した状態にして繰り返す。
    ファイルが最後の場合はforを抜ける。

17行:見つけたファイル数を入れる変数を宣言。

18行:.Countプロパティでファイル数を取得して変数へ格納。
    「FSO.GetFolder(検索フォルダ).Files.Count」のまま使ってもいいが、
    パッと見何か分からないのであえて分かりやすい名前の変数に入れる。
    説明用の変数とも言う。

20行:定数を宣言。
    変更前の列として「1」とする。

21行:Rangeのオブジェクトを宣言。
    Rangeはセルの事

22行:貼り付けたいセルをRangeオブジェクトへ入れる。
    セルの範囲を指定している。
    1つ目のCells()が最初のセルで2つ目のCells()が最後のセル

23行:取得したファイル名が入った2次元配列をエクセルに貼り付ける。
    長い文字が続いているが、イメージとしては2次元配列は横並びだとしたら。
    今回貼り付けるのは縦並びのセルなので横から縦にする呪文!

24行:これでエクセルへの貼り付け処理は終わり。

25行:タイトル
    これを実行すると変更前のファイル名が変更後のファイル名に変更される。

26行:変更前の列と変更後の列を定数として宣言。
    それぞれ1列目と2列目にしている。

27行:この後に出てくる「ファイル名変更処理」を呼び出している。
    Callは書かなくてもいいが呼び出している事が分かりやすいので書いている。
    後ろの()は呼び出し先へ渡したい値を指定している。
    33行の処理から見てもらいたい。

28行:基本的に呼び出し先で完結するようにしているのでここで処理は終わり。

29行:タイトル
    これは1度変更したけどやっぱり戻したくなった時に使う処理。
    変更前と変更後の列の番号が入れ替わっているだけだ。

30行:変更前の列と変更後の列を定数として宣言。
    それぞれ1列目と2列目にしている。

31行:この後に出てくる「ファイル名変更処理」を呼び出している。
    Callは書かなくてもいいが呼び出している事が分かりやすいので書いている。
    後ろの()は呼び出し先へ渡したい値を指定している。
    33行の処理から見てもらいたい。

32行:基本的に呼び出し先で完結するようにしているのでここで処理は終わり。

33行:タイトル
    27行目や31行目から実行される処理。
    実行された時に2つの値を渡されているので()の中で受け取っている。
    受け取りの際に数値型のLongを宣言している。
    ByValは値渡しといって呼び出し元の変数を変えたくない場合に使う。

34行:変更しない変数(定数)を宣言。
    ファイル名を2行目から取得したいので「2」を指定。

35行:変数を宣言。
36行:データの入っている最終行を取得している。
    1列目の一番下のセルから「CTRL+↑」を実行した時の行。
    よく使うので呪文に近い。

37行:マクロの書かれたエクセルファイルのフォルダを取得。

39行:オブジェクトを宣言。
   ファイルシステムを入れる「FSO」とファイルを入れる「ファイルオブジェクト」の2つ

40行:ファイルシステムオブジェクトを使う呪文。

42行:変数を宣言。

43行:変数を宣言。

44行:forでファイル名の入っている行数分繰り替えす。
    Rに行数を入れて使用する。

45行:変更後のファイル名を変数へ格納する。
    分かりやすくするための説明用変数。

46行:変更後のファイル名が空欄か確認するif文。
    ここでは
    もし「変更後ファイル名」が空欄だった場合にEnd Ifまでの処理を実行する事になっている。

47行:ファイル名が空欄の場合は処理をスキップさせたいので、
    GoToを使いNextの直前にある「コンテニュー:」へジャンプする。
    他言語ではよくある「Continue」コマンドがVBAでは存在しないのでこうするしかない。

48行:if文の終了であるEnd Ifを記載している。
    実際は47行目でジャンプするのでここを通過する事はない。
    if文の公文エラーになるので書く。

49行:変更前のファイル名を変数へ格納する。
    分かりやすくするための説明用変数。

50行:フォルダパスとファイル名を合体させてファイルのフルパスにしている。
    BuildPathを使っているが「&」を使った文字列の結合でもいい。
    ファイルフルパス = フォルダパス & 変更前ファイル名

51行:ファイル名を変更している。
    GetFileで変更前のファイルを取得してNameプロパティで名前を指定
    そこへ「変更後ファイル名」を格納する事で変更している。

52行:47行でのGoToのジャンプ先となっている。

53行:Nextなので44行で指定したRの値をプラス1して45行へ戻って繰り返す。
    Rが最終行の値になるとforを抜けて54行へ進む。

54行:変更処理はここで終わりなので呼び出し元の27行や31行の次の行へ戻る。

最後に

今回のコードはファイルシステムオブジェクトとfor eachがうまく使えるかが鍵になっていると思う。

ファイル名が被った時のエラー処理などしなかったので実際に使うときは気を付けてもらいたい。

13行目にあるReDim Preserveの配列再宣言の部分は間違えて何度かエラーになったΣ(・口・)

忘れているところがあったので良い復習になった。

配列再宣言は初めてやろうとすると躓きやすいので参考にしてもらえたら嬉しい。

コメント

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