Power BI カスタムコネクター開発 : いつも使っている Power Query をパッケージする

この記事では、すでに持っている M コードを Power BI カスタムコネクタとしてパッケージする方法について紹介します。普段 PowerPlatform しか使っていないから Visual Studio とか開発はちょっとという方にも、はじめの一歩としてお勧めです。


# 前提条件

- [Power BI Desktop](https://powerbi.microsoft.com/en-us/desktop/)
- [Visual Studio](https://visualstudio.microsoft.com/vs/)
- [Power Query SDK](https://marketplace.visualstudio.com/items?itemName=Dakahn.PowerQuerySDK)

それぞれウィザードに従ってインストールしてください。Visual Studio のどの機能が必要かまでは情報がないので、気になるワークロード適当に入れてみてください。

# 既存の M スニペットから始める

みなさんがどんなコードを使っているか知らないので、ここでは [TripPin Service](https://www.odata.org/blog/trippin-new-odata-v4-sample-service/) という認証不要の JSON データを返すだけの Web サービスをデータソースにします。

## データを読み込む

1\. Power BI Desktop を開いて「空のクエリ」を選択。

2\. 詳細エディタで以下の関数一つを含むスクリプトを張り付け。

```fsharp
let    
    GetAirports = () as table =>
        let
            DefaultRequestHeaders = [
                #"Accept" = "application/json;odata.metadata=minimal",
                #"OData-MaxVersion" = "4.0"
            ],
            source = Web.Contents("https://services.odata.org/v4/TripPinService/Airports", [ Headers=DefaultRequestHeaders ]),
            json = Json.Document(source),
            value = json[value],
            toTable = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
        in 
            toTable,
    airports = GetAirports(),
    #"Expanded Airport" = Table.ExpandRecordColumn(airports, "Column1", {"IcaoCode", "Name", "IataCode", "Location"}, {"IcaoCode", "Name", "IataCode", "Location"}),
    #"Expanded Location" = Table.ExpandRecordColumn(#"Expanded Airport", "Location", {"Address", "City", "Loc"}, {"Address", "City", "Loc"}),
    #"Expanded City" = Table.ExpandRecordColumn(#"Expanded Location", "City", {"CountryRegion", "Name", "Region"}, {"CountryRegion", "Name.1", "Region"}),
    #"Expanded Loc" = Table.ExpandRecordColumn(#"Expanded City", "Loc", {"type", "coordinates", "crs"}, {"type", "coordinates", "crs"}),
    #"Extracted Values" = Table.TransformColumns(#"Expanded Loc", {"coordinates", each Text.Combine(List.Transform(_, Text.From), ","), type text}),
    #"Expanded crs" = Table.ExpandRecordColumn(#"Extracted Values", "crs", {"properties"}, {"properties"}),
    airportsDetail = Table.ExpandRecordColumn(#"Expanded crs", "properties", {"name"}, {"crs"})
in
    airportsDetail
```
3\. データが表示されることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/46f45a83-5745-e7d2-1836-8598f0a1f749.png)

4\. カスタムコネクタを読み込むには設定を変える必要があるので、設定を変更する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/9cfe8a13-9a39-8409-9767-cf713e114731.png)

ではこの M スニペットをカスタムコネクタにしていきます。

## プロジェクトの作成

1\. Visual Studio 2019 を開いて「新しいプロジェクトの作成」をクリック。

2\. **Data Connector Project** で検索してテンプレートを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/c028c676-eba5-39b9-cae9-25be52d4c327.png)

3\. プロジェクト名を指定。ここでは **TripPinConnector** として作成。プロジェクトが作成されると複数のファイルが作成されるが、重要なのは以下のファイル。

- *.pq ファイル: コードを書くメインのファイル
- *.query.pg ファイル: テスト用のファイル

4\. pq ファイルを開いて中身を確認。

安心してください。M 言語です。

## M スニペットの移行

次にスニペットを以降していきます。ほぼ同じ構文ですが、Power BI の詳細エディタと異なりすべての関数を一気に書かないため、それぞれの関数の終わりはセミコロン［;］にします。

1\. GetAirports 関数を張り付ける。場所は任意だがここでは **shared** セクションの直下とした。関数の最後がセミコロンである点に注意。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/4c0454e7-9dcf-26b3-d974-1726a2c06e49.png)

2\. 次の残りのコードを shared に移行。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/a69ed904-0735-4cd1-d64e-0de2cf7f89e9.png)

作業はこれだけです。

## テスト

書いたスクリプトが動作するかテストします。

1\. query.pq ファイルを開き、既存の shared 関数を実行していることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/64eb18b1-f56e-6a4f-4247-abfeb005c09b.png)

2\. F5 キーを押下するか「開始」ボタンをクリック。認証の設定を聞かれるので、**Anonymous** を選択し「Set Credential」で保存。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/b9a3c522-fd5d-002e-d025-92ace8c83aa3.png)

3\. 再度 F5 を押下。結果が表示されることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/e605044b-58ce-1b16-9316-db9cbf6bf425.png)

簡単ですね。

## 展開

最後にコネクタをパッケージして展開してみましょう。

1\. プロジェクトを保存したフォルダ | bin | Debug にある *.mez ファイルをコピー。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/f3eb16e6-6c01-86a8-063b-de733dd8a37c.png)

2\. ファイルを C:\users\user_name\Documents\Power BI Desktop\Custom Connectors フォルダにコピー。なければ手動で作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/42244e87-607b-6d77-2fb3-f02bfb271c79.png)

# Power BI Desktop で読み込み

1\. Power BI Desktop を再起動して「データを取得」を選択。

2\. "TripPin" で検索して接続。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/f99c5e65-164c-6da7-c34f-508e5c6f3770.png)

3\. メッセージが出るので読んで「続行」をクリック。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/5d82a07e-cf28-25b7-9d29-97617274ec54.png)

4\. 匿名認証のみ表示されるので、「接続」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/49963262-36f8-31f0-ed9d-19c72c4a3ee1.png)

5\. 必要に応じて「読み込み」または「データの変換」を実行。操作は通常のコネクタと同様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214116/34d8c4d7-626e-a4a9-6c03-36762c6368bd.png)

# まとめ

この記事では、細かいことはさておき、まずカスタムコネクタを開発する手順について説明しました。まだまだ疑問は多くあると思います。

- 関数名は変更できるか？
- 他の機能などはどう実装するのか？
- ブランディングはどうやるのか？
- Debug ビルドのままでいいの？
- 認証あるエンドポイントはどうするか？

これらの疑問は以降の記事で紹介していきます。次はよくある認証のパターンとして OAuth を扱います。エンドポイントは Microsoft Graph です。待ちきれない方は [My Graph sample](https://github.com/microsoft/DataConnectors/tree/master/samples/MyGraph) にあるサンプルを参照してください。説明のリンク切れてる問題がありますが。。

[次の記事へ](https://qiita.com/kenakamu/items/b0b8b3572eef3ca95ee6)