フォルダにあるファイル名を一括で変更する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行の次の行へ戻る。
VBAはどうやって覚える?
プログラムのコードが読めないと、参考にしているコードの理解や自分でプログラムを書くときに時間がかかってしまいます。そんな時は基礎から学ぶと応用もできるようになり自分の作りたいプログラムがスムーズに作れるようになります。
無料でやるならネット上の学習サイトを参考にするといいです。
こちらはVBAの基礎から説明している無料のWEBサイトになります。
>>基礎から学べるWEBサイトを見てみる
過去にネットでの学習でつまずいた方には専門書をオススメします。
本なら基礎から学べる事はもちろん、読者視点で分かりやすい解説になっています。
一人で集中してコツコツ進めたい方は書籍を試してください。
本を読んでもわからない所が多すぎたり、誰かに質問したい場合はオンラインスクールを見てみましょう。
カウンセリングから目的に応じた学習プランと教材を提供してくれるので、プログラミングの敷居がとても低くなります。
誰かに相談できるのは心強いです。
>>オンラインスクールを無料体験で始める
最後に
今回のコードはファイルシステムオブジェクトとfor eachがうまく使えるかが鍵になっていると思う。
ファイル名が被った時のエラー処理などしなかったので実際に使うときは気を付けてもらいたい。
13行目にあるReDim Preserveの配列再宣言の部分は間違えて何度かエラーになったΣ(・口・)
忘れているところがあったので良い復習になった。
配列再宣言は初めてやろうとすると躓きやすいので参考にしてもらえたら嬉しい。