パワークエリで、特定のフォルダ配下、ファイル、シート名の全シートを結合して読み込む方法

はじめに

以下のような複数フォルダに格納されている複数ファイルのテーブルを結合して読み込む方法を紹介します。
フォルダ名やファイル名に、除外ワード("対象外")がある場合は読み込み対象外とします。

さらに各ファイルには複数シートが存在し、読み込み対象のシートも複数あります。DataXXXという名前のシートが読み込み対象で、はじめにシートや、対象外XXXといったシート名は読み込み対象外とします。


手順

まずは新しいソースから、フォルダを指定してクエリに読み込みます。

冒頭で示したフォルダのルートフォルダ(”データ”フォルダ)を指定すると、以下のダイアログが表示されるので、「編集」を押して読み込みます。

すると、以下のようにフォルダ配下のファイル全てがパワークエリに読み込まれます。

次にフォルダ名やファイル名に除外ワードが含まれている行を、パワークエリのフィルタ機能で除外します。
まずはフォルダ名から除外します。以下のようにフォルダパス名の列の▼ボタンからフィルタ指定ダイアログを出します。ダイアログから、「指定の値を含まない」を選択します。ここでその他の選択肢を使用することで、様々な除外ルールを適用できそうです。

”対象外”と記入します。

フォルダ名に除外ワードを含む行がフィルタされました。

ファイル名の方も同様の手順で除外ワードを含むものをフィルタします。

除外ファイルもフィルタできました。

次に、上で読み込んだ各エクセルファイルのシート一覧をクエリに読み込みます。まずはエクセルファイルからシート一覧を取得する関数を作成します。
パワークエリで空のクエリを作成し、以下のコードを詳細エディタに記載することで、この関数が作成できます。

(エクセルファイル) =>
 let
   ソース = Excel.Workbook(エクセルファイル, null, true)
 in
   ソース

パワークエリ画面では以下のように関数が定義されます。

最初に読み込んだクエリに戻り、カスタム関数の呼び出しをクリックし、先ほど作成した関数を指定します。関数の引数(図中の”エクセルファイル”の欄)には、エクセルファイル自体を表す「Contents」列を指定します。

列が追加されました。

以下のボタンを押して、追加された列を展開します。


すると、各ファイルにシート名の一覧(図中”Name”)と、各シートのデータが「Data」列に読み込まれます。

Name列のシート名の内、”DataXXXX”(Xは数値)というルールに従うシートのみを読み込み対象とするため、このルールでフィルタします。
まずはDataで始まる行のみにフィルタします。
以降Name列の内容を加工する操作をしていくため、まずはName列を複製します。

複製したら、その列に対し、Dataで始まる行のみにフィルタします。

フィルタされました。

Dataの後ろは数値というルールのため、Dataとそれ以降に列を分割します。

分割されました。

右側の列が数値かどうか確認します。右側の列を選択して、以下をクリックします。

一番下の行は数値ではない文字列(”_old”)が含まれていたので、Errorになりました。

このErrorをダミーの数値に変換します。

ここでは-1としておきます。

以下のように-1に置換されました。

あとはこの列が正の値のもののみでフィルタすれば、読み込み対象のシートのみの選択が完了します。手順はこれまでと同様のため割愛します。
結果、読み込み対象のシートのみにフィルタできました。

パワークエリでは正規表現はサポートされていないようです。
ただ、上記のように、フィルタ機能やメニューバーの各機能(型の変換、列の分割、書式、抽出、解析など)を駆使することにより、それなりに高度なフィルタは可能と思います。

各シートのテーブルを展開して結合します。

下のようにテーブル情報(Column1~3の部分)が展開されます。

しかし、各シートの見出しの行(上図でいうA、B、Cと書かれている各行)まで結合されています。
見出し行を除去していきます。
まず、列の削除を使い、ファイル名とシート名を表す列とテーブル情報(Column1~3の部分)だけを残します。以下は削除後です。

各シート(図中のData001などの単位)ごとのテーブルに1始まりの連番を付与し、連番が1の行のみを削除すれば、見出し行の除去はできそうです。ただ、シート名は異なるファイル名でも重複することを考慮し、ファイル名とシート名の組み合わせで、テーブル情報(Column1~3の部分)をグルーピングすることを考えます。
具体的な操作は、以下です。Name(ファイル名)、Name.1(シート名)の列を選択し、グループ化をクリック。その後ダイアログに以下のように指定してOKをクリックします。

下図のようにテーブル情報(Column1~3の部分)がファイル名&シート名の組み合わせごとにグルーピングされ、グルーピング列の各Tableとして格納されました。一番上のTableをクリックすると、図中下段にそのテーブルの内容が表示されます。

次に各グルーピングされたテーブルごとにインデックスを付与します。
具体的にはカスタム列の追加してダイアログに、以下のように記載します。

Table.AddIndexColumn([グルーピング], "index", 1, 1)

上記は、グルーピング列をAddIndexColumn()関数の引数に指定することにより、この列の各テーブルごとにIndex列を追加するという意味です。結果のイメージは以下のとおり。

改めて上の「インデックス付与テーブル」列を展開します。以下のように展開され、期待通りシートごとにグルーピングされたテーブルごとに1始まりの連番が付与されました。

テーブル情報(Column1~3の部分)とIndex以外の列を削除します。

1行目をヘッダーとして使用します。

下のようになります。

1番右の列名が1になってしまいましたが、この列を1以外でフィルタします。

見出し行のみが除去できました。

仕上げに1番右の列を削除して完成です。

いいなと思ったら応援しよう!