特定のフォルダにあるExcelファイルを全部開き、各A1の値をコピーして一つのファイルに集約する
特定のフォルダにあるExcelファイルを全て開き、その中身を集約する場面があった。そこで昔を振り返りながら、わがマクロの変遷を辿ってみる。
例えば、↓ こんな感じでファイルが三つあるとする。
実際の場面では、毎回何個か分からないだろうが、とりあえず今回は三個とする。
それぞのシートのA1には、食べ物の名前が入力されている。
昔はとにかく、決め打ちだった。パスも固定で、一つずれれば手直しが必要。
Sub Test_1() Workbooks.Open ("C:\Temp\test1.xlsx") Range("A1").Copy ActiveWorkbook.Close Range("A1").PasteSpecial Workbooks.Open ("C:\Temp\test2.xlsx") Range("A1").Copy ActiveWorkbook.Close Range("A2").PasteSpecial Workbooks.Open ("C:\Temp\test3.xlsx") Range("A1").Copy ActiveWorkbook.Close Range("A3").PasteSpecial End Sub
これを活かしつつ修正するとしたら、こんな感じかな。
Sub Test_1() Dim i As Long For i = 1 To 3 Workbooks.Open ("C:\Temp\test" & i & ".xlsx") Range("A1").Copy ActiveWorkbook.Close Cells(i, 1).PasteSpecial Next End Sub
しかし実際は、毎回こんな都合の良いファイル名であるはずもなく。
時が経ち、Dir関数を覚えた。定番の、Do ~ Loop との組み合わせだ。
Sub Test_2() Const FolderPath As String = "C:\Temp" Dim FileName As String FileName = Dir(FolderPath & "\*.xls*") Workbooks.Open (FolderPath & "\" & FileName) Range("A1").Copy ActiveWorkbook.Close False Range("A1").PasteSpecial FileName = Dir Do While FileName <> "" Workbooks.Open (FolderPath & "\" & FileName) Range("A1").Copy ActiveWorkbook.Close False Range("A" & Rows.Count).End(xlUp).Offset(1).PasteSpecial FileName = Dir Loop End Sub
流石に各ファイルパスの決め打ちは無くなったものの、未だ全体的に野暮ったい。
そして更に時は流れ現在に至る。今ある知識で、贅の限りを尽くしたのがコチラ。
Sub Test_3() ' 画面更新の一時停止。 ' ※ファイルの数だけ開いたり閉じたりするため。 Application.ScreenUpdating = False ' ファイルが保存されたフォルダー。 Const FolderPath As String = "C:\Temp" ' ファイル操作用。 ' MicroSoft Scripting Runtime 参照済み。 Dim FSO As Scripting.FileSystemObject Set FSO = New Scripting.FileSystemObject ' 値格納用。 Dim Dict As Scripting.Dictionary Set Dict = New Scripting.Dictionary Dim File As Scripting.File ' フォルダー内の各ファイルについて処理。 For Each File In FSO.GetFolder(FolderPath).Files ' 拡張子がExcelのものであることを確認する。 ' ※xls*にすることで、xls,xlsx,xlsm,xlsbの全てに対応。 If FSO.GetExtensionName(File.Path) Like "xls*" Then ' リンクの更新要求を避けるため、UpdateLinksはFalseとする。 ' 編集不要なため、読み取り専用(ReadOnly)で開く。 With Workbooks.Open(FileName:=File.Path, _ UpdateLinks:=False, _ ReadOnly:=True) ' ファイルパスをキーに、A1の値をアイテムとして辞書に登録。 Dict(File.Name) = Range("A1").Value ' 用が済んだファイルを閉じる。 .Close False End With End If Next ' 辞書のアイテムは配列なので、シートに一括貼り付けできる。 Range("A1").Resize(UBound(Dict.Keys) + 1) = WorksheetFunction.Transpose(Dict.Items) ' 画面更新停止の解除。 Application.ScreenUpdating = True End Sub
でも実は、PowerQueryを用いれば、マクロ不使用でも同じことができるので、
本当はそれが一番スマートかも。
来年の今頃、同じテーマでもう一度検討してみると、自分の成長度合いが確認
できてよいかも。
参考まで。