この記事では、閉じているExcelファイルからデータを取り出してExcelのシートに出力する方法についてご説明します。
【動画】閉じているExcelファイルからデータを取り出してExcelのシートに出力する実際の動き
本題に入る前に、まずは次の動画をご覧ください。
閉じている6つのExcelファイル「1月.xlsm」「2月.xlsm」「3月.xlsm」「4月.xlsm」「5月.xlsm」「6月.xlsm」の中からデータを取り出して「0164.xlsm」のシートに出力しています。
なお、シートは各ファイルごとに作成し、シート名をそのファイル名で付けています。
(「1月.xlsm」なら1月、「2月.xlsm」なら2月)
マクロ作成の流れ
なお、今回はシートの有無チェックを行い、シートがなければ生成し、すでにシートが存在する場合はシートの生成は行わず、そのシートをクリアしています。
参照先のExcelファイルが削除されたり移動されたりした場合、計算式が入ったままだと値の参照ができなくなるので、値そのものを再入力させます。
Excelファイルの例
今回用意したExcelファイルは次の通りです。
セルA2に閉じているExcelファイルの置き場を、セルA5からセルA2に閉じているExcelファイル名を記入しています。
この閉じているExcelファイルの置き場と閉じているExcelファイル名とマクロが読み込んでシートに出力します。
コードの例
Excelのマクロのコード(例)
Option Explicit Private Sub btn_dataImport_Click() Dim cnt As Integer 'カウンタ Dim filePath As String 'データが入力されているExcelファイルの格納先 Dim dataFile() As Variant 'データが入力されているExcelファイル用配列 Dim shtExistFlg As Boolean 'シート存在確認フラグ Dim ws As Worksheet 'Worksheet用変数 Dim pstDdSheetNM As String 'データを貼り付ける先のシート名 'データが入力されているExcelファイルの格納先を取得する filePath = Worksheets("work").Range("filePath").Value 'データが入力されているExcelファイル名全てを取得する dataFile = Worksheets("work").Range("A5:A10").Value For cnt = 1 To UBound(dataFile) 'データを貼り付ける先のシート名を取得する pstDdSheetNM = Split(dataFile(cnt, 1), ".")(0) 'データを貼り付ける先のシート有無のチェック For Each ws In Worksheets If ws.Name = pstDdSheetNM Then 'データを貼り付ける先のシート名が存在している場合 '変数「shtExistFlg」にTrueを設定する shtExistFlg = True End If Next ws If shtExistFlg = False Then 'データを貼り付ける先のシートが存在しない場合 'データを貼り付ける先のシートを新規作成する Worksheets.Add(After:=Worksheets(Worksheets.Count)) _ .Name = pstDdSheetNM Else 'データを貼り付ける先のシートが存在する場合 'データを貼り付ける先のシートのセル全てをクリアする Worksheets(pstDdSheetNM).Cells.Clear End If With Worksheets(pstDdSheetNM) 'データを貼り付ける先のシートにデータを貼り付ける .Range("A1:F9").Formula = "=if(ISBLANK('" & filePath & "\[" & dataFile(cnt, 1) & "]work'!A1), """",'" & filePath & "\[" & dataFile(cnt, 1) & "]work'!A1)" '取得先のExcelファイルを参照している計算式がセルに入力されているので、値そのものを再入力する .Range("A1:F9").Value = .Range("A1:F9").Value End With Next cnt End Sub
注目すべきコード①
最初に見て頂きたいのは13行目から16行目です。
'データが入力されているExcelファイルの格納先を取得する filePath = Worksheets("work").Range("filePath").Value 'データが入力されているExcelファイル名全てを取得する dataFile = Worksheets("work").Range("A5:A10").Value
以上のコードは、閉じているExcelファイルの置き場と閉じているExcelファイル名を取得するコードです。
注目すべきコード①
次に見て頂きたいのは21行目です。
'データを貼り付ける先のシート名を取得する pstDdSheetNM = Split(dataFile(cnt, 1), ".")(0)
以上のコードは、生成するシートに付ける名前を取得するコードです。
今回、生成するシートには閉じているExcelファイルの名前を付けたいので、Excelファイルのファイル名から「.xlsm」を取り除いた文字列を取得して変数「pstDdSheetNM」に格納しています。
Split関数の第2引数に「.」を、さらに(0)を指定してSplit関数を実行すると、例えば「1月.xlsm」のExcelファイルの場合は文字列「1月」を返します。
ちなみに(0)ではなく、(1)を指定してSplit関数を実行すると文字列「xlsm」を返します。
注目すべきコード③
次に見て頂きたいのは24行目から52行目です。
'データを貼り付ける先のシート有無のチェック For Each ws In Worksheets If ws.Name = pstDdSheetNM Then 'データを貼り付ける先のシート名が存在している場合 '変数「shtExistFlg」にTrueを設定する shtExistFlg = True End If Next ws If shtExistFlg = False Then 'データを貼り付ける先のシートが存在しない場合 'データを貼り付ける先のシートを新規作成する Worksheets.Add(After:=Worksheets(Worksheets.Count)) _ .Name = pstDdSheetNM Else 'データを貼り付ける先のシートが存在する場合 'データを貼り付ける先のシートのセル全てをクリアする Worksheets(pstDdSheetNM).Cells.Clear End If
以上のコードは、生成するシートの数だけ行うシート有無チェックと、シート生成処理を行うコードです。
24行目でExcelファイルの中のシートの数だけループを行うループ処理のfor文を記述し、26行目でシートの有無チェックを行います。
シートの有無チェックでは、マクロ側のExcelファイル内のシート名(ws.Name)と、閉じているExcelファイルの名前(pstDdSheetNM)が同じかどうかを判定しています。
もし同じの場合は、31行目でシートが存在しているか否かを知らせるフラグshtExistFlgにTrueを設定します。
同じではない場合はFalseのまま後続処理に進みます。
次に37行目で、先ほどのフラグshtExistFlgの値を判定し、もしフラグshtExistFlgがFalseの場合、つまりシートが存在しない場合はシートを生成します。
生成するシート名には閉じているExcelファイルの文字列を付与します。
一方、もしフラグshtExistFlgがTrueの場合(45行目)、つまりシートが存在する場合はシートを生成せず、そのシートをクリアします。(50行目)
注目すべきコード④
次に見て頂きたいのは54行目から62行目です。
With Worksheets(pstDdSheetNM) 'データを貼り付ける先のシートにデータを貼り付ける .Range("A1:F9").Formula = "=if(ISBLANK('" & filePath & "\[" & dataFile(cnt, 1) & "]work'!A1), """",'" & filePath & "\[" & dataFile(cnt, 1) & "]work'!A1)" '取得先のExcelファイルを参照している計算式がセルに入力されているので、値そのものを再入力する .Range("A1:F9").Value = .Range("A1:F9").Value End With
以上のコードは、シートにデータを貼り付ける処理のコードです。
57行目で、閉じているExcelファイルからデータを取り出し、データを貼り付ける先のシートのA1からF9のセルに出力しています。
以上のコードだと変数が使われているので、変数の値をそのまま使ったコードを以下にお見せします。
.Range("A1:F9").Formula = "=if(ISBLANK('C:\work\10_勉強\10_VBA関連\0164\data\[1月.xlsm]work'!A1), "",'C:\work\10_勉強\10_VBA関連\0164\data\[1月.xlsm]work'!A1)"
以上のコードをさらに分解して解説すると、閉じているExcelファイルからデータを取り出すコードは次の通りになります。
‘C:\work\10_勉強\10_VBA関連\0164\data\[1月.xlsm]work’!A1
以上のコードは、「C:\work\10_勉強\10_VBA関連\0164\data」の格納先にある1月.xlsmのExcelファイルのworkというシートのA1の位置からセルの値を取り出す、というコードです。
これでもデータを取り出すことができますが、これをそのまま実行すると一つ問題があります。
その問題というのは、このコードをマクロが実行すると、空白のセルがマクロ側のセルに「0」と表示されてしまう、という事象が起きてしまいます。
また、もし閉じているExcelファイル側にそもそも「0」の値が入力されている場合に、正しい「0」なのかマクロ側の問題による「0」なのか見分けが付きません。
実際にマクロを実行すると下のように表示されてしまいます。
ちなみに閉じているExcelファイル側は下の赤枠のセルが空白のセルとなっています。
以上のように、閉じているExcelファイル側に空白のセルが存在している場合は、マクロ側のセルに「0」の値が出力されないようにする対策が必要になります。
そこで使うのがIF文とISBLANK関数です。
ISBLANK関数は、セルが空白の場合はTRUEを、空白でない場合はFALSEを返します。
このISBLANK関数が返すTRUEかFALSEの値をIF文で判定し、TRUEだったら空白を、FALSEだったら取り出した値をそのまま出力する、と処理させることで「0」の値が出力されてしまう問題は解決することができます。
次に60行目のコードですが、このコードは閉じているExcelファイルから取り込んだマクロ側のセルに対して、値そのものを再入力している処理です。
なぜこの処理を行うのかというと、この処理を行わないと値を参照する閉じているExcelファイルが削除されたり移動された場合に値が参照できすに参照エラーになるからです。
以下は60行目のコードを実行する前のセルの数式は以下の画像の通りです。
以上の画像の赤枠で示した数式を見ると閉じているExcelファイルを参照しています。
このままだと、閉じているExcelファイルが削除されたり移動された場合に値が参照できすに参照エラーになってしまいます。
なので、値そのものを再入力してこの数式を値で上書きするようにすることで、閉じているExcelファイルが削除されたり移動された場合でも問題が起きることが無くなります。
動作確認
マクロ実行前
閉じているExcelファイルの置き場と閉じているExcelファイル名が(黄色枠のセルに)入力された状態です。
マクロ実行後
マクロの実行が正常に完了すると、閉じているExcelファイルのデータがマクロ側のExcelファイルのシートに出力されています。
以下のマクロ側のExcelファイルに「1月」というシートが生成されて、閉じているExcelファイル「1月.xlsm」のデータがシート「1月」に出力されています。
ちなみに以下のExcelファイルが閉じているExcelファイル「1月.xlsm」になります。
以上のExcelファイル「1月.xlsm」以外のExcelファイルからも、全て取り込まれて各シートに出力されたことが確認できました。
最後に
本記事では、閉じているExcelファイルからデータを取り出してExcelのシートに出力する方法についてご説明しました。
マクロが閉じているExcelファイルから一括でデータから、データを取り出したい時は本記事の内容を参考にしてみてくださいね。
Excelのスキル向上やExcelの基礎知識をしっかりと学びたいなら
Excelのスキルを習得したい、Excelの基礎知識をもっと理解したい、そう考えているなら「無期限サポート付きExcel講座【すごい改善】」がおすすめです。
Excelのスキルの基礎を身につけるなら【すごい改善】で無期限サポート付きがあるので、これで「Excelのスキルや基礎」を学ぶのにおすすめですよ。