はじめに
Power Apps界のロックスター、Reza Dorraniが 「Graph APIを使ったExcel出力方法」 をいくつか紹介しています。
海外のMVPも良く紹介されているテーマですが、Reza
のYouTubeはとりわけ丁寧です。
Excel
へのエクスポートと言えば、Office Scripts
やPower Automate
が選択肢として挙げられます。
しかし、Reza Dorraniが紹介している手段は、OneDrive for Business
を出力先に設定し、Office 365 Users コネクタを介して、Grarh APIを使う方法であり、処理速度が非常に速く、魅力的な機能です。
本当に素晴らしい機能です。内容の紹介と同時に、実装するうえで課題に遭遇したため、その内容を紹介したいと思います。
概要
Reza Dorraniが紹介している手段は、SharePoint Lists
の項目を取得し、OneDrive for Businessに結果を格納しています。
- Power AppsからSharePoint Listsの
フィルター クエリ
を文字列で渡す -
OneDrive for Business コネクタで、空のファイルを作成する
- 拡張子は
.xlsx
に設定、ファイル コンテンツは空白文字列
- 拡張子は
- Excel Online (Business) コネクタをもちいて、(2)で作成したExcelファイルに、テーブルを作成する
- Graph APIで挿入する配列を
選択
アクションで作成する -
Office 365 Users コネクタで
Excel
に値を挿入
上記をベースに、Power Apps
でJSON 関数
を用いて、配列を直接Power Automate
に渡し、Excel出力する方法で進めてみます。
簡易版で作成した例
まずは下記のようなPower Apps
の画面を作成します。
ChatGPT
で生成した200件のデータが表示されています。こちらのテーブルに記載のある値を、Excelに出力するというシナリオで進めてみます。
表データはHTML 文字列
をConcat 関数で組み合わせて表現しています。
With(
{
commonPadding: "padding: 12px 15px; text-align: left; border-bottom: 1px solid #e9ecef;",
headerStyle: "color: #495057; font-weight: 600; text-transform: uppercase; font-size: 0.85rem; position: sticky; top: 0;"
},
$"
<table style='width: 100%; border-collapse: collapse; box-shadow: 0 1px 3px rgba(0,0,0,0.2); border-radius: 8px; overflow: hidden;'>
<thead>
<tr style='background-color: #f8f9fa;'>
<th style='{commonPadding}{headerStyle}'>製品ID</th>
<th style='{commonPadding}{headerStyle}'>製品名</th>
<th style='{commonPadding}{headerStyle}'>カテゴリー</th>
<th style='{commonPadding}{headerStyle}'>ブランド</th>
<th style='{commonPadding}{headerStyle}'>価格</th>
<th style='{commonPadding}{headerStyle}'>在庫状況</th>
<th style='{commonPadding}{headerStyle}'>評価</th>
</tr>
</thead>
<tbody>
{Concat(Samples,$"<tr style='hover: background-color: #f8f9fa;'>
<td style='{commonPadding}'>{ThisRecord.ProductID}</td>
<td style='{commonPadding}'color: #007bff; font-weight: 500;'>{ThisRecord.ProductName}</td>
<td style='{commonPadding}'>{ThisRecord.Category}</td>
<td style='{commonPadding}'>{ThisRecord.Brand}</td>
<td style='{commonPadding}'font-weight: 600; color: #28a745;'>¥{ThisRecord.Price}</td>
<td style='{commonPadding}'>
<span style='color: #856404; background-color: #fff3cd; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem;'>{ThisRecord.StockStatus}</span>
</td>
<td style='{commonPadding}'color: #6c757d;'>★{ThisRecord.Rating}</td></tr>")}
</tbody>
</table>
"
)
Power Apps
で値を持っている場合は、Filter 関数をはじめ、Power Apps
側で出力する値を制御できます。
そのシナリオを想定し、複数のデータをJSON 関数で文字列に変換し、Power Automate
に渡します。
Export.Run(
JSON(
Samples,
JSONFormat.FlattenValueTables
)
);
JSON 関数の引数はFlattenValueTables
です。
値テーブル として、[1,2,3] 表記は、各レコードに 1 つの 値 列があるレコードを含むテーブルになります。 JSON では、同じ表記法で 3 つの数値の配列を表します。 2 つの間の相互運用性を容易にするために、このオプションは、レコードの配列ではなく、Power Fx 値テーブルを JSON 対応の配列にフラット化します。
ここまでがPower Apps
の解説です。
次にPower Automate
を見ていきましょう。
Power Automate
Power Automateの流れは下記のようになります。
- Power Appsから
出力する二次元配列
を文字列で渡す -
JSON の解析
で値をパースする -
選択
アクションで値を二次元配列
として設定する -
OneDrive for Business コネクタで、空のファイルを作成する
- 拡張子は
.xlsx
に設定、ファイル コンテンツは空白文字列
- 拡張子は
- Excel Online (Business) コネクタをもちいて、(2)で作成したExcelファイルに、テーブルを作成する
-
Office 365 Users コネクタで
Excel
に値を挿入する
上記のうち(3)、(4)、(5)の設定値を紹介します。
(3) 選択
アクションで値を二次元配列
として設定する
-
From
: Excel出力する二次元配列@{body('JSON_の解析')}
-
Map
: 行の要素を指定
選択
アクションにおいて、テキスト モードに切り替え
をクリックし、[]
で囲んで要素を指定します。
[
@{item()?['Brand']},
@{item()?['Category']},
@{item()?['Price']},
@{item()?['ProductID']},
@{item()?['ProductName']},
@{item()?['Rating']},
@{item()?['StockStatus']}
]
(4) OneDrive for Business コネクタで、空のファイルを作成する
ファイル コンテンツを
(半角スペース)にして空のファイルを作成します。
これが一番驚いたポイントです。
フォルダーパス
: /
(任意のパスに置き換えるポイントです)
convertTimeZone(utcNow(),'UTC','Tokyo Standard Time','yyyy-MM-dd_HHmmss')}.xlsx
convertTimeZone(utcNow(),'UTC','Tokyo Standard Time','f')
ファイルコンテンツ
:
(5) Excel Online (Business) コネクタをもちいて、(2)で作成したExcelファイルに、テーブルを作成する
-
場所
:OneDrive for Business
-
ドキュメント ライブラリ
:個人のOneDrive for Businessに紐づいたドキュメント
-
ファイル
: (4)の戻り値からID
を取得
表の範囲
、テーブル名
、列名
はハードコードしてしまっています。
テーブル名は後述のGraph API
で用いるため、重要なキーになります。
表の範囲や列名を流動的にするには、データ操作のテクニックが必要です。
(6) Office 365 Users コネクタでExcel
に値を挿入する
Graph API
を使って、作成したテーブルに配列を挿入します。
https://graph.microsoft.com/v1.0/me/drive/items/@{split(actions('テーブルの作成')?['inputs']?['parameters']?['file'],'.')?[1]}/workbook/tables/Sample/rows
上記のポイントは split(actions('テーブルの作成')?['inputs']?['parameters']?['file'],'.')?[1]
です。
こちらの正体は、「(4) OneDrive for Business コネクタで、空のファイルを作成する」から取得できるファイル識別子Id
を.
で分割した最後の値です。
テーブルの作成
の入力値を参照するため、ドツボにハマるとすれば、テーブルの作成
のファイルの指定を誤るときですね。(体験談)
実行時のアクションの出力を返すか、または式に割り当てることができる他の JSON の名前と値のペアの値を返します。 既定では、この関数はアクション オブジェクト全体を参照しますが、必要に応じて値を取得するプロパティを指定することができます。 短縮版については、 body()を参照してください。 現在のアクションの場合は、action() をご覧ください。
- メソッド:
POST
{
"values": @{body('選択_二次元配列に変換')}
}
非常に素晴らしい機能です。圧倒的な速さで処理が完了します。
課題点
しかしながら、このエクスポート方法にはいくつか課題があります。
Excel Online (Business) コネクタ、テーブルの作成
の際に、ファイルの場所
、ドキュメント ライブラリ
の設定が下記のようにされています。
この設定値drive
は、ユーザーによって値が変動するdriveId
です。
アプリケーションを公開し、ユーザーに機能を展開した際に、driveId
の相違から正しく機能しない可能性が発生します。
対応策
対応策としては、このdriveID
をGraph APIで明示的に取得し、テーブルの作成に当てはめる方法があります。
旧情報
OneDrive for Business
をターゲットにすれば、Office 365 Users コネクタを介して簡単にdriveId
は取得できます。
- メソッド:
GET
エンドポイントは下記のとおりです。
https://graph.microsoft.com/v1.0/me/drive/root
ここで取得できる値の例です。parentReference
のもとにあるdriveId
が欲しい値です。
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem)/$entity",
"createdDateTime": "2022-06-04T15:06:22Z",
"id": "01FGLN35V6Y2GOVW7725BZO354PWSELRRZ",
"lastModifiedDateTime": "2024-11-30T13:04:21Z",
"name": "root",
"parentReference": {
"driveType": "business",
"driveId": "b!2ZD9opzPOkWhzqZIQCFx4WyB88c_7exOoyaMumiJ4BfRIaYZstvCRJcaEZUxLaL0"
},
"webUrl": "https://personal.sharepoint.com/personal/personal_com/Documents",
"fileSystemInfo": {
"createdDateTime": "2022-06-04T15:06:22Z",
"lastModifiedDateTime": "2024-11-30T13:04:21Z"
},
"folder": {
"childCount": 0
},
"root": {},
"size": 999
}
body('HTTP_要求を送信します_driveIdの取得')?['parentReference']?['driveId']
新情報
有識者おいしみさんよりご助言いただきました!!
OneDrive for Business ファイルの作成
の出力であるID
から値は取得できそうです。
OneDrive for Business
コネクタのファイルの作成
アクションから下記を取得します。
こちらがdriveId
に該当します。
split(outputs('ファイルの作成_空のコンテンツを作成')?['body/Id'],'.')?[0]
上記からテーブルの作成
アクションのドキュメントライブラリの値を下記のように設定します。
この場合、ユーザーが多様な場合でも正常に動作します。
結果
200件ほどの値の出力であれば、秒で完了します。
改めてReza
の超絶テクニックには脱帽ですね!