みなさん、こんにちはケンケンです。
今回は、ファイルやフォルダを操作して、ファイル名一覧を作成したりファイルに記述されているデータを取得してシートに転記する方法をご紹介します。
実務で無数のファイルと格闘している方も多いと思います。
ファイルが多くなると当然作業効率は悪くなり、目的のファイルを検索するのもストレスがかかります。
それを解消するための第一歩は、フォルダ内に存在しているファイル名を瞬時に取得できる仕組みを作っておくことです。
今回は、フォルダ内を検索しファイル名とその内容を転記できるテクニックをご紹介します。
ファイル名を取得(Dir関数)
それでは、ファイル名を取得するところから始めます。
フォルダとファイル構成は以下のようになります。
フォルダ操作というフォルダの中にBook1からBook6までと、VBA登録用の転記先ファイルを用意しました。
それでは、転記先ファイルにBook1からBook6までのファイル名を取得して転記していきます。
最初に転記先ファイルに「ファイル名一覧」と「詳細転記」シートを用意します。
VBEを起動し、以下のコードを書いてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Sub file_folder() Dim bookN 'ファイル名を格納する変数 Dim tenkiCnt '入力行数を格納する変数 tenkiCnt = 2 '入力開始行数を格納 Columns(1).ClearContents '転記先の列を消去→初期化 Range("A1").Value = "ファイル名一覧" bookN = Dir(ThisWorkbook.Path & "\book*")'「"\book*"」の「\」は「¥」 Do While bookN <> "" '変数bookNに文字列が格納されなくなるまで Range("A" & tenkiCnt).Value = bookN tenkiCnt = tenkiCnt + 1 bookN = Dir() Loop End Sub |
ファイル名一覧シート上でコードを実行すると、以下のように一覧を作成することが出来ます。
それでは、コードの解説をします。
Dim bookN
Dim tenkiCnt
まず、ファイル名を格納する変数bookNとファイル名を転記先の行数を指定するための変数tenkiCntを用意します。
tenkiCnt = 2
転記先の行数は2行目からを想定しているのでデフォルトで2を格納します。
Columns(1).ClearContents
A列に記載されている文字を消去します。初期化のことです。
Range(“A1”).Value = “ファイル名一覧”
A列が初期化されて空白になっているのでA1セルにファイル名一覧と記述します。
bookN = Dir(ThisWorkbook.Path & “\book*”)
まずお断りしておきますが、「”\book*”」の「\」は「¥」のことです。CSSの仕様の問題らしいのでここでは特に触れません。
Dir関数は、括弧内(引数)に指定したファイルがあった場合にファイル名を返し、存在しないときは空欄を返す関数です。
大事なのは、Dir関数の引数です。
括弧内の引数ThisWorkbook.Pathについては、今いるフォルダのパスを表しています。
以前ご紹介しましたので詳しくはこちらをご覧ください。
今いるフォルダは「フォルダ操作」ですね。
そして、¥book*の内、¥は一つ下の階層を表します。つまり、「フォルダ操作」という名前のフォルダ内のことです。
そしてbook*の「*」はアスタリスクと呼ばれるもので、今回はワイルドカードの役目を果たします。
ワイルドカードとは部分的に等しい文字列などを検索することができるものです。
book*を日本語に翻訳すると、bookから始まる名前のファイル、ということです。
改めてbookN = Dir(ThisWorkbook.Path & “¥book*”)を解説すると
フォルダ操作フォルダ内にあるbookから始まるファイルを変数bookNに格納する、ということです。
具体的には、「Book1.xlsx」が格納されているはずです。
Do While bookN <> “”
Range(“A” & tenkiCnt).Value = bookN
tenkiCnt = tenkiCnt + 1
bookN = Dir()
Loop
DoLoopステートメントをご紹介します。
条件が満たされているうちはDoとLoopの間の処理が繰り返し行われます。
繰り返し文でおなじみのForNext構文との違いは、ForNextでは、初めから終わりまでの回数が分かっている時に使い、DoLoopはいつ終わるか分からないときに使うということです。
今回は、フォルダ内にいくつのファイルが存在しているか不明なのでDoLoopを使っていきます。
それでは、コードを1行ずつ解説します。
Do While bookN <> “”
これは、変数bookNにファイル名が格納されている場合は、Loopまでの処理をする、という意味です。
<>は~~ではないとき、を表します。
つまり「bookN <> “”」は、bookNが空白でないとき→bookNに格納されているとき、と解釈できます。
Range(“A” & tenkiCnt).Value = bookN
変数bookNに格納されているファイル名を転記します。最初の処理はA2セルに転記します。
tenkiCnt = tenkiCnt + 1
A2セルに転記したら次はA3セルに転記したいので、転記先行数を格納する変数tenkiCntの値に1プラスします。
bookN = Dir()
転記したファイル以外のファイル名をDir関数で取得し、変数bookNに格納します。
なぜDir()で次のファイル名を取得できるか不思議に思ったかもしれませんが、僕も不思議です。
いろいろ調べてみましたが、どうやら答えは「そういう仕様だから」ということらしいです。
つまり、理論的に説明はできないようです。説明できる方は教えてください。
説明はできませんが、Dir関数が起こすアクションを順番にまとめることはできます。
- 最初にワイルドカードで指定して検索されたファイル名が返る
- 2回目以降はDir関数の引数を省略すると前回のワイルドカードを指定した前提で次のファイルを探す
- すでに検索済みのファイルは除外されて検索される
このようになるみたいです。
コードの解説は以上となります。
便利なので理屈はともかくテンプレートとして覚えてしまった方が良いでしょう。
ファイルを開いて転記する
次は、それぞれのファイルを展開してA1セルに記述されている文字列を詳細転記シートに転記してみましょう。
コードの完成形からご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Sub file_folder2() Application.ScreenUpdating = False '画面の更新を止める Dim fileLrow fileLrow = Workbooks("転記先.xlsm").Sheets("ファイル名一覧").Range("A" & Rows.Count).End(xlUp).Row Sheets("詳細転記").Columns(1).ClearContents '転記先の列を消去→初期化 Sheets("詳細転記").Range("A1").Value = "詳細転記" Dim fileTenki For fileTenki = 2 To fileLrow Workbooks.Open ThisWorkbook.Path & "\" & Range("A" & fileTenki).Value Workbooks("転記先.xlsm").Sheets("詳細転記").Range("A" & fileTenki).Value = Range("A1").Value ActiveWorkbook.Close Next End Sub |
新しいプロシージャを作成し、コードを記述してください。
ちなみに、Book1からBook6のA1セルには以下のように記述されています。
コードをファイル名一覧シートで実行すると、「詳細転記」シートに各ファイルから転記されます。
それでは、コードの解説をしていきます。
Application.ScreenUpdating = False
このコードで画面更新を止めることができます。
ファイルを開いて閉じてを繰り返すと画面が開いたファイルに自動で移動してしまい、その分処理が遅くなります。
そこで、このコードを記述することで画面移動の時間を短縮できます。
FalseをTrueに変更すると画面更新を再開できます。
処理対象の数が増えると処理時間も多くなってしまうので最初に一行書いておきます。
Dim fileLrow
fileLrow = Workbooks(“転記先.xlsm”).Sheets(“ファイル名一覧”).Range(“A” & Rows.Count).End(xlUp).Row
ファイル名一覧シートに記述したファイル名の最終行を取得しています。
Sheets(“詳細転記”).Columns(1).ClearContents
Sheets(“詳細転記”).Range(“A1”).Value = “詳細転記”
A列を初期化してA1セルに「詳細転記」と記述するコードです。先ほどファイル名を取得した際と同じですね。
Dim fileTenki
For fileTenki = 2 To fileLrow
Workbooks.Open ThisWorkbook.Path & “\” & Range(“A” & fileTenki).Value
Workbooks(“転記先.xlsm”).Sheets(“詳細転記”).Range(“A” & fileTenki).Value = Range(“A1”).Value
ActiveWorkbook.Close
Next
格子はForNext構文になってます。
ForNextの中の処理内容は、ファイル名一覧に記述されたファイルを一つずつ開いてA1セルの値を詳細転記シートへ転記するものです。
カウント変数fileTenkiを用意して2(行目)からfileLrow(7行目)まで処理を繰り返します。
Workbooks.Open~~
Openメソッドを使ってファイルを開くコードです。~~の部分にファイルのパスとファイル名を記述します。
ThisWorkbook.Path & “\” & Range(“A” & fileTenki).Value
上記コードが開こうとするファイルパスとファイル名となります。変数fileTenkiに「2」が入っている場合は、Book1を指定することになります。
Workbooks(“転記先.xlsm”).Sheets(“詳細転記”).Range(“A” & fileTenki).Value = Range(“A1”).Value
開いたファイルのA1セルの値を詳細転記シートに転記します。
Workbooks(“~~~”)でファイルを指定できます。~~~の部分にファイル名を記述します。
ActiveWorkbook.Close
Closeメソッドで開いたファイルを閉じます。
プロシージャをまとめてボタンを作成する
今回2つのプロシージャを作ったのでひとつにまとめましょう。
1 2 3 4 |
Sub file_folder_kansei() Call file_folder Call file_folder2 End Sub |
そして、ファイル名一覧シート上にボタンを作成します。
これで完成です。
まとめ
ファイルやフォルダの操作ができるようになると、業務の幅が広がっていきます。
複数の部署にまたがった資料を瞬時に検索し、必要なデータだけ収集することも可能です。
この手の業務に時間をかけていた方は是非今回の方法を試してみてください。
また、今回作ったもののファイル名を変更してBookから始まるファイル以外のファイルがあった場合にはどういう挙動をするか、などいろいろ試してください。新しい発見があるかもしれません。
今後もファイルフォルダ操作を使って応用的なテクニックもご紹介していきますのでご期待ください。
おすすめ記事
- 【ExcelVBA】文字列操作で業務を快適に①【Left関数Right関数Mid関数】
- 【ExcelVBA】文字列操作で業務を快適に②【Instr関数を使いこなす】
- 【エクセルVBA番外編】実務で使えるテクニック紹介します
- 【ExcelVBA】指定した範囲だけスクロールさせる【イベントの基本】