ラベル Power BI Desktop の投稿を表示しています。 すべての投稿を表示
ラベル Power BI Desktop の投稿を表示しています。 すべての投稿を表示

2026/05/04

Power BI と M言語:外部API連携のラーニングまとめ

Power BI M言語・API連携 学習メモ

概要

このドキュメントは、Power BI Desktop と Power BI サービスで外部API(connpass API v2、Doorkeeper API)を使ってデータを取得・加工する際に学んだことをまとめたものです。


1. M言語の基本ルール

変数名のルール

  • 数字から始まる変数名は使えない
    • 90日前 = ...
    • 過去90日 = ...
  • スペースを含む場合は #"..." で囲む
  • 日本語の変数名は使用可能

関数の引数名と外側の変数名の衝突に注意

M言語
// ❌ 引数名 subdomain が外側の Query フィールド名と衝突する
GetLatestEvent = (subdomain as text) =>
    Web.Contents(..., [Query=[subdomain = subdomain]])

// ✅ 引数名を sd に変更して衝突を回避
GetLatestEvent = (sd as text) =>
    Web.Contents(..., [Query=[subdomain = sd]])

2. Power BI サービスでの動的クエリの制限

問題

Power BI サービスでは、URLを動的に生成するクエリ(動的データソース)は自動更新できない

解決策:Query=[] オプションを使う

M言語
// ❌ 動的URLとみなされ更新不可
ソース = Web.Contents("https://api.example.com/events?" & "subdomain=" & P1)

// ✅ Query=[] オプションを使うことで更新可能
ソース = Web.Contents(
    "https://api.example.com/events/",
    [
        Query=[subdomain = P1, count = "100"]
    ]
)

重要:Text.Combine も動的とみなされる場合がある

ベースURLは固定の文字列にして、パラメーターは Query=[] に渡す。

3. Power BI サービスでの外部API認証設定

問題

ヘッダーにAPIキーを渡す方式の外部APIは、Power BI サービスの資格情報設定で「匿名」認証が拒否される場合がある。

解決策

資格情報設定画面で以下のように設定する:

設定項目
認証方法匿名
プライバシーレベルPublic
テスト接続をスキップする✅ チェックを入れる ← これが重要!

APIキーはヘッダーで渡す

M言語
ソース = Json.Document(Web.Contents(
    "https://api.example.com/events/",
    [
        Headers=[#"X-API-Key"= "YOUR_API_KEY"],
        Query=[subdomain = P1, count = "100"]
    ]
))

4. 並列読み込みの無効化

複数のクエリが同時にAPIを叩くと、アクセス制限(429 Too Many Requests)に引っかかる。

設定方法

  1. ファイル」→「オプションと設定」→「オプション
  2. 現在のファイル」→「データの読み込み
  3. テーブルの並列読み込み」→「同時ジョブの最大数
  4. 1(並列読み込みを無効にする)」を選択

5. APIのアクセス制限回避:Function.InvokeAfter

APIに1秒間に1リクエストの制限がある場合、Function.InvokeAfter で待機時間を入れる。

M言語
GetLatestEvent = (sd as text) as record =>
    Function.InvokeAfter(
        () =>
            let
                response = try Json.Document(Web.Contents(
                    "https://api.example.com/events/",
                    [
                        Headers=[#"X-API-Key"= "YOUR_API_KEY"],
                        Query=[subdomain = sd, count = "1", order = "2"]
                    ]
                )),
                結果 = if response[HasError] then
                    [最新イベント日 = null, 最新イベントタイトル = "APIエラー: " & response[Error][Message]]
                else if response[Value][results_available] = 0 then
                    [最新イベント日 = null, 最新イベントタイトル = "イベントなし"]
                else
                    [
                        最新イベント日 = response[Value][events]{0}[started_at],
                        最新イベントタイトル = response[Value][events]{0}[title]
                    ]
            in
                結果,
        #duration(0, 0, 0, 1.2)  // 1.2秒待機
    ),

待機時間の目安

待機時間特徴
1.0秒API制限ギリギリ
1.2秒適度な余裕で安全 ✅
1.5秒より安全だが処理時間が長い

6. エラーハンドリング

try...otherwise パターンで途中エラーでも処理を止めない。

M言語
response = try Json.Document(Web.Contents(...)),
結果 = if response[HasError] then
    [最新イベント日 = null, 最新イベントタイトル = "APIエラー: " & response[Error][Message]]
else if response[Value][results_available] = 0 then
    [最新イベント日 = null, 最新イベントタイトル = "イベントなし"]
else
    [
        最新イベント日 = response[Value][events]{0}[started_at],
        最新イベントタイトル = response[Value][events]{0}[title]
    ]

7. SubdomainList の管理

複数のクエリで共通して使うサブドメインリストは、別クエリ(SubdomainList)として管理して参照する。

M言語
// SubdomainList クエリ
let
    Subdomains = {
        "subdomain-1",
        "subdomain-2",
        "subdomain-3"
        // ...
    },
    クリーン済み = List.Transform(Subdomains, each Text.Clean(Text.Trim(_)))
in
    クリーン済み

注意:Power BI サービス(Dataflow Gen1)での制限

Dataflow Gen1 では他のクエリを参照する「計算されたテーブル」は Premium ライセンスが必要。Power BI Pro では使えない。

解決策:SubdomainList をクエリ内に直接埋め込む。

8. ページング対応

APIの1回の取得件数上限(100件)を超える場合のページング処理。

M言語
// 1ページ分を取得する関数
GetPage = (start as number) as list =>
    Json.Document(Web.Contents(
        "https://api.example.com/events/",
        [
            Headers=[#"X-API-Key"= "YOUR_API_KEY"],
            Query=[
                subdomain = P1,
                count = "100",
                start = Number.ToText(start)
            ]
        ]
    ))[events],

// 1回目のAPIコールで総件数を確認
ソース1 = Json.Document(Web.Contents(...)),
総件数 = ソース1[results_available],

// 必要なページ数を計算
ページ数 = Number.RoundUp(総件数 / 100),

// 各ページのstartパラメーター値のリストを生成
Starts = List.Generate(
    () => 1,
    each _ <= (ページ数 - 1) * 100 + 1,
    each _ + 100
),

// 全ページのイベントを取得して1つのリストに結合
全イベント = List.Combine(List.Transform(Starts, GetPage)),

注意

Power BI サービスでは動的な start パラメーターがあるためページングと動的クエリ制限が相性が悪い。100件以内の場合はページングなしで設計し、超えた場合に警告を出す方が現実的。

M言語
// 100件超えた場合の警告
件数チェック = if List.Count(SubdomainList) > 100 then
    error "SubdomainList が100件を超えています(現在 " & Number.ToText(List.Count(SubdomainList)) & " 件)。ページング対応が必要です。"
else
    SubdomainList,
⚠️ connpass API v2 のページング不具合(2026年5月時点)

connpass API v2 では results_available および start パラメーターが正しく動作しない不具合が確認されています。

ドキュメントの定義では results_returned は「含まれる検索結果の件数」、results_available は「検索結果の総件数」とされています。

実際の動作(不具合):

  • count=100, start=1 の場合、results_available は総件数ではなく count と同じ 100 を返す
  • count=10, start=1 の場合も同様に results_available は 10 を返す
  • count=100, start=101 の場合、results_returned は次の100件ではなく 0 を返す
  • count=10, start=2 の場合、results_returned は全体の2件目から10件ではなく、count=10 で絞った結果の2件目から9件目となり 9 を返す

本質的な問題: count パラメーターが「取得件数」ではなく「検索結果のフィルター件数」として機能しており、start パラメーターがその絞られた結果に対して適用されているため、ページングが根本的に機能しない状態です。

API v1 との比較: v1 では count=1 の場合でも results_available に総件数(例:91)が返されており正常にページングが機能していました。v1・v2 ともにドキュメントの定義は同じであるため、v2 の明確な不具合と判断されます。

現実的な対応策: 各サブドメインの年間イベント数が100件以内であれば現状のコードで全件取得可能です。100件を超える場合は connpass の修正を待つか、別の取得方法を検討する必要があります。

9. 複数のAPIソースを結合する

connpass と Doorkeeper など異なるAPIのデータを同じ列名で結合する。

M言語
// connpass テーブルと Doorkeeper テーブルを結合
最終テーブル = Table.Combine({connpassテーブル, DoorkeeperTable})

ポイント

  • 列名を統一する(例:acceptedpublic_urlname
  • id など型が異なる場合は Text.From() でテキスト型に統一する

10. Dataflow について

Dataflow の役割

Power BI の Dataflow は ETL(Extract・Transform・Load)に相当する。

ETL内容Dataflow での役割
Extractデータを抽出外部APIからデータを取得
Transformデータを変換列の選択・名前変更・型変換など
Loadデータを読み込むPower BI Desktop にデータを提供

Dataflow Gen1 vs Gen2

Gen1Gen2
Power BI Pro で使える❌(Fabric Premium が必要)
計算されたテーブル❌(Premium必要)
外部API(匿名認証)❌ 制限あり未検証

結論

現時点では Power BI Desktop + Power BI サービス(pbix アップロード) が最も確実。

11. Power BI ダッシュボードのTips

日付の階層化を防ぐ

日付型の列が自動的に年・四半期・月・日に階層化される場合:

方法①:「ファイル」→「オプション」→「データの読み込み」→「自動日付/時刻」のチェックを外す

方法②:M言語で日付を YYYY-MM 形式のテキスト型に変換する

M言語
年月 = Text.From(Date.Year(...)) & "-" & Text.PadStart(Text.From(Date.Month(...)), 2, "0")

月の並び順が正しくない場合

テキスト型の 年月 列は文字列順で並ぶため、数値型の並べ替え列を追加する。

M言語
年月数値 = Date.Year(...) * 100 + Date.Month(...)

Power BI Desktop の「列ツール」→「列で並べ替え」→「年月数値」を選択。

DAX メジャーの例

DAX
// イベント数
イベント数 = COUNTROWS('テーブル名')

// 申込人数合計
申込人数合計 = SUM('テーブル名'[accepted])

// ユニーク支部数(同じ月に同じ支部が複数回開催しても1)
ユニーク支部数 = DISTINCTCOUNT('テーブル名'[subdomain])

12. connpass API v2 メモ

  • エンドポイント:https://connpass.com/api/v2/events/
  • 認証:X-API-Key ヘッダー
  • アクセス制限:1秒間に1リクエスト
  • 1回の最大取得件数:100件
  • 主なパラメーター:subdomaincountorderym
  • ⚠️ ページング不具合あり(2026年5月時点)results_available が総件数ではなく count と同じ値を返す。詳細はセクション8を参照。

13. Doorkeeper API メモ

  • エンドポイント:https://api.doorkeeper.jp/groups/{group}/events
  • 認証:Authorization: Bearer YOUR_TOKEN ヘッダー
  • 1回の取得件数:25件(ページネーション必要)
  • 主なパラメーター:sortsinceuntilpage

2022/04/24

[Power Query] OneDrive パーソナル (onederive.live.com) の Excel ブックに接続する方法

Power BI は OneDrive for Business (中身は SharePoint で、URL に my.sharepoint.com が含まれるもの) のフォルダへの接続を前提にしているようで、サービス名が同じでややこしいのですが、個人が使う OneDrive (URL に onedrive.live.com が含まれるもの)への接続は「簡単には」許していないように思えます。それはもう7年も前のことで、以下のような投稿をしています。このときは OneDrive パーソナル(と便宜上呼びます)への接続方法を見つけることができませんでした。(2015年当時)

Power Query から https 経由で SharePoint の Excel ブックを開く

Googleスプレッドシート(ベータ)に接続する

最近 Power BI ユーザーさんのブログで Google スプレッドシートがベータとはいえ、Power BI から取り込み可能になった、と知りました。[データを取得] から「Google」キーワードで検索すると、ベータですが Google スプレッドシートが表示されるようになりました。

Googleスレッドシートを表示している URL を使い、Google アカウントでサインインして Power BI に取り込めました。また、Power BI Service にアップロードして、資格情報(Google アカウントによるサインインと、プライバシーレベルを Organizational)の再設定を行うことで、[スケジュールされている更新] が完了することを確認しました。

コネクタのリファレンス Googleシート(ベータ)
https://docs.microsoft.com/ja-jp/power-query/connectors/googlesheets

OneDrive パーソナルにある Excel ブックに接続したい

Google スプレッドシート同様に [データを取得] で OneDrive といれても、それらしい、わかりやすいサービスは列挙されません。[OneDrive 内の Excelブック] があればベストなのですが、残念ながら、そういう用途は SharePoint という前提なのでしょう。

データ分析的なフィロソフィーとしては、手入力の Excel をデータソースとしたくないのはわかります。それをするなら Power Apps でデータを収集すべきで、生スプレッドシートをいじらせるのは「綺麗なデータを用意する」という観点からもあまりお勧めできないからでしょう。そう、目指すは以下のような世界。

Power Apps、Power Automate、および Power BI を SharePoint Online と統合する

しかし、そのデメリットを理解した上でも、Google スプレッドシートが OK ならば、簡単に利用できる OneDrive パーソナルに保存した Excel ブックの Power BI への取り込みは世界中の Excel ユーザーと Power BI ユーザーが感じているはずで、2022年にもなれば何らかの解決方法があるのではないか?と思い、少しだけしつこく探して、、、見つけました! 2017年の投稿で、たしかにこの Embed の機能が2016年前後に追加されたのを覚えています。(訂正: Excel Web App で 2011年には存在していました)

PowerBI support for OneDrive Personal as data source
https://community.powerbi.com/t5/Power-Query/PowerBI-support-for-OneDrive-Personal-as-data-source/td-p/129125

実際に試して、上述の Google スプレッドシートの手順同様に Power BI Servcie にアップロードして、[スケジュールされている更新] もうまくいきました。その手順をあらためて紹介します。

1) OneDrive の Excel ブックで右クリックメニューで [埋め込み] を選択します

2) この操作がはじめての場合は URL生成のメッセージが右ペインに表示されるので [生成] をクリックします。[生成] ボタンの下に書いてあるように、これによりサインインせずにこのファイルを埋め込んだブログやWebページで表示できるようになります。セキュリティに注意してください。

3) プレビューと iframe コードが表示されるので、この iframe のコード内の、resid= から &em=数 まで (width の前) をコピーします。

4) Power BI に Web ソースとして入力する URL を作ります。以下の文字列に、上記 3) でコピーした文字列を追加し、&app=Excel で閉じます。

https://onedrive.live.com/download? <文字列コピー> &app=Excel

上記の例だと以下のようになります。

https://onedrive.live.com/download?resid=6E1B8001F99D3597%2179199&authkey=AACEgb0W3bmJHXs&em=2&app=Excel

5) Power Query で Web からデータをインポートを選び、URLをコピーします。[基本] で構いません。[OK] をクリックします。


6) ワークシートにテーブル オブジェクトが含まれていればテーブル名が表示され、SharePoint Online (OneDrive for Business) と同じようなナビゲーションが表示されます。


7) この pbix を Power BI  Servcie にアップロードし、データセットの [データ ソースの資格情報] のプラバシーレベルで [Public] を指定。(これは Embed コードは「一般公開」の設定のため - このプライバシーレベルは仕事で使う場合は常に注意ですね)


8) 資格情報を設定することで [スケジュールされている更新] の設定が可能になる。


以上となります。

この設定は Excel の取得と変換の [Web から] でも利用できます。


足かけ7年のモヤモヤが解消されました。

ただし、繰り返しますが、セキュリティとしては匿名アクセス可能な一般公開の URL を生成しています。一般公開されているデータ、特に公になっても問題の無いデータに限られ、不安であれば、SharePoint Online/OneDrive for Business で組織アカウント サインインの元でのデータ活用に切り替えたほうが良いと思います。ベータの Google スプレッドシートが認証を通しているのも納得できます。Goolge スプレッドシートも有力な選択肢ですね。

既知かもしれませんが、参考になれば幸いです。

2017/07/08

[Power BI / Excel] 複数にまたがる Web ページからデータを取得する

Excel や Power BI Desktop のデータ取得の機能である Power Query (データの取得と変換) の話題です。

地震データを取得する

最近、また地震が多いのが気になりますよね。地震データは気象庁のホームページで随時公開されています。しかしながら、この公開データは、良い意味でデータ クレンジングのサンプルになり、違う意味では「集計」や「レポート作成」などの後工程をあまり考慮していないデータかもしれない、と愕然とします。
今回のお題とは離れた話題なのですが、ちょっとだけご紹介します。

http://www.jma.go.jp/jp/quake/quake_local_index.html

すべての数字が「全角」です。大きい、小さいの判断をするためには数値にしないと比較できないので、まずはこれを半角に変換する必要があります。同じく日付に使われている数字も全角です。良いか悪か別にして、Excel は全角数字をセルに入力すると、自動的に全角数字を半角の数字に変換してくれます。また、関数も用意されていて、ASC関数が全角のアルファベット、数字を半角に変えてくれます。(反対は JSC関数)

残念ながら Power Query エディターには全角→半角にしてくれる関数はありません。自分でカスタム関数を作って対応します。やることはものすごくベタで、全角のAは半角の A に、全角の1は半角の 1 に、というようにすべてを羅列するようなものです。

一方、Yahoo さんの地震情報は、数字は半角になっています。元ネタは気象庁のデータを使っていると思うので、後工程・再利用を考えて変換されているのでしょう。

Yahoo! JAPAN 天気・災害 地震情報
https://typhoon.yahoo.co.jp/weather/jp/earthquake/list/


全角・半角変換の手間を考えると Yahooさんのページからデータを取得したいところですが、地震の回数が多くなる、ちょっと長い期間でみてみたい、となると最初の1ページのデータだけでは足りなくなります。

Yahooさんのこの情報ぺージは、1ページから300ページまであり、かなり前の情報も Web ページから取得することが可能です。


300ページ目を開くと、今だと 2004年の2月後半からデータを取得することができます。1ページあたりに100件のデータをテーブル内で表示してくれます。
URL は以下です。

https://typhoon.yahoo.co.jp/weather/jp/earthquake/list/?sort=1&key=1&b=101

?から後ろがページを指定するパラメーターですが、一番最後のパラメーターの b=101 が、このページで表示する「開始番号」の扱いです。なので

1ページ目 b=1
2ページ目 b=101
3ページ目 b=201
4ページ目 b=301
・・・・・
10ページ目 b=901

といったルールになっていることがわかります。

複数の Web ページからデータを取得する

Power Query で最新100件(=1ページ目)を超える過去のデータを取得したい場合は、2ページ目、3ページ目、、、と複数のページ上のデータを取得する必要があります。

毎回、たとえば3ページ分のデータを取得して分析しよう、とした場合、すぐに思いつくのは URL 固定で 3 個のクエリを作成し、そのクエリを Append (追加) する方法でしょうか。


https://typhoon.yahoo.co.jp/weather/jp/earthquake/list/?sort=1&key=1&b=1
https://typhoon.yahoo.co.jp/weather/jp/earthquake/list/?sort=1&key=1&b=101
https://typhoon.yahoo.co.jp/weather/jp/earthquake/list/?sort=1&key=1&b=201

この3つのWebページのクエリ結果のテーブルを追加(Append)する方法です。

これでもいいんですが、URL固定、数固定にできない場合などを考慮すると、違う方法も覚えておくと便利です。それが「カスタム関数」を使う方法です。上記の URL であれば、b=1 や b=101 の部分の数値を変数、引数として扱い、結果をもらう、という方法です。

Excel / Power BI Desktop で「繰り返しの処理」のような方法でデータをとりたいな、と感じたときは、上述のように変数と関数を使うことを検討してみます。

データの読み込み処理を関数にする

Excel でも Power BI Desktop でも方法と手順は同じです。Excel の画面で手順を追ってみましょう。Excel 2016 のデータ タブにある「取得と変換」または「データの取得と変換」を使います。繰り返しになりますが、取得と変換はこれまでの外部データの取り込みに代わる新しい機能で Power Query と呼ばれていたものであり、Power BI Desktop のデータの取り込み・変換の機能(ETL機能)と同じものです。製品の更新タイミングによって若干の表現の差がありますが、ほぼ同じ位置や言い回しなので、脳内補完してください。あえて画面は少し前の Excel のスナップショットです。

データ タブの「(データの)取得と変換」と「新しいクエリ」や「データの取得」などのメニューから「Webから」を選びます。


データを取得する Web ページの URL を入れるダイアログが表示されます。
Yahoo!さんの地震情報ページの 1 行目からを表示する URL を入れて [OK] を押します。

https://typhoon.yahoo.co.jp/weather/jp/earthquake/list/?sort=1&key=1&b=1


今回は、Yahoo! さんの一般向けのページなので [匿名] のまま [接続] を押します。


指定したページにあるデータ情報からどのデータを取得するか指定する「ナビゲーターウィンドウ」が表示されます。テーブル形式でデータがまとまっている [Table 0] を選んで
[編集] を押します。[読み込み] を押すと、このまま取り込んでしまうので、いったん [編集] を押し、クエリ エディターにデータを読み込んで、変換・編集作業をします。


クエリ エディターが立ち上がります。取り込んだデータをもとにして、データの型が最初から列の属性として設定されています。気象庁のデータと違って、元データの数字が半角になっていること、マグニチュードの”M”が無いこと、などでマグニチュードは数値データとして、情報発表時刻は日付データとして認識されています。発生時刻が「ABC」の文字になっているのは 2017年7月8日 15時42分 ごろ という「ごろ」がデータに含まれているからです。最大震度が同じく「ABC」の文字になっているのは、半角数字の後に「弱」や「強」の文字がついているものがあったからです。


今回は発生時刻の「ごろ」や最大震度のお「強・弱」を扱う「データ クレンジング」処理は割愛しますが、このクエリ エディターでクレンジング処理をすると、クエリ エディターで「ステップ」として記録され、再利用することができます。

なお、マグニチュードでも文字列が入るデータがあるため、クレンジングの作業は必要です。

このクエリ エディタは基本 GUI で操作しますが、それらの操作手順は VBA のマクロ記録のように Power Query の M 言語で記録されます。M 言語で記述されたソースを編集するために詳細エディターを立ち上げます。[ホーム] タブの [クエリ] グループの [詳細エディター] をクリックしてください。詳細エディターを立ち上げるコマンドは他にも多く配置されています。


詳細エディターが立ち上がりました。詳細といっても、機能的には「簡易」です。
何度かお伝えしていますが、現段階で M 言語を深く習得し、詳細エディターでガリガリと操作を記述するような使い方をマイクロソフトは想定していないと思います。このエディターには本当に最低限の機能しかありません。そういうものだ、と思ってあまり深堀りしないほうがいいと感じています。

この簡易エディターで「引数」の指定をします。let の上に (page as number) => を挿入します。page という変数で、数値(number)型を引数として指定します、という意味です。


これで、page という変数(数値)が let 以下で使えるようになりました。これで 1 から始まる、101 から始まる、201 から始まる、という指定が可能になります。
URL の一番最後の値として置き換えたいのですが、注意点は page は「数値」であり、URL は「文字」であること。よって、数値を文字に変換してあげます。

Number.ToText(page)

この関数で変数 page の中の数値データが、文字のデータに代わります。URL の最後の b=1 の部分を以下のように書き換えます。

[変更前] /?sort=1&key=1&b=1")),
[変更後] /?sort=1&key=1&b="& Number.ToText(page))),


ウィンドウの右下の [完了] を押すと、エラーがなければ、パラメーターの入力を促す画面が表示されます。


画面左のナビゲーションの [クエリ] の上にある [>] 展開マークを押すと、このクエリ エディターで扱えるクエリが表示されます。(Excel の場合は、ブックに含まれるクエリであり、Power BI Desktop の場合は pbix ファイルに含まれるクエリを含みます)


引数(パラメーター)を準備する

ナビゲーションの Table 0 の前に [fx] アイコンからわかるように、この引数を設定する操作によって、Tablel 0 クエリは関数に代わりました。page パラメータに 1 を入れて [呼び出し] を押すと、1 からのデータの表を関数の「クエリの結果として」表示します。101 をいれると、101 からのデータの結果を表示してくれます。このクエリの結果はナビゲーションから削除することができます。削除するまでの操作手順のアニメーション GIF が以下です。


パラメータに、1、101、と入力し関数 Table 0 に渡し、その結果を表にすることができました。この 1、101、、、を手入力ではなくしたいのです。これが Power Query の繰り返しの処理です。

たとえば、常に10ページ分がほしいのであれば、1、101、201、、、901 までパラメータとして渡します。そのため、そのパラメータをリストとして用意します。

手順は、10個の連続した数値を用意して、1から901を作ります。いろいろなやり方があると思いますが、0 から 9 までの連続した数値から以下のように作ってみます。

0 -> 0*100+1 = 1
1 -> 1*100+1 = 101
2 -> 2*100+1 = 201
・・・
8 -> 8*100+1 = 801
9 -> 9*100+1 = 901

クエリ エディターで 0 から 9 までの連続した数値を作る方法は、数式で ={0..9} を使います。この数式の結果は {0,1,2,3,4,5,6,7,8,9} の連続した数値のリストを作成します。

クエリ エディターで、このリストをテーブルに変換して、新しい列を追加して、0*100+1 の数式を使って 1 から 901 までの数字を作ります。そこまでは以下のアニメーションGIFです。


パラメーターを使って関数を利用する

この操作で関数へ渡すパラメーターが用意できたので、このパラメーター列の横に新しく列を追加し、そこに作成した関数 Table 0 を指定して、1列目にある数値をパラメーターとして指定します。
関数 Table 0 はパラメーターで指定されたデータから始まる「表」をクエリの結果として返してくれます。個々の [Table] のリンクをクリックすると、1ページ100件分のデータのみですが、列名の横にある [展開] ボタンを押すと、すべての結果の表(テーブル)を結合して一気にデータ 10ページ 1000件を作成します。


0~9のパラメーターの最大値の 9 をさらにパラメーター化したり、多めの引数を用意して、取り込んだ後でエラー行の削除を行う、クレンジングをする、という方法を組み合わせることができます。

まとめ

今回は複数の Web ページのデータをまとめる、というお題でしたが、ポイントは「関数化」と「パラメーターの準備」による「繰り返し処理」と「クエリ結果の追加統合」の処理だと言えます。この方法を知っていると、Web ページだけではなく、他のところでも応用が利くテクニックです。

以上、少しでも参考になれば幸いです。

2017/05/23

[Excel BI] ピボット テーブルとメジャー

先日、Power BI 勉強会で「使える!クイック メジャー」というお題でお時間をいただき、メジャーの紹介をいたしました。勉強会にご参加いただいたみなさま、ありがとうございました。また、このブログで「Excel ユーザーにとってのメジャーとは?」というタイトルの記事を過去に投稿しています。参照数などから、この話題は興味のある人が多いようで、エクセル ユーザーも「メジャー」や Power BI といったキーワードが気になっているようですね。

Office 製品は、機能はもう十分です、追加は要りません、と言われた時期もありましたが、現在、Excel はちょっとした改善ではなく、ガラリと使い勝手が変わる機能強化が押し寄せてきているように感じます。

そのような機能強化の中で「これは・・・」と私も驚いた機能をご紹介します。先日の勉強会では、メジャーを理解するにはいったんExcelを(セルを基本とするワークシートを)忘れたほうがいいかもしれない、という紹介をしたのですが、実は、Excel のピボット テーブルで「メジャー」を使う、というお話です。

データ モデル利用のデメリット

VLOOKUP関数などを使わず、いわゆる「表引き」を実現する「リレーションシップ」の機能は、Excel 2013から標準機能として搭載されました。

[ブログ] テーブルのすすめ ピボット テーブルとリレーションシップ
https://road2cloudoffice.blogspot.jp/2014/11/blog-post_7.html

[Office Support] Excel のテーブル間にリレーションシップを作成する
https://support.office.com/ja-jp/article/fe1b6be7-1d85-4add-a629-8a3848820be3

このリレーションシップ機能は、分析するデータを「データ モデル」に格納して、ピボット テーブルを作成しますが、当初、データ モデルにより使えなくなる機能がいくつかありました。その代表が「日付のグループ化ができない」と「集計フィールドが使えない」でした。
データ モデル利用によりグレイアウトされた集計フィールド
日付のグループ化などは機能拡張で後日対応しましたが、集計フィールドは日付のグループ化のような後日対応はありませんでした。集計フィールド同等の機能は、Power Pivot のメジャーや計算列で対応が可能だったからだと思います。

しかし、Power Pivot はすべてのエディションで利用可能ではありません。一部古いバージョン用を除いて、ダウンロードセンターから Power Pivot アドインのダウンロードもできなくなりました。
例えば、Office 365 Business の Excel で Power Pivot を利用することはできません。Office 365 ProPlus と Excel 2016 の Professional Plus のエディションに限られ、このエディションにはアドインとして最初から同梱されてます。つまり、所有している Excel のアドインに同梱されていなければ利用できない、ということです。

Excel 2016 のデータ モデルのピボット テーブル

では、Power Pivot を利用できないエディションでメジャーの作成ができないのか、ということです。
Excel でメジャーの作成を検索すると Power Pivot を使う情報がほとんどですが、Excel 2016 以降、Power Pivot アドインを含んでいない Office 365 Business 含め、いずれのエディションでも、ピボット テーブルでデータ モデルを利用すると、Power Pivot なしでも「メジャー」の作成が可能になっています。

以下のようなシンプルな列で構成されるテーブルを使って検証してみます。


このような表やテーブルからピボット テーブルを作成する時、[ピボットテーブルの作成] ダイアログ ウィンドウの [このデータをデータ モデルに追加する] のチェックを入れて、データ モデルにテーブルを追加します。ピボットテーブルは「データ モデル」に追加され、そこから作成されます。


複数テーブルの分析をしなくても、このチェックをオンにしてデータ モデルからピボットテーブルを作ることができます。
ピポット テーブル作成後、フィールド リスト ウィンドウに表示されるテーブル(サンプルでは [Table01])上で右クリックをすると、[メジャーの追加] を含むコンテキストメニューが表示されます。


[メジャーの追加] をクリックすると、メジャー のダイアログ ウィンドウが表示されます。ここで DAX を使ってメジャーの数式を作成・編集することが可能です。


集計フィールドの代替でメジャーを利用

Excel の集計フィールドの説明や解説では、テーブルの列の数値から消費税を計算したり、売上から原価を引いて粗利を計算したり、といった例が紹介されます。
データ モデルを使ったピボット テーブル レポートでは、集計フィールドのかわりにメジャーを使うことができますが、数式に相当する表記方法はメジャーの表記方法(=DAX数式)を使う必要があります。

たとえば、数値A列の数値に 0.08 を乗算する消費税の計算のようなものだと、集計フィールドを使うと以下のような数式になります。
集計フィールドによる消費税計算
メジャーでそのまま同じ式を使うと以下のようになります。

これは本物のメジャーなんですね。ですから、ワークシート上の構造化参照式のような数式はエラーになるんですね。='table01'[数値A]*0.08 という数式を入れた時のエラーは以下です。

この数式は無効または不完全です: 'Calculation error in measure 'table01'[mj2]: A single value for column '数値A' in table 'table01' cannot be determined. This can happen when a measure formula refers to a column that contains many values without specifying an aggregation such as min, max, count, or sum to get a single result.'。

'table01' の数値Aは単一の値として定義されていない(列で複数の行を持っている)から計算できません。min や max、count や sum などの集計関数を使って、単一の結果を取得して、それを使いなさい、というような内容です。

ピボット テーブル レポートの基本的な「動き」は、レポートの行ラベルまたは列ラベルとして設定された要素でグループ化をして集計するものです。よくあるのは行は製品区分、列は年度、のようなマトリクス表です。また、集計対象の要素が数値データで構成されていれば「合計」を計算し、数値以外を含んでいるデータであれば「個数」を集計します。これがいわゆる「暗黙のメジャー」というわけです。


ピボット テーブル レポートで計算が合わない原因

暗黙といわれるせいか、あまり意識されていないかもしれませんが、ピボット テーブルにおける数値列の計算は、まずは合計を計算します。たとえそれが列に対するパーセンテージを計算するものであっても、行ラベルのグループで「合計」をしてから、列合計を分母として、行ラベル合計を分子にして割合を計算、という順序です。(それゆえ実務では、サンプルとして使っている消費税の計算は、メジャーではなく、元のテーブルに列を追加して各行にて端数処理を行い合計すべきか、合計してから消費税を計算し、端数処理を行うかは注意しなければなりません)

ちょっと話がそれますが、ピボット テーブル機能が今ひとつ一般的にならず、人気がない、もしくは難しいといって避ける人が多いのは、個人的に上述の「まず、行・列のラベルのグループで合計しているんだよ」という暗黙の計算を意識していないせいではないかと思います。

ピボットあるあるの話で、かつ、間違った解説をしている記事がネット上にいくつかあるのですが、集計フィールドの解説で「受注金額は、単価*数量 で求められるので、ピボット テーブル レポートで 単価*数量 の数式の集計フィールドを追加すればいいんですよ。」と紹介しているものがあるのですが、これは完全な誤情報です。それ、本当に間違いです。Google での検索で結構上位にくるものでも、このような説明をしている記事を見ることができます。本当に注意してください。以下その解説です。

単純に以下を考えてみましょう。佐藤さんは、5月に、単価 100円のものを1個、単価1000円のものを1個売りました。佐藤さんの5月の売上はいくらでしょう?

100円*1個で100円と、1000円*1個で1000円、合計は 1,100円ですよね。

これをピボット テーブルの集計フィールドで、受注は 単価*数量 だからといって、受注の集計フィールドを作って計算すると、2,200円になります。2件しかありませんからすぐに間違いに気が付きますが、もし、件数が多い場合などすぐには気が付かないでしょう。

この計算は、まず、佐藤さんというレコード(行)を集めます。その次に、単価の列で合計します。単価は 100 と1000 が1つづつあるので 1100 です。次に数量の列で合計をします。1が2つあるので 2 になります。最後に集計フィールドで指定されている数式による演算を行います。1100 * 2 なので結果は 2200 です。

つまり、集計フィールドの例としてあげている数式の、受注金額=単価*数量 は、

受注金額 = SUM(テーブル[単価]) * SUM(テーブル[数量])

を計算しています。

これは、利益のような加算、減算であれば問題ありません。利益 = 売上 - 原価 の数式は、1行ごとに計算したものを最後に合計しても、総売上から総原価を引いても同じです。

ピボット テーブル レポートの計算結果が間違っていることがあるので使いたくない、という話を聞きます。「元データが汚いよね」というのも現実ですが、この行・列ラベルでの小計が優先されることを意識していない場合もあるかもしれません。

ここでメジャーに話が戻るのですが、その意味で、ピボット テーブルのメジャーの数式では、=[単価] * [数量] という数式を記入すると上述のエラーになります。明確に以下のように数式を書かなければなりません。そして、その段階で数式がおかしいことに気が付いてほしいわけです。

= SUM('テーブル'[単価]) * SUM('テーブル'[数量])

なお、受注金額の合計を求めたいのであれば、元データに単価*数量の列を追加するか、Power Query/取得と変換 のクエリエディターで計算列を追加し、あらかじめデータ モデルに計算データを取り込むことになります。Power BI Desktop の場合はデータを取り込んだ後で、計算列の追加を使ってもいいでしょう。

2017/04/12

[Power BI Desktop] 期待のクイック メジャーが利用可能になりました

ついに待望の機能「クイック メジャー」が追加されました。

2017年4月現在、クイック メジャー (Quick Measures) は「簡易分析」という日本語訳が当てられていますが、近い将来、すべての訳は クイック メジャー に変更されそうです。

クイック メジャーは、Excel ユーザーにとってみればピボットテーブルの「計算の種類」です。Power BI Desktop ユーザーにとっては「自動DAX式生成機能」といえるでしょう。複雑な DAX 式を手で作るのではなく、ダイアログで条件などを指定することで「自動生成」してくれる機能です。

ピボットテーブル レポートを使って分析をしている Excel ユーザーにとっては、DAX 式学習のコスト削減になることは間違いありません。
ピボットテーブル レポートの「計算の種類」のリストから選択し、ダイアログボックスで条件設定するだけでできるのと同じ計算を、Power BI Desktop でやるには?という質問に、「DAX でイチから書くしかないですね」といつも言われ、その DAX 式が結構複雑になることから、Power BI Desktop の利用・移行を躊躇している人も多かったと思います。

たとえば以下のピボットテーブル レポートでは、計算の種類の「基準値との差分の比率」 - 「基準アイテム (前の月)」を使って、前月との差分を計算しています。


繰り返しになりますが、この列の計算結果は、ピボットテーブルの「計算の種類」からダイアログの設定のみで算出可能です。数式を弄ることは一切ありません。

これと同じ計算結果を Power BI Destop のレポートでは、テーブルのビジュアルで、クイック メジャーを使うことで、DAX を直接記述する必要はなくなりました。


このメジャーの DAX 式は以下になります。この DAX 式は、日本語のエラーメッセ―ジを含めて、すべて自動的に作成されたものです。


前月との差分の比率(MoM% = Month Over Month %) を計算するには、上記のような DAX 式を書かなければならないわけですが、それをクイック メジャーのダイアログで条件設定することで可能になるのは、すごく利用のハードルを下げてくれました。

クイック メジャーはまだ「プレビュー」機能です。バージョン 2.45.4704.442 64-bit (2017年4月) 版から利用可能ですが、 オプションのプレビュー機能のチェックをオンにする必要があるので注意してください。


とりいそぎ現時点でマイクロソフトから提供されている クイック メジャー の情報のページは以下になります。ぜひ参考にしてください。

Use Quick measures to easily perform common and powerful calculations (Preview)
https://powerbi.microsoft.com/ja-jp/documentation/powerbi-desktop-quick-measures/

2017/03/03

[Power Query] 大量のデータベースから、セルに指定した条件でデータを取り出したい

Power Query/Excel の勉強会でお付き合いのある方から以下のような質問をいただきました。

PowerQueryの機能には、MSクエリで可能だったセルの値を使ったパラメータークエリのような機能はないのでしょうか?大量のデータベースから、セルに指定した条件でデータが取り出せて便利だったのですが。
昨年の春頃に、Power BI Desktop および Excel Power Query - 取得と変換 で、「パラメーター」の機能が実装されました。このパラメーターを使えば、設定した値(文字や数値、日付など)の中から選択して、データ抽出の条件として使えることはわかっていました。

Deep Dive into Query Parameters and Power BI Templates
https://powerbi.microsoft.com/ja-jp/blog/deep-dive-into-query-parameters-and-power-bi-templates/

期待している Excel 利用のシナリオは、取り込みたい条件を Excel のセルで指定、たとえば、入力規則で設定したドロップダウン リストから選択などで行い、その指定した条件で元のテーブルからレコードを絞り込んでワークシートに展開する、というような使い方だと思います。

パラメーターを使って絞り込み条件を変更する

Power BI Desktop であれば、新機能の「パラメーター」を使い、 A, B, C, D などのリストで作ったパラメーターで、リストから選んだ条件で絞り込みを行い、データ モデルに結果を Load します。

等しい条件にパラメーターを指定する
この条件を変えたければ、Power BI Desktop の [ホーム] タブ - [外部データ] の [クエリを編集] から [パラメーターを編集] を選び、表示されるパラメーターの入力 ダイアログボックスで、条件(パラメーター)を変更できます。[変更の適用] を行えば、変更した条件で元のデータセットからデータを読み込み、データ モデルを更新します。
[クエリを編集] - [パラメーターの編集] を選択
[パラメーターの編集] で表示される パラメーターの入力 ダイアログ
パラメーター変更後に表示される警告
Power BI Desktop の場合、このようにクエリ エディター ウィンドウを再度開くことなくパラメーターの変更が可能です。この使い勝手は想定通りだと思います。

ところが、Excel Power Query - 取得と変換 では、同様の行の絞り込み条件とパラメーター設定をしても、Excel のリボンから [パラメーターの編集] に相当するコマンドを見つけることができず、同じ操作手順を得ることができませんでした。(使用更新チャンネルは 最新機能更新チャンネル バージョン 1611 ビルド 7571.2109)

もちろん、クエリ エディターを開けば、パラメーターを変更でき、その変更したクエリを適用・保存することで、結果のテーブルの更新ができますが、想定しているシナリオの手順ではないと思います。

条件を「引数」として渡す、それは関数化

では、リボンに [パラメーターの編集] コマンドがない間はどうすればいいか。

クエリに引数で「条件として使う値」を渡せば解決できます。事実、パラメーター管理 (Query Parameters) 実装の前は、引数と関数の組み合わせで対応していたんですよね。

サンプルとして、条件の設定は「入力規則」を設定したセルにしました。といっても、見出しとデータ部分が1行で構成したテーブルとします。

大量データのテーブルから、絞り込み条件を付けたクエリを作成します。この場合の条件は、テーブルの列のフィルター オプションで、まずは明示的に A や B を指定してます。
次に詳細エディターを使って、let の直前に、引数 param1 を使う宣言をします。

(param1 as text) =>
let
 ・・・・・
in

そして、この引数名 param1 を使って、先ほど明示的に指定したステップの条件の値(入力規則で指定し、条件として選択している A や B や C)を入れ替えます。
以下の例だと、ステップは「フィルターされた行 =」であり、絞り込み条件の列として使用している [区分A] に定数として指定されている "A" や "B" などを param1 に置換えます。



この追加・修正を行い、詳細エディターを閉じると以下のダイアログが表示されます。


クエリ ウィンドウ(昔はナビゲーター ウィンドウと呼んでいました)の [>] をクリックしてウィンドウを展開すると、データを絞り込むために作成したクエリーの種類は「関数」になっていることがわかります。(Table01 クエリの前のアイコンが [fx] になっています)


すでにこのクエリは「関数」になっています。この関数クエリに引数として条件の値を渡せばいいのです。

このクエリ ウィンドウは [閉じて読み込む] ことによって、ワークシートには何もロードされない [接続専用] のクエリがブックに保存されます。(パラメーターの入力ボックスに絞り込み条件を指定すれば、その条件で絞り込んだテーブルがワークシートにロードされます)

この関数クエリを使うクエリの書き方は色々な方法がありますが、条件指定の1行データ入力規則のテーブル(列名は[条件]、データは1行)から作るクエリ作成手順を紹介したいと思います。

(1) 条件指定の1行データテーブル内にアクティブカーソルを移動して、[取得と変換] の [テーブルから] を選んで、アクティブカーソルがあるテーブルからクエリの作成を行うクエリ エディターを起動します。
クエリ ウィンドウを展開すると、直前に作成した関数クエリと、いま編集しているクエリの2つが表示されます。(以下のサンプルでは Table01 と pTable1)


(2) [列の追加]タブの [全般] - [カスタム関数の呼び出し] をクリックします。これでカスタム関数を使った列の追加をするためのダイアログ ウィンドウが表示されます。


関数クエリのドロップダウン リストで直前に作成した関数クエリを選択し、引数の param1 には、[条件](これは、1行データテーブルの「列名」として指定した文字です)を指定して、[OK] をクリックします。


関数クエリを使った新しい列 [Table01] が追加されました。


(3) 新しく追加された Table01 の結果が欲しいので、[条件] 列を削除し、[Table01] の「Table」を展開ボタンを使って展開します。元の列名は使用しないのでプレフィックスのチェックを外し、[OK] をクリックします。


この例では列の順序が元のテーブルとは変わってしまいましたが、[区分A] の値で絞り込まれたテーブルのプレビューが表示されます。


 [閉じて読み込む] でクエリの結果をワークシートにロードします。


(4) 条件を変えて、クエリを実行して、テーブルの更新をします。
まず、条件設定のテーブルで他の値を選びます。サンプルでは "D" を選びました。


(5) 次に関数クエリの結果でワークシートにロードされたテーブル上で、右クリックメニューから [更新] をクリックすると、テーブルが指定した条件で絞り込まれたものに更新されます。


いかがでしょう。たぶん、このようなシナリオを想定しているのではないでしょうか。

まとめ

パラメーター(Query Parameters)を使って、ダイナミックに変数、条件を変え、クエリ―結果も変えることができます。
クエリを関数にして、関数の引数を動的に変更することで、パラメーターの利用と同じことが可能です。

ただ、もしメモリー上に余裕があれば、データセットに対してフィルターをかける「取得と変換」や「Power Query」の処理は、データ分析用のデータ準備として最低限にしておいていいと思います。
ある条件で絞り込んだ、生の「テーブル(表)」がワークシート上で必要、というケースは、データ件数が多くなればなるほど非現実的ですよね。(印刷のため・・・は知っています。その昔、連続帳票で何千件のレコードを印刷、、、を経験したことがありますが(笑)。)

どうしても Excel の発想から、テーブルや表に対してオートフィルターで条件を指定して絞り込みを行い、そこから何かしらの処理を行う、という手順を考えてしまいます。
もちろんその手順に問題はないのですが、フィルターをかけて計算をする、という「一括りの処理」は、分析フェーズの DAX の FILTER関数などを使い、数式内で行うのが柔軟な利用方法だと感じています。

最大100万行のワークシートをデータセットの前提としていた旧来の Excel 利用の考え方とは別に、これからは、SSAS(SQL Server Analysis Services) のインメモリ表形式モデルの「データ モデル」を Excel に実装した Power BI 系のモダン Excel では、データ モデルにできるだけ「必要なデータ」を「必要な形に変換」して「ロード」する(Power Query - 取得と変換 - ETL機能としての処理)のが基本だと感じています。そのため SQL Server 2012 以降の xVelocity の最適化の圧縮技術を惜しみなく適用しているような気がしています。

(独り言・・・でも、そのモダンな使い方をすると Power BI Desktop をすぐに使えるよう(それで十分)になるんですよね・・・)
Powered by Blogger.

自己紹介

自分の写真
1989年新卒で日本IBMに入社しダウンサイジング担当としてホストコンピュータと繋げるオフコン、UNIX、PCサーバーのプロジェクトを担当。1997年 MSKK(現日本マイクロソフト)入社、NT4出荷に伴い企業向けサポート部門のビジネスマネージャーとして Excel 使いとなり、2002年 にMSMVPなどをサポートするユーザーコミュ二ティ部門を設立、部門をリード。2006年にMSKK退職後、企業向けのITトレーニング会社・団体に携わり、2014年頃よりPowerBI勉強会主催メンバーの一人として参画、そのコミュニティ活動で MSMVP for Data Platform PowerBI 2017受賞。https://mvp.microsoft.com/ja-jp/PublicProfile/5002635 同年にMVP Awardを返上し、アマゾン ウェブ サービス ジャパンに入社、コミュニティプログラム担当として現在に至る。