はじめに
先日YouTubeで下記の動画を拝見しました。
SharePoint の HTTP 要求フローの送信アクションを実行することで、大規模なデータセット(リスト)に対応させている例です。
有識者の方からは、SharePointはデータベースではないと言われておりますので、
限られたシーンの際にご利用ください。
記載した動画を解説すると
- Power Appsのデータ行の制限を2000(最大値)にする
- SharePoint の HTTP 要求フローの送信アクションで、「次ページへのリンク」と「取得したリストの行データ」をJSONで取得する
- Power Appsで、ParseJSON 関数を使い、値を表示する
といった方法で成り立っています。
日本地図アプリを作成して、効果を体験してみる
今回は、郵便番号データをもとにSharePointリストとして作成し、アプリケーションを作ります。
124,675行の大規模データです。
※2024年 1月 31日更新分
あくまで実験目的です。
■ 機能
- 郵便番号データを、SharePoint の HTTP 要求フローの送信アクションで取得する
- 郵便番号から、HeartRails Geo APIを利用し、緯度・経度を取得する
- Power Appsの対話型マップ コントロールを使い、地図に郵便番号の場所を表示する
- 都道府県を選択するコンボボックスを設けて、住所をフィルターする
対話型マップ コントロールは、使用できるライセンスが制限されます。
詳しくは下記をご参照ください。
SharePoint リスト
かなり雑に作ってしまいました。
リストの中身は下記のようになっています。
列名 | 内部名 | データ型 | インデックス |
---|---|---|---|
郵便番号 | Title | 1 行テキスト | |
都道府県カナ | field_3 | 1 行テキスト | |
市区町村カナ | field_4 | 1 行テキスト | |
町名番地カナ | field_5 | 1 行テキスト | |
都道府県 | field_6 | 1 行テキスト | インデックス付きの列 |
市区町村 | field_7 | 1 行テキスト | |
町名番地 | field_8 | 1 行テキスト |
内部名が滅茶苦茶なのは、インポートをミスったからです・・・。
またデータ型もテキトーです(苦笑
後述しますが、SharePoint の HTTP 要求フローの送信アクションで、行を取得することに当たり、フィルターを実装するためにインデックス付きの列に都道府県
の列を設定しています。
大規模データセットの場合、インデックスが付与されていないと、正しく機能しません。
Power Apps
モダン コントロールを、多く採用し、下記のようなレイアウトにしています。
このアプリケーションで、フォーム
は、データを表示のみ
実施する機能となっています。
SharePointリストを更新するためには、更新を実施するための SharePoint の HTTP 要求フローの送信アクション が必要になります。
実装している関数
UpdateContext({ListData:ParseJSON(GetSPListsItems.Run("Postcode","$top=20").response)});
ClearCollect(colM,Table(ListData.results));
-
ListData
は、Power Automateを経由して取得したSharePointのデータをParseJSON関数を経て、格納しています - テーブルのデータは、ListDataの
results
If(CountRows(ComboboxCanvas1.SelectedItems) = 1,
UpdateContext({ListData:ParseJSON(GetSPListsItems.Run("Postcode","$filter=field_6 eq '" & ComboboxCanvas1.Selected.Value & "'&$top=20").response)});,
UpdateContext({ListData:ParseJSON(GetSPListsItems.Run("Postcode","$top=20").response)});
);
ClearCollect(colM,Table(ListData.results));
- 都道府県を選択するコンボボックスに応じて、Power Automateに渡す値を変えています
- コンボボックスに値がある場合、フィルター条件を文字列に追加し、上位20件の値を取得
- コンボボックスに値がない場合、上位20件の値を取得
- その他の挙動は、
OnVisible
と同様
UpdateContext({ListUrl:Last(Split(Text(ListData.__next),"?")).Value});
UpdateContext({ListData:ParseJSON(GetSPListsItems.Run("Postcode",ListUrl).response)});
ClearCollect(colM,Table(ListData.results));
- JSONから
__next
を取得します。ここから、ページングされたことによる、次の検索クエリの結果を取得することができます( 例: 前回の検索結果からみて、次の上位20件のレコードの検索結果) -
__next
を?
で分割した最後の値を、検索用URLとしてPower Automateに渡します - 戻り値を再度コレクションに新しく格納します(ClearCollect関数を使って、毎回リフレッシュしています)
UpdateContext({GeoInfo:GetGeoInfomation.Run(ThisItem.Value.Title)});
- ギャラリーの郵便番号データが選択されたときに、選択された郵便番号をもとに、HeartRails Geo APIを利用し、緯度・経度を取得します
Power Automate
Power Automateの内容は、かなりエッセンシャルな内容になります。
SharePointから行データを取得 - GetSPListsItems
- メソッドは
GET
- URI
_api/web/lists/GetByTitle('{-リスト名-}')/Items?{-検索条件-}
- リスト名は
ListTitle
として、検索条件はListURL
として、Power Appsから値を受け取ります
JSON ライトを使用した場合、検索クエリで利用する__next
の値が取得できません。
ここで大切になることは、フィルターを実装するにあたり、
評価の対象となる列がインデックス付き列に設定されていないと、検索クエリが機能しません。
SharePoint側の設定が必要になるので、ご注意ください。
地理的な情報を取得 - GetGeoInfomation - HeartRails Geo API
- Power Appsから郵便番号を
ハイフンなし半角数字7桁
で受け取ります - メソッドは
GET
- URI
http://geoapi.heartrails.com/api/json?method=getStations&postal={-郵便番号ハイフンなし半角数字7桁-}
郵便番号が060-0941
の場合、APIの戻り値は下記のようになります。
{
"response": {
"station": [
{
"name": "西線14条",
"kana": "にっせんじゅうよじょう",
"line": "札幌市電",
"y": 43.040775,
"x": 141.336429,
"postal": "0640914",
"prev": "西線11条",
"next": "西線16条",
"prefecture": "北海道",
"distance": 1273.3884260023942
}
]
}
}
緯度や経度もあって嬉しいですね!
配列の最初の値のみ取得する形で、Power Automateを作りました。
body('HTTP')?['response']?['station'][0]
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"kana": {
"type": "string"
},
"line": {
"type": "string"
},
"y": {
"type": "number"
},
"x": {
"type": "number"
},
"postal": {
"type": "string"
},
"prev": {
"type": "string"
},
"next": {
"type": "string"
},
"prefecture": {
"type": "string"
},
"distance": {
"type": "number"
}
}
}
かなりヌルヌルサクサク!
非常にレスポンスが良く、大規模データセットでも機能します!
複数の行を取得する
アクションが、すでにPower Automateで存在しますが、速度の違いも0.3秒と数秒と段違いです。
やっていることは全くローコードではないと思いますが、
Power Apps / Power Automate活用を更に尖らせる意味で良いですね!
大規模データセットを採用する場合、Dataverse
が望ましいです。用法用量を考えて、活用してください。
追加!対話型マップ コントロール
さくっと、対話型マップ コントロールを含めた赤枠の箇所を解説します。
具体的な要素はこちら
- テンプレートで配置されている
MainContainer
- conHeader - 水平コンテナー(ヘッダー用)
- icoHeader - 地点のアイコン
- lblHeader - Map!!という文字
- conBody - 水平コンテナー(ボディ用)
- フォームコントロール
- マップコントロール
- conHeader - 水平コンテナー(ヘッダー用)
ヘッダー部分
アプリ内で色を統一することが好きなので、conHeader
のFill
を下記の通り設定しました。
App.Theme.Colors.Darker10
このように設定することで、Power Appsのテーマに合わせた色の統一ができます。
私のお気に入りはTeams
です
ボディ部分
conBody(Container)
には、上下左右にパディング
を10
設けました。
Formコントロール
今回使用しているのは、モダンコントロールのFormです。
Width(幅)
はParent.Width / 2.5
に設定しています。
ParseJSON 関数
で評価した値を、どう表示するか解説すると、
フォームのフィールド
から三点リーダー
を選択し、カスタム カード
を、表示したい要素分、追加します。
DataCard
が追加されるので、この要素のDataField
プロパティに、Formのうち割り当てる列
を設定します。
ThisItem.Value.field_6
あとは必要に応じて、テキストラベル
など、コントロールを追加しましょう。
テキストラベル
に表示する値を反映するには、下記を設定することで、
データソースから値を反映することができます。
Parent.DataField
対話型マップ コントロール
あまり工夫はできていません(苦笑
そもそもが優秀な機能なので、下記の部分のみ設定しております。
項目 | 値 | 解説 |
---|---|---|
CurrentLocation | true | 現在地のオンオフ ピコピコするマークとして使用 |
CurrentLocationLatitude | GeoInfo.y | 現在地の緯度を変数で決定、APIの戻り値を使用 |
CurrentLocationLongitude | GeoInfo.x | 現在地の経度を変数で決定、APIの戻り値を使用 |
DefaultLatitude | GeoInfo.y | デフォルト(マップの中心地)の緯度を変数で決定、APIの戻り値を使用 |
DefaultLongitude | GeoInfo.x | デフォルト(マップの中心地)の経度を変数で決定、APIの戻り値を使用 |
DefaultZoomLevel | 8 | 拡大、縮小を設定 |
MapStyle | 'Map.MapStyle'.SatelliteRoadLabels |
私の地元だとこんな感じで映ります!