PowerQueryでテンプレートファイルにマスタデータを自動反映させる　～クエリでデータ取得から結合まで～

# はじめに

業務で、複数人の人にExcelへ記入してもらうテンプレートを作成することになりました。
ただこのテンプレート、「複数のデータマスタが必要」で、「ドロップダウンの項目が随時増えるかもしれない」し「項目が変わったら全テンプレートに反映が必要」なのです。

そこで、PowerQueryを利用してマスタファイルから、利用者が使用時に更新してデータを再取得することで、いちいちテンプレート差替え・再配布しなくてよくできるようにしたいと思います。

ちなみに、テンプレートファイルにマスタデータを取り込む際は、テンプレート側には何個もテンプレートの項目シート用意したくないので、マスタデータを1シートに纏めちゃおうと考えています。
（見た目は微妙だけど、項目のシートは非表示にしちゃうので。。）

イメージ図はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/f911595b-3413-bade-bf76-8ae5dbe8879c.png)

# 使用環境
使用環境は、Windows10 で Office365 の Excel です。

# PowerQueryとは
（これはこちらの参考サイトの受け売り）

https://qiita.com/mosugi/items/71df310b35db81722d1e

PowerQueryとは、2016年に公開されたMicrosoft製のデータ分析用Excelアドインであり、Excel2010以降に対応しています。2010、2013はアドインのインストールをすることで利用可能です。

ファイル・DB・Webサービス等からデータを読み込み、変換・加工してExcelのシートに出力できます。VBAのマクロの記録と同じように、画面上で操作するとクエリ（読み込み手順の定義）が生成されます。複雑な加工をしない限りプログラミングは必要ありません。

 **Excel内に全ての情報を格納するため、一つのファイルで完結し他のツールは必要ありません。** 

中間処理は全てメモリ上で行われ、処理が非常に高速であることが特徴です。
ファイルに出力されるのは最終の出力結果のみであるため、ファイルサイズも少なく済みます。

## まずはマスタファイル作成

マスタファイルを準備して、所定のフォルダに保存します。
今回は商品マスタと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/5521308d-cdcf-30de-4fa1-56508ac26014.png)

社員マスタの2つを用意しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/645f3488-74bd-a087-e55e-5ff6f6bbb37a.png)

## テンプレートを作成

テンプレートは、とりあえず入力させたいカラムを準備。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/00410e7e-c4fa-af62-2a78-5015321e5fcd.png)

## PowerQueryエディタを起動→データの取得
いよいよPowerQueryを使っていきます。
Excelの「データ」タブ→「データの取得」→「PowerQueryエディターの起動」を押下します。
![SS1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/3ef97702-c485-fc9e-d1d8-fdf3bde15d21.png)

すると空っぽのPowerQueryエディターが開きます。
ここで、「新しいソース」→「ファイル」→「Excelブック」を選択します。
![SS2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/bf255693-508b-0e1e-d08e-bbcaaff3c52d.png)

ファイル選択のポップアップが開くので、先ほど作成したマスタファイルを選択して「開く」を押下。

![SS3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/95b00808-7bdc-9ff1-5272-5ea968157332.png)

するとマスタファイルの各シートが表示されました。
ここでは、2つのマスタデータを取り込みたいので、「複数のアイテムの選択」にチェックを入れて、
「社員マスタ」と「商品マスタ」を選択。「OK」を押下します。
![SS4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/2679c28a-a638-7c73-a9e4-8809586521bd.png)


データが取り込めました！まずは第一関門突破。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/6058e9c7-9def-2123-0c50-d4835dcdcbb2.png)

## クエリの結合

マスタを結合する前に、どのレコードはどのマスタなのか、という分類が必要そうなので、それぞれのマスタクエリに1列追加します。
（本当は自クエリの名称を列で追加出来たらよかったのですが、上手く見つからず。。諦めて力技です。笑）
「列の追加」タブ→「例からの列」を押下します。
![SS10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/60b15640-9c39-a50f-387f-400dffbc1c4f.png)

画面右に、新規追加したい列が出てくるので、サンプルでいくつか入力してみます。
ここではマスタ名として「社員」と2行分入れてみたところ、予測で全行に「社員」が入りました。
ただのリテラル列になっちゃったけど、仕方ない。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/1d9aa254-d9ce-c178-0be5-4480e97fc6ae.png)

はい、マスタの列が追加できました。
商品マスタ側でも同様に列の追加をしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/f8a2df2f-0d81-86a2-b2c7-4d943b644e06.png)

では、クエリを結合していきましょう。
画面左のクエリリストのあたりで「右クリック」→「結合」→「クエリを新規クエリとして追加」を押下します。
![SS6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/65b47c9a-d243-d7a8-ee09-409fb9973997.png)


行結合する対象のクエリを選択するポップアップが出るので、「2つのテーブル」を選んで、「社員マスタ」と「商品マスタ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/72254145-8ea7-3a33-624e-324d43cc5fe9.png)

「追加1」というクエリが完成！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/986d795b-6c61-b0c5-ebfd-fb0acb4ec494.png)

いらないヘッダーが混ざっているのはフィルターではじきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/0dec6312-5f87-342a-2a7c-f933b2a715f2.png)

列名はダブルクリックで任意の名前に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/7d33c9db-b196-e904-8038-9cc45b7e7188.png)

クエリ名もダブルクリックで任意の名前に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/1ad061dd-72cb-6f0f-f17a-bdd460a50f16.png)

これでOK！「閉じて読み込む」ボタンを押下します。
![SS7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/6482fb64-ded1-1790-8251-912ff0efffa1.png)

## マスタ情報を結合したシートが完成

これでマスタデータの取り込み設定が完成です。
テーブルになって表示されてますね。
![SS8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/79e953a7-3238-7209-a087-8e3c4cd6c0a9.png)

いらないシートは消しちゃいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/36e0e8c4-7595-787d-13ef-baf4058f163f.png)

## テンプレートシート側にドロップダウンリストを設定

最後の仕上げとして、ドロップダウンリストを作成します。
テンプレートでは、「部署名」を選択したらその部署に応じた「社員名」が表示されてほしいのですが、今のままの項目情報だと単純な範囲選択では重複データが表示されてしまいます。
そのため、テンプレートシートの右端に重複を削除したレコードリストを作成します。

参考にしたのはこちらのサイトです。

https://kokodane.com/kan365_02.htm

関数はUNIQUE関数とFILTER関数を利用するようです。
例として、部署名のリスト表示から作成してみます。

書き方はこんな感じです。
```
=UNIQUE(FILTER(項目情報_2[[#すべて],[小分類]],項目情報_2[[#すべて],[大分類]]="社員"))
```

PowerQueryで取得したクエリはテーブルとして定義されるので、列を指定する際もPowerQUeryで自動定義された範囲で指定できるんですね。
（ドラッグして範囲指定すると自動でこういった表示になります）
![SS11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/93dca559-9f90-e2a7-40af-4e3096d588a6.png)

Enterを押下すると、部署のリスト（スピルというらしい）ができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/3f0181b2-b8fa-0075-f4c2-59988857f392.png)

これをA列「部署名」のドロップダウンリストに設定します。
対象範囲を選択して、「データ」タブ→「データツール」の真ん中一番下のアイコン→「データの入力規則」を押下します。
![SS9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/fcd9256e-5e65-2c71-663c-e86e5eba7712.png)

「データの入力規則」のポップアップが表示されます。
「設定」タブの「入力値の種類」で「リスト」を選択し、「元の値」に部署リストの最上位セルを選択して末尾に「#」を付けます。
（#によってスピルを指定可能な模様）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/57eba528-75ea-0b94-6ac3-7aeb866286b9.png)

これで部署名のドロップダウンリストができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/0256aa53-8299-dbfa-3c94-0e7fb67f8765.png)

次は選択した部署の社員名をドロップダウンリストにします。
これはこちらのサイトを参考にしました。

http://www4.synapse.ne.jp/yone/excel/excel_input_list5.html

OFFSET関数とMUCH関数を利用するようですね。
直接社員名列を選択して、同様にデータの入力規則を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/05bf0a3b-2c46-8716-f067-e82ede74084d.png)

分かりづらいですが、指定した関数はこちらです。

```
=OFFSET(項目情報!$B$1, MATCH($A2,項目情報!$B:$B,0)-1, 1, COUNTIF(項目情報!$B:$B,$A2),1)
```

OKを押下することで、無事隣のセルの入力値によってドロップダウンリストが変わるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/a7461fb8-678f-a222-fd1f-d662701f7d77.png)

商品側でも同様に行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/ed091612-a612-ecbf-0d28-b98e1b77b5c3.png)


## マスタデータに変更が入ったらちゃんと更新されるのか

これで基本構造は完成です！
最後に、マスタに社員や商品が追加された場合にちゃんと反映してくれるかを確認します。

社員に「松本」さんを、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/fb3e566b-b135-d6da-8e26-a0985bd17d93.png)

商品に「金平糖」を追加してみます。
そういえば今回データのPowerQueryでソートを設定するのを忘れてしまったので、データは和菓子群の一番下に挿入します。
次に作るときはちゃんとソートも指定しますね。
（たぶんデータ位置が分類間を飛んでしまうと、ドロップダウンリストで上手く拾えないんじゃないかな…）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/52957688-c09d-c6c3-6f7a-38e75d2f9de9.png)

マスタファイルを保存したら、再度テンプレートファイルを開きます。
「データ」タブ→「すべて更新」を押下すると…
![SS12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/8aa4d874-e346-f2e4-ded1-a6ff9566ca81.png)

おお！ちゃんとデータが増えてますね！
![SS13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/d80065fb-929a-8aad-3817-f034bacac4a0.png)

「テンプレート」シートでもドロップダウンリストが増えています！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165503/89adac3a-7a02-0807-b48a-436162c7a611.png)

## おわりに

はじめてPowerQueryを使ってみましたが、かなり早いですね！
データの更新速度も、ネットワーク速度によるとは思いますが全然ストレスなく更新されました。
PowerQueryエディターはちょっと癖がありますが、おおむね直観的操作でできたように思います。

マスターデータのの結合にはデータ項目数を合わせる必要があったりで、ちょっとコアな記事になってしまいました。
どこかに需要があるといいなあ…。