コルネの進捗や備忘録が記されたなにか

進捗や成果物や備忘録てきななにかを雑に更新していきます。

SharePoint ListのDatverseへの移行がこれまで以上に簡単に行えるようになりました!

はじめに

SharePoint Listにある列定義や、データをDataverseにこれまで以上により簡単に移行できるようになりました!

powerapps.microsoft.com

そのまま単純移行するだけでなく、当初間違えて日本語名などで列を作成してしまって内部名が適切なものでない列の内部名の修正や、データ型の変更などもこの移行時に行えるようですね。

SharePoint ListのDataverseへの新しい移行法を試してみる

移行方法

SharePoint ListをDataverseに移行する方法は現在大きく分けて2種類あります。

1つ目は、SharePoint ListをDataverseに移行した後そのままPower AppsでDataverseをデータソースにしたキャンバスアプリを作成する方法です。

これはブログでも紹介されている通り、「データで開始する」 > 「SharePoint リストで作成」を選ぶことで利用できます。

これはこちらや、

こちらから選択した場合でも同じことができます。

もう一つがSharePoint ListをDataverseに移行だけを行う方法です。
こちらの方法で移行した場合はDataverseにテーブルだけが作成されアプリの作成は行われません。

自身のやりたいことに合わせてそれぞれ利用してください。

細かい機能の確認

公式の記載ではなく、私が検証してみた限りの記載なのでご注意ください。

テーブルのプロパティを編集する

「テーブルのプロパティを編集する」を選択するか、テーブル名の右にある鉛筆アイコンを選択すると、テーブルのプロパティ情報の編集が可能です。

説明には元となったSharePoint Listの場所が自動で記載されています。

表示名はもちろんのこと、プライマリ列やスキーマ名も変更することが可能です。

プライマリ列とは?という場合は以下を参考にしてください。

learn.microsoft.com

行の所有権

「行の所有権」を選択することで、テーブルの所有権を設定することができます。

所有権に関してはこちらを参考にしてください。

learn.microsoft.com

列の編集

特定の列を選択して、「列の編集」を選択することで対象の列のデータの種類や書式、スキーマを変更可能です。

もし日本語で列名作成しちゃってて内部名が適切なものでなかった場合や、データ型を適当に設定してしまったせいで適当なものでない場合などはこのタイミングで変更を行ってください。

設定されるデータの種類

SharePoint Listで設定していた列が、どのようなデータの種類に初期設定されるかの簡易対比です。

絶対こうなる!といったような保証はないのであくまでも参考にとどめていただければ。

ちなみにSharePoint List側はこのようなリストを用意しています。

これを移行しようとすると初期表示ですとこのような表示になります。

Dataverseの列の種類はこちらを参考にしてください。

learn.microsoft.com

learn.microsoft.com

数値

元データから考えると、多分これは整数の方がいいですかね。

数値(小数あり)

1行テキスト

複数行テキスト

書式が何故か入ってくれないんですよね。(不具合?)

恐らくこういう表記になるのが正しい。

日付と時刻

選択肢

選択肢もちゃんと移行できるっぽいですね。

ただ既定の選択肢がちゃんと設定できてないっぽいので必要に応じて自身で設定が必要そうです。

参照

参照列はやはりだめっぽいですね。。。

参照列に関してはテーブル作成後に自身で移行をしてあげる必要がありそうです。

ちなみに今回追加されたこの機能では移行対象外の列の指定というのができなさそうなので、一旦この設定のまま列を作成する必要があります。

はい/いいえ

ちなみに「はい/いいえ」列はデータがちゃんと移行されません。

どうやら「既定の選択肢」で設定した値にすべて上書きされちゃうようです。

通貨

通貨になってくれてないですね。

通貨に関しては自身で直してあげる必要がありそうです。

ハイパーリンクまたは画像

選択肢(複数選択可能)

評価(AverageRating)

DataverseにはSharePoint Listの評価に類するデータの種類はないので小数になりますね。

評価の数(RatingCount)

こちらは移行されませんでした。

ただし誰が評価したのか?を表す "評価者" (RatedBy) は移行されますので、こちらを利用することになります。

ただしこちらは1行テキストになってしまっているのでメールアドレスに変更した方が良いですね。

集計値

まぁ無理ですよね。
せめて数値にはして欲しかったなぁ。。。

ユーザーまたはグループ

こちらも1行テキストになってしまうので注意してください。

イメージ

こちらは移行されませんでした。

おわりに

まだまだPreviewの機能なので上手く動いてくれないところもいくつかありますね。

ただこの機能を利用することでこれまで以上にSharePoint ListからDataverseへの移行が行いやすくなったかと思います!

SharePoint Listですと利用できないがDataverseであればできることや、アクセス権周りでDataverseへの移行を考えなくてはいけない場面があるかと思います。
その際にこの機能が役立ちそうですね!

Dataverseへの移行の判断材料としてはりなたむさんのこちらのスライドが非常に参考になるかと思います。

www.docswell.com

www.docswell.com

Virtual Tableを用いてDataverse利用を行う。というのも1つの回避策ですが、それではいくつか制限もありますので、機能をきちんと理解して利用するようにしましょう。

Power Appsに新しく追加されたAI関数を試してみる

はじめに

Power Appsにいつの間にか新しいAI関数が追加されていました!

learn.microsoft.com

今回紹介するのは、以下6つの関数です。

  • AIClassify
  • AIExtract
  • AIReply
  • AISentiment
  • AISummarize
  • AITranslate

AI関数を試してみる

これらの関数を利用するためには、Dataverseの"Enviroment"テーブルをアプリに追加する必要があります。

また、正直公式ドキュメントの記載わかりにくいなぁ。。。と思いますが、

AI 機能はキャンバス アプリ、AI Builder、およびローコード プラグインで動作するため、ソリューションに簡単に統合できます。

とある通り、AI関数の利用にはAI BuilderのCapacityが必要です。

AIClassify

AIClassify 関数は、テキストを指定されたカテゴリに分類します。

構文

Environment.AIClassify({Text: <Text>, Categories: <Categories>})
パラメータ 必須 データ型 説明
Text 必須 テキスト型 分類を行う文章
Categories 必須 テーブル型 Textを分類するカテゴリ

戻り値は Classification で返され、テキスト型です。

実行例

UpdateContext({Classify: Environment.AIClassify({Text: TextInput.Text, Categories: ["Power Apps", "Power Automate", "Power BI"]}).Classification})

実行結果

公式ドキュメントのPower Appsの説明を対象の文章として行ってみます。

Power Apps は、ビジネス ニーズに合ったカスタム アプリを構築するために短時間で開発できる環境を提供する、アプリ、サービス、コネクタ、およびデータ プラットフォームのスイートです。 Power Apps を使用すると、基盤データ プラットフォーム (Microsoft Dataverse)、あるいはさまざまなオンラインおよびオンプレミス データ ソース (SharePointMicrosoft 365、Dynamics 365、SQL Server など) に接続するカスタムのビジネス アプリをすばやく構築できます。

learn.microsoft.com

続いて、公式ドキュメントのPower Automateの説明を対象の文章として行ってみます。

Power Automate は、反復的なタスクを自動化して組織に効率をもたらすために使用できるサービスです。

クラウド フロー、デスクトップ フロー、または ビジネス プロセス フロー を作成できます。

さまざまな種類のフローについては、このビデオをご覧ください。

learn.microsoft.com

最後に、公式ドキュメントのPower BIの説明を対象の文章として行ってみます。

Power BI はソフトウェア サービス、アプリ、コネクタのコレクションで、これらを組み合わせることで、関連性のないデータ ソースから、まとまりがあり、実体験的な対話型の分析情報を得ることができます。 Excel スプレッドシートや、クラウドベースとオンプレミスのハイブリッド データ ウェアハウスのコレクションなど、さまざまなデータを使えます。 Power BI を使うと、ご利用のデータ ソースへの接続、重要事項の視覚化と検出、必要に応じた任意のユーザーまたはすべてのユーザーとの共有を、簡単に実行できます。

learn.microsoft.com

いい感じに分類できてますねー

AIExtract

AIClassify 関数は、テキストから指定されたエンティティを抽出します。

ただし、ドキュメントにも記載されている通り開発中のため正しく動作しない場合があります。

私が検証した限りでは一度も動いてくれませんでした(´・ω・`)

構文

Environment.AIExtract({Text: <Text>, Entity: <Entity>})
パラメータ 必須 データ型 説明
Text 必須 テキスト型 データ抽出を行う文章
Entity 必須 テキスト型 Textから抽出を行うエンティティ

戻り値は ExtractedData で返され、テーブル型です。

実行例

Environment.AIExtract({Text: TextInput.Text, Entity: "State"}).ExtractedData

実行結果

Entityを変えたり文章を変えたりしてみましたが、動かなかったです。。。

AIReply

AIReply 関数は、メッセージに対する返信のサンプルを作成します。

構文

Environment.AIReply({Text: <Text>})
パラメータ 必須 データ型 説明
Text 必須 テキスト型 応答を行うテキスト

戻り値は PreparedResponse で返され、テキスト型です。

実行例

Environment.AIReply({Text: TextInput.Text}).PreparedResponse

実行結果

以下のようなメッセージで実行しました。

お世話になっております。社内のシステムにログインできなくなってしまいました。パスワードをリセットしていただけないでしょうか?

その結果以下のようなメッセージが作成されました。

お世話になっております。ご連絡いただきありがとうございます。システムへのログインに問題が発生しているようで、お手数をおかけして申し訳ありません。

パスワードのリセットについては、システム管理者にお問い合わせいただく必要があります。システム管理者に連絡し、パスワードのリセット手続きをお願いいたします。もし、システム管理者の連絡先がわからない場合は、詳細を教えていただければ、より具体的なアドバイスをお伝えできます。

お手続きに関して何かお力になれることがありましたら、お知らせください。よろしくお願いいたします。

社内ドキュメントなどを参考にしているわけではないので、所謂ChatGPTなどに質問したときと同様の返信結果が得られます。

AISentiment

AISentiment 関数は、メッセージに対するセンチメントを返します。

構文

Environment.AISentiment({Text: <Text>})
パラメータ 必須 データ型 説明
Text 必須 テキスト型 センチメントの抽出を行うテキスト

戻り値は AnalyzedSentiment で返され、テキスト型です。
返される値は「Positive」、「Neutral」、「Negative」の3種です。

実行例

Environment.AISentiment({Text: TextInput.Text}).AnalyzedSentiment

実行結果

まずは以下のようなメッセージで実行しました。

今年のサマーピクニックは素晴らしかったです!会場の雰囲気、食事、そしてスタッフの対応が素晴らしく、参加者全員が楽しめました。来年もぜひ開催してほしいです。

次に以下のようなメッセージで実行してみました。

社内セミナーで新しいツールの導入についてのプレゼンテーションがありました。内容は分かりやすかったですが、質疑応答の時間が少なかったのが残念でした。

最後に以下のようなメッセージを実行してみました。

忘年会の会場が狭すぎて、参加者同士のコミュニケーションが取りづらかったです。また、料理の味もあまり良くなかったです。来年は改善してほしいです。

AISummarize

AISummarize 関数は、テキストの要約を作成します。

構文

Environment.AISummarize({Text: <Text>})
パラメータ 必須 データ型 説明
Text 必須 テキスト型 要約を行う文章

戻り値は SummarizedText で返され、テキスト型です。

実行例

Environment.AISummarize({Text: TextInput.Text}).SummarizedText

実行結果

公式ドキュメントのPower Appsの説明を対象の文章として行ってみます。

Power Apps は、ビジネス ニーズに合ったカスタム アプリを構築するために短時間で開発できる環境を提供する、アプリ、サービス、コネクタ、およびデータ プラットフォームのスイートです。 Power Apps を使用すると、基盤データ プラットフォーム (Microsoft Dataverse)、あるいはさまざまなオンラインおよびオンプレミス データ ソース (SharePointMicrosoft 365、Dynamics 365、SQL Server など) に接続するカスタムのビジネス アプリをすばやく構築できます。

learn.microsoft.com

以下のような要約結果が返ってきました。

Power Apps is a suite of apps, services, connectors, and a data platform that allows for the quick development of custom apps tailored to business needs. With Power Apps, users can rapidly build custom business apps that connect to foundational data platforms like Microsoft Dataverse, as well as various online and on-premises data sources such as SharePoint, Microsoft 365, Dynamics 365, and SQL Server.

うーん。。。
日本語の文章を要約しても英語で返ってきてしまいます。

日本語訳すると以下のようになります。

Power Apps は、アプリケーション、サービス、コネクタ、およびデータプラットフォームのスイートであり、ビジネスニーズに合わせたカスタムアプリケーションの迅速な開発を可能にします。Power Appsを使用することで、ユーザーはMicrosoft Dataverseのような基盤となるデータプラットフォームや、SharePointMicrosoft 365、Dynamics 365、SQL Serverのような様々なオンラインおよびオンプレミスのデータソースに接続するカスタムビジネスアプリを迅速に構築することができます。

要約できている...?

もとの文章が簡潔だったってことかな?

冗長な文章で試してみます。

お世話になっております。私たちのチームは、最近新しいプロジェクトに取り組んでいます。このプロジェクトは、当社の製品ラインを拡大し、市場での競争力を高めることを目指しています。

プロジェクトの背景には、顧客からの要望や市場の変化があります。私たちは、これらの要因を考慮して、新しい製品を開発し、既存の製品を改善しています。

プロジェクトのスコープは広範で、多くの部門が関与しています。設計、開発、テスト、マーケティング、販売、サポートなど、さまざまな活動が進行中です。

私たちは、プロジェクトの進捗状況を定期的に報告しており、ステークホルダーと連携しています。課題やリスクも適切に管理しています。

プロジェクトの成功に向けて、私たちは全力を尽くして取り組んでいます。今後も引き続き報告を行い、進捗を共有していきます。

ご質問やご意見があれば、お気軽にお知らせください。よろしくお願いいたします。

以下のような要約結果が得られました。

Our team is currently working on a new project to expand our product line and increase our competitiveness in the market. This project is driven by customer demands and changes in the market. We are developing new products and improving existing ones to meet these factors.

The project involves multiple departments, including design, development, testing, marketing, sales, and support. We are actively working on various activities within these departments.

We regularly report on the progress of the project and collaborate with stakeholders. We also manage issues and risks effectively.

We are fully committed to the success of the project and will continue to provide updates and share progress. If you have any questions or feedback, please feel free to let us know. Thank you.

日本語訳がこちら

私たちのチームは現在、製品ラインを拡大し、市場での競争力を高めるための新しいプロジェクトに取り組んでいます。このプロジェクトは、顧客の要望と市場の変化によって推進されています。これらの要因に対応するため、新製品の開発や既存製品の改良を行っています。

このプロジェクトには、設計、開発、テスト、マーケティング、販売、サポートなど複数の部門が関わっています。私たちはこれらの部門の中で、さまざまな活動に積極的に取り組んでいます。

プロジェクトの進捗状況を定期的に報告し、ステークホルダーと協力しています。また、問題やリスクを効果的に管理します。

私たちはプロジェクトの成功に全力で取り組んでおり、今後も最新情報を提供し、進捗状況を共有していきます。ご質問やご意見がありましたら、遠慮なくお知らせください。ありがとうございました。

うーん。こんなもんかな?
段落ごとで別文章として認識しちゃってるのかな?

ちなみにChatGPTに要約依頼した結果がこちら

チームは新しいプロジェクトに取り組んでおり、これは製品ラインの拡大と競争力向上を目指しています。顧客の要望や市場の変化を考慮して新製品の開発と既存製品の改善が進められています。多くの部門が関与し、設計、開発、マーケティング、販売、サポートなどの活動が進行中です。進捗状況は定期的に報告され、課題やリスクも管理されています。チームはプロジェクトの成功に向けて全力を尽くし、引き続き進捗を共有していく意向です。質問や意見があれば歓迎します。

Microsoft EdgeのCopilotに要約依頼した結果がこちら

もちろんです。以下は、提供された文章の要約です。


プロジェクト要約: 製品ライン拡大と競争力向上

私たちのチームは新しいプロジェクトに取り組んでいます。このプロジェクトの目的は、当社の製品ラインを拡大し、市場での競争力を高めることです。顧客の要望や市場の変化を考慮して、新製品の開発と既存製品の改善を進めています。プロジェクトは広範で、設計、開発、テスト、マーケティング、販売、サポートなど多くの部門が関与しています。進捗状況は定期的に報告され、ステークホルダーと連携しています。課題やリスクも適切に管理し、プロジェクトの成功に向けて全力を尽くしています。ご質問やご意見があればお知らせください。


最後にGemini

プロジェクト概要

目的: 製品ラインの拡大と市場競争力の強化
背景: 顧客からの要望と市場の変化
内容: 新製品開発、既存製品改善
範囲: 設計、開発、テスト、マーケティング、販売、サポート
進捗: 定期報告、ステークホルダーとの連携、課題・リスク管理
今後の予定: 継続的な報告、進捗共有
連絡先: 質問・意見があればご連絡ください

補足

  • プロジェクトチームは、このプロジェクトの成功に向けて全力を尽くしています。
  • 詳細については、担当者にお問い合わせください。

この要約は、以下の点を考慮して作成しました。

  • 文章全体の内容を簡潔にまとめました。
  • 重要な情報を抽出し、わかりやすく表現しました。
  • 読みやすく、理解しやすいように構成しました。

ご不明な点があれば、お気軽にご連絡ください。

AITranslate

AITranslate 関数は、テキストの翻訳結果を作成します。
翻訳対象の言語は指定する必要なく(指定できない?)、自動で検出されます。

構文

Environment.AITranslate({Text: <Text>, TargetLanguage: <TargetLanguage>})
パラメータ 必須 データ型 説明
Text 必須 テキスト型 翻訳を行う文章
TranslatedText 任意 テキスト型 翻訳先のテキスト

公式ドキュメントの例だと Language になっていますが、こちらでは動きません。

Power Appsで関数入力時にHintとして表示されることらが正しいです。

戻り値は TranslatedText で返され、テキスト型です。

実行例

Environment.AITranslate({Text: TextInput.Text, TargetLanguage: "ja"}).TranslatedText

実行結果

公式の例にある文章を日本語に翻訳してみます。

Washington is a state that offers a variety of food experiences for locals and visitors alike.
Whether you are looking for fresh seafood, farm-to-table produce, ethnic specialties, or gourmet treats, you will find something to satisfy your taste buds in Washington. Washington is famous for its seafood, especially salmon, oysters, crab, and clams. The state has a long coastline and numerous rivers and lakes that provide abundant and high-quality seafood.

以下のような翻訳結果が得られました。

ワシントン州は、地元の人々や観光客にさまざまな食体験を提供する州です。
新鮮なシーフード、農場から食卓までの農産物、エスニック料理、グルメなおやつを探しているかどうかにかかわらず、ワシントンで味覚を満足させるものが見つかります。ワシントン州はシーフード、特にサーモン、カキ、カニ、アサリで有名です。この州には長い海岸線と数多くの川や湖があり、豊富で高品質のシーフードを提供しています。

ちなみにDeeplの結果はこちら

ワシントン州は、地元の人にも観光客にも様々な食体験を提供する州である。
新鮮なシーフード、農場直送の農産物、エスニック料理、グルメなお菓子など、ワシントン州ではあなたの舌を満足させる何かが見つかるはずだ。ワシントンはシーフード、特にサーモン、カキ、カニ、ハマグリで有名だ。ワシントン州には長い海岸線と多数の川や湖があり、豊富で質の高いシーフードを提供している。

問題ない精度で翻訳できてるのではないでしょうか?

AISummarize の結果も AITranslate と組み合わせれば指定の言語で出力することが可能ですね。

おわりに

  • Dataverseのテーブルをアプリに追加が必要なこと
  • AI Builderのクレジットを消費してしまうこと

が許容できるのであれば、これらを使えば簡単にPower AppsでAI関数を用いることができます。

皆さんも是非お試しください!

Power AppsにCopilot answer(Preview)が追加されました!

はじめに

Power AppsにCopilot answerコントロールPreviewで追加されました🎉

powerapps.microsoft.com

learn.microsoft.com

これはDataversreにあるデータをもとにCopilotが回答してくれる。というコントロールですね。

似たコントロールでCopilotコントロールがあります。

learn.microsoft.com

こちらのコントロールに関しては以下記事で紹介していますので、見てみてください。

koruneko.hatenablog.com

今回追加されたCopilot answerコントロールは、Copilotコントロールとは異なり事前に定義された質問(プロンプト)に従って回答を生成します。

Copilot answerを利用する

前提条件

公式ドキュメントですと以下のように記載されていますが、この設定ないと思うのですよね。。。

実際の画面

設定色々弄って最低要件のチェックしたわけではないので、多分ここ設定必要だよね?と思われるところを列挙すると、

  1. Resion(地域)がUnited States(米国)の環境の作成
  2. Copilotのオン
  3. Browserの言語設定を英語にする

恐らく上記が最低限必要な条件だと思います。

Copilot answerを利用する

使い方はいたって単純です。

Copilot answerコントロールを追加して、対象のDataverseテーブルとCopilotが回答を行うためのViewやFeildsを設定するだけでOKです。

CopilotコントロールのようにDataverse側の設定は不要ですぐに使えます。

例えば以下のような架空のユーザー情報が格納されたテーブルに対して、 "Summarize records" というレコードをサマリーしてもらうような指示を実行します。

その結果以下のような回答が得られます。

There are more than 30 records in the dataset. The dataset contains the cr2cc_externalprimarykey column, which is of type Float. Some of the records includes 1.0, 2.0 and 3.0.

==NOTE==
上記英文はPowerToysのOCR機能 + 私が手動で修正したものです。Power Appsからコピペできないので注意してください。
もし、回答内容をユーザーが2次利用できるようにしたい場合は CopilotAnswer.Answer を参照してください。
====

日本語訳

データセットには30以上のレコードがある。データセットにはcr2cc_externalprimarykeyカラムがあり、これはFloat型である。レコードの中には1.0、2.0、3.0がある。

うーーん。。。ちょっと違う!

ちなみに、"Question for Copilot"(Question)のプロパティの値をテキスト入力などで入力された値のような動的な値に設定することも可能です。

CopilotコントロールとCopilot answerコントロールの比較

CopilotコントロールとCopilot answerコントロールの簡易比較です。

どちらのコントロールを利用するか?の判断材料になれば。

Copilot Copilot answer
対応地域 米国 米国
Dataverse側の設定 必要 不要
対話形式での会話 可能 不可

Preview機能なので変更になる可能性があります。

おわりに

Power AppsにもCopilotを活用した機能がどんどん追加されていますね!

CopilotコントロールやCopilot answerコントロールの利用にはDataverseの利用が必要になってきますが、AI BuilderやAOAIを活用するよりも気軽に試せるので、これらのコントロールでやりたいことが充分満たせるのであれば、これらのコントロールを利用してみてもいいかもですねー

Power AppsにCopilotによる入力テキスト作成補助機能が追加されたので試してみた

はじめに

Power Appsに"Draft text input with Copilot"という、アプリ利用者がテキストを入力する際にPower Appsの画面上でCopilotを利用して入力補助を行うことができるような機能が追加されました👏

powerapps.microsoft.com

なおこの機能は現在Preview機能であり、また以下の条件を満たしている必要があります。

learn.microsoft.com

重要

  • この機能を使用するには、環境が米国地域にある必要があります。
  • この機能を使用するには、ブラウザー言語が米国英語である必要があります。
  • この機能は、Azure OpenAI Service によって提供されます。
  • この機能は、使用制限またはキャパシティ調整の対象となる場合があります。
    Copilot はサポートされていないため、カスタマー マネージド キー (CMK) またはロックボックスがある環境では機能しません。
  • プレビュー機能は運用環境での使用を想定しておらず、機能が制限されている可能性があります。 これらの機能を公式リリースの前に使用できるようにすることで、顧客が一足先にアクセスし、そこからフィードバックを得ることができます。
  • この機能は現在展開中であるため、お住まいの地域ではまだ利用できない可能性があります。
  • プレビューの詳細については、プレビューの条件 をご覧ください。

恐らく以下がハードル高めですかね。

  • 環境が米国地域にあること
  • ブラウザーの言語が米国英語であること

動作

対応しているコントロール

現在(2024/04/03)は、

  • 複数行テキスト
  • リッチテキスト

にて利用することができます。

普通の"Text Input"コントロールではこちらの機能は利用できないのでご注意ください。

どういうことに使えそう?

ぱっと思いついた限り以下のようなケースで役立ちますかね。

  • 一般的な用語や製品の概要を作成してもらう
  • 日報や週報の文章をいい感じにしてもらう
  • メールやチャットに投稿する文章をいい感じにしてもらう

とかですかね?

注意としては、ChatGPTやCopilot Chatのように対話形式でなにかを出力してくれるわけではないので、その点を理解してプロンプトを記載する必要がある点です。

現時点の動作を見る限りでは、記載した文章の要約に使える。程度に思っておいた方がよさそうだなと感じました。

おわりに

Copilotがどんどん色々なサービスや機能に付与されていきますね!

どんなことができるか?なにができるか?など検証できる環境のある方は一度自身でも試してみてみることをおすすめします。

ドキュメントや他者からの伝聞では過小評価/過大評価してしまうことが多々あると思いますので。

今回は検証 + 紹介を行うための記事でしたので短めでしたがこの程度で。

Power Appsを新規作成するとソリューションに含まれるようになりました

はじめに

Power Platformには「優先するソリューション (プレビュー)」という機能があります。

こちらの"詳細"にあるリンクに飛ぶと「正常なALMについて」のドキュメントへ遷移します。

learn.microsoft.com

多分みたいのこれじゃないと思うな。

「優先するソリューション (プレビュー)」のドキュメントはこちらになります。

learn.microsoft.com

上記をみると、Power Platform管理センターにて「優先するソリューション」を「オン」に設定するとソリューション画面で、各ユーザー自身が選択したソリューションにアプリが追加される。との記載があります。

しかし、私が確認したかぎり3/2(土)時点ではソリューション画面にて以下のように優先するソリューションの設定が表示されていました。

これに伴い、現在Power Appsで新規作成したアプリは優先するソリューションで設定したソリューションに含まれるようになっています。

ドキュメントと動作が違う!と思いますね。

こういうときは英語(原文)のドキュメントを見てみましょう。

learn.microsoft.com

更新が2024/03/01になっています。

また前提条件のPower Platformの管理センターにまつわる記載もこちらでは消えていますね。

つまり日本語のドキュメントはまだ更新が間に合っていないだけ。ということで、そしてプレビューも現在では外れている。
ということですね。

Power Platform管理センターにあるあの設定項目も今ではハリボテです。

ちなみにこの変更により、既存のアプリとフローに対しては影響はありません。

影響を直接受けるのは新規作成のアプリだけですね。(この設定だけなら)

動作の検証(新規作成)

Power Appsを新規作成したとき

優先するソリューションをデフォルトの"Common Data Services Default Solution"にしてPower Appsで新規アプリを作成してみます。

名前とか中身はどうでもいいので適当に作成したアプリを新規作成して保存します。

保存後、ソリューションの中身をみてみます。

ソリューションに含まれていますね。

Power Automateを新規作成したとき

引き続き優先するソリューションを"Common Data Services Default Solution"に設定したまま、新規フローの作成を行います。

またもや適当にフローを新規作成して保存します。

保存後、ソリューションをみてみます。

ソリューションに含まれていないですね。

そもそもPower Automateのソリューションの画面では優先するソリューションの設定項目がありません。

ドキュメントをみてみると以下のように記載されています。

Prerequisites
We recommend that admins enable the Cloud flows environment setting in Power Platform. Enabling this feature ensures cloud flows are also stored in Dataverse and that they're added to the maker's preferred solution. More information: Create new canvas apps and cloud flows in a Dataverse solution

前提条件
Power Platformのクラウドフロー環境設定を有効にすることをお勧めします。この機能を有効にすることで、クラウドフローもDataverseに保存され、作成者の希望するソリューションに追加されます。詳細はこちら: Dataverseソリューションで新しいキャンバスアプリとクラウドフローを作成する

直接的には記載されていないものの、文章から察するにクラウドフローも優先するソリューションに含まれるようにしたい場合は別途設定しろ。みたいなこといっていますね。

こちらの設定については後程記載。

何が困る?

このままの設定ですと、ざっくり記載すると以下が困ることですかね。

開発者目線
* Power AppsとPower Automateの連携がこのままだとできず、もう1アクションが必要になる
* 一度ソリューションに追加したアプリ(フロー)を非ソリューション管理にすることはできない

管理者目線
* Dataverse環境のキャパシティ消費と関連コストが増加する可能性がある

Power AppsとPower Automateの連携

恐らくすぐに困ることになるのは、Power AppsとPower Automateの連携に関してですね。

Power AppsとPower Automateを連携する際、Power AppとPower Automateはお互い非ソリューション管理であるかソリューション管理である必要があります。

表にするとこんな関係になります。

従って、先ほど作成したアプリから先ほど作成したフローは連携できないということですね。

これは既存フロー(非ソリューション管理)を新規作成した保存前のアプリでも同様の事象です。

フローをソリューションに追加してアプリと連携できるようにする

先ほどの表でも示した通り、お互いに非ソリューション管理であるか、ソリューション管理であればアプリとフローの連携は行うことができます。

ただし、一度ソリューション化したアプリ(フロー)を非ソリューション管理に戻すことはできません。

従って、フローの方をソリューションに含めてあげます。

クラウドフローを追加したいソリューションを選択し、「既存を追加」 > 「自動化」 > 「クラウドフロー」を選択します。

その後、「Dataverse の外部」よりクラウドフローを選択して「追加」を行います。

これにより、クラウドフローもソリューションに含めることができたので、アプリとフローの連携ができるようになります。

注意点として、ソリューション化を行うとPower Automateのzipでのエクスポートができなくなります。
※Power Appsはできます。

一応裏ワザとして、フローの詳細画面からURLの "/details" を "/export" に変更してアクセスすると、zipエクスポートの画面に遷移することは可能ではあります。

詳細画面

ただしこの方法は公式から案内されている方法ではなく、現状こうすることでできるよ!という本当に裏ワザ程度の認識でいてください。
これによりなにか不都合が発生しても私含めて誰も責任は取れない。という理解のもとのご使用をおすすめします。

Power Appsの編集画面からPower Automateを作成する

Power AppsのPower Automateペインからフローを作成することもできますね。
これを行った場合の動作に関してです。

保存済みアプリからフローを作成する

上で作成したアプリにてPower Automateペインからフローを作成してみます。

このようなフローを作成し保存します。

その後アプリを保存してソリューションを確認してみます。

追加されてないですね。

ではどこに追加されたのか?というと「既定のソリューション」に追加されています。

「既定のソリューション」というソリューションに追加されているので、このフローは他新規アプリからも参照することが可能です。

未保存のアプリからフローを作成する

未保存のアプリ、つまりまだソリューションに含まれていないアプリからフローを作成してみます。

上記状態からフローを作成します。

このアプリを保存します。

アプリ、フローともに優先するソリューションで指定したソリューションに含まれていますねー

Power Automateも新規作成時にソリューションに含まれるようにする

優先するソリューションの機能が追加された後に作成されたPower AppsとPower Automateを連携する方法を上記で記載しましたが、一々フローをソリューションに追加するのはめんどくさいですよね。

ということでフローも優先するソリューションに含まれるようにしたいと思います。

上でも記載しましたが、「Dataverse ソリューションで新しいキャンバス アプリとクラウド フローを作成する (プレビュー)」をオンにすれば、フローも優先するソリューションに追加されるとドキュメントに記載されていましたので、これを試してみます。

learn.microsoft.com

ただし、これを行う前に以下前提条件および考慮事項を確認の上設定してください。

learn.microsoft.com

前提条件

learn.microsoft.com

考慮事項
既定でソリューションにキャンバス アプリとクラウド フローを作成することを決定する前に、次の考慮事項を考慮してください。

  • Dataverse 環境のキャパシティ消費と関連コストが増加する可能性があります。

  • キャンバス アプリに関連する既知のソリューション制限は、ソリューションで作成されたキャンバス アプリにも既定で適用されます。

  • この機能により、アプリのデータ ソースを追加するときに、環境変数が自動的に作成されます。

  • 既定では、この機能はすべてのキャンバス アプリを、Microsoft Dataverse の既定の発行者 が公開した既定のソリューションである、Common Data Services の既定のソリューション に保存します。 ただし、キャンバス アプリを別のソリューションに保存することをお勧めします。 既存のキャンバス アプリのソリューションへの追加に関する詳細情報

  • Power Platform 管理センターでキャンバス アプリとクラウド フローの機能をオンまたはオフにすると、組織テーブルの Dataverse プロパティ enablecanvasappsinsolutionsbydefaultenableFlowsInSolutionByDefault が更新されます。 次のサンプル ODATA スニペットを使用して、これらのプロパティの値を表示できます: [org URI]/api/data/v9.0/organizations。 詳細については、組織サービス参照 を参照してください。

  • ご利用の環境の既定の発行者またはソリューションの接頭辞を変更する予定がある場合は、ソリューション発行者の接頭辞ソリューション発行者の接頭辞の作成ソリューション発行者の接頭辞の変更 を参照してください。

  • 非ソリューション キャンバス アプリと非ソリューション クラウド フローをソリューションに追加して Dataverse に追加することはできますが、元に戻す方法はありません。

「Dataverse ソリューションで新しいキャンバス アプリとクラウド フローを作成する (プレビュー)」をオンにする

「Dataverse ソリューションで新しいキャンバス アプリとクラウド フローを作成する (プレビュー)」をオンにする場合は、Power Platformの管理センターより、「環境」 > 「<対象の環境>」 > 「設定」 > 「機能」にアクセスします。

その後「Dataverse ソリューションで新しいキャンバス アプリとクラウド フローを作成する (プレビュー)」より、「クラウド フロー(オフ)」となっている項目を「オン」にします。

なお、この機能をオンにしようとすると以下のようなメッセージが表示されます。

前提条件や考慮事項で記載されていた内容ですね。   問題なければ「はい」を選択します。

その後忘れずに、画面下部にある「保存」を選択して、変更を反映させましょう。

フローを新規作成してみる

上記設定を行ったうえで、フローを新規作成してみます。

保存を行うと詳細画面で以下のような設定を確認できます。

既定のソリューションに保存されてそうですね。

既定のソリューションを確認してみると、ソリューション内に先ほど作成したクラウドフローがいますね。

一応Power Apps側のソリューションで設定していた優先するソリューションの中をみてみると上記フローは存在していません。

そもそもPower Automateのソリューションの画面では優先するソリューションの設定はないですね。

これは「優先するソリューション (プレビュー)」をオンに設定していた場合でも同様です。

ソリューションにアプリが作成されないようにする

続いて反対にそもそも新規作成したアプリがソリューションに含まれないようにする方法です。

これを行うには、要は対象にユーザーがソリューションにアプリを追加できないようにすればよいです。

ソリューションにキャンバスアプリを追加するには"Canvas App"テーブルに対しての書き込み権限をなくせばよいです。

learn.microsoft.com

これによりそもそもソリューションにアプリを作成する権限がないので、非ソリューション管理のアプリしかユーザーは作れなくなります。

ただし、これは個別の環境のみ有効な対策です。

既定の環境については"Environment Maker"ロールを全ユーザーがもっており、このロールでは"Canvas App"テーブルに対しての書き込み権限を持っています。

そして既定の環境のこちらのロールは変更不可であり、またユーザーからこちらのロールを取り上げることはできません。(取り上げても少しすると自動で戻るかと思います。)

learn.microsoft.com

管理者目線でいうと、既定の環境こそブロックしたい気がするんですけどねー。。。
ただ、私はPower Platformの環境管理に関しては素人に毛が生えたレベルなので、私がしらないだけでなにかやり方があるのかもしれません。

詳しい方追加や訂正していただけると助かります。

おわりに

検証結果 + 私の知っている & 調査した限りの情報まとめでした。

記載内容に誤りや補足情報などありましたらご指摘いただけますと幸いです。

【2024/02/27】旧デザイナーのPower AutomateでPower Appsに値を返す場合、注意が必要な場合があります

はじめに

Power AppsからPower Automateを呼び出し、Power AutomateからPower Appsに値を返す場合、以下のようなエラーが表示される場合があります。

JSON 解析エラー。必要な 'ブール値' に対して '文字列' です。

まず結論から書くとこのエラーは以下条件下で発生することを現在(2024/02/27)私の方では確認しています。

  • Power Automateを旧デザイナーで編集している
  • Power Appsへ返す値の型を変更した

検証

新しいデザイナーでフローを作成した場合

まずは、以下のようにPower AutomateからPower Appsへ「文字列」のデータを返すだけのフローを新しいデザイナーで作成します。

こちらのフローをPower Appsから呼び出してみます。

当然、「文字列」のデータを取得することができますね。

続いて、Power Appsに返すデータを「文字列」から「ブール値」に変更してみます。

当然、「ブール値」のデータを取得することができますね。

ここまでが正常な動作です。

旧デザイナーでフローを作成した場合

さて、続いて旧デザイナーでPower AutomateからPower Appsへ「文字列」のデータを返すだけのフローを作成します。

こちらのフローをPower Appsから呼び出してみます。

「文字列」のデータが返ってきます。
期待される動きですね。

さて、続いてPower Appsに返すデータを「文字列」から「ブール値」に変更してみます。

「ブール値」ではなく「文字列」の"False"が返ってきてしまいました。

"body": {
  "bool": "False"
}

期待している結果と異なりますので、以下のように「JSON 解析エラー」が発生してしまっています。

JSON 解析エラー。必要な 'ブール値' に対して '文字列' です。

これは「ブール値」だけでなく、「数値」の場合などでも同様の結果になります。

JSON 解析エラー。必要な '数値' に対して '文字列' です。

まぁ、数値の場合Power Appsでの応答結果みるに数値で来てるように見えるんですけどね。

問題と解決策

新しいデザイナーに戻して保存しなおす(解決しません)

新しいデザイナーでは上手くいってるので、新しいデザイナーに変更して保存しなおせばこの問題は解決するのでは?
と考えるかもしれませんがこれでは解決しないです。

コードの修正を行う

まずこの問題はフローにあり、そしてフロー側のアクション定義に問題があります。

新デザイナー、旧デザイナーのそれぞれの「コード ビュー」を見比べてみましょう。

新デザイナー

{
  "type": "Response",
  "kind": "PowerApp",
  "inputs": {
    "schema": {
      "type": "object",
      "properties": {
        "bool": {
          "title": "bool",
          "type": "boolean",
          "x-ms-content-hint": "BOOLEAN",
          "x-ms-dynamically-added": true
        }
      },
      "additionalProperties": {}
    },
    "statusCode": 200,
    "body": {
      "bool": "@false"
    }
  },
  "runAfter": {}
}

旧デザイナー

{
    "kind": "PowerApp",
    "inputs": {
        "statusCode": 200,
        "body": {
            "bool": "@{false}"
        },
        "schema": {
            "type": "object",
            "properties": {
                "bool": {
                    "title": "bool",
                    "x-ms-dynamically-added": true,
                    "type": "boolean"
                }
            }
        }
    },
    "metadata": {
        "operationMetadataId": "15a88610-3083-4fbe-bcf7-7ed0cfe8ec3c"
    }
}

差分というと、

  • Power Appsに返す値("@false" と "@{false}")
  • "metadata"の有無

の2か所ですね。

このうち問題なのは、Power Appsに渡している値です。

したがって、こちらの定義を修正します。
クリップボードにコピー (プレビュー)」よりこちらのアクションの情報をコピーします。

その後、メモ帳などに貼り付けて以下のように {} で囲まれている箇所を削除します。

そのJSONを再度コピーし、「新しいステップ」 > 「自分のクリップボード」を開き、Ctrl + Vで貼り付けを行います。

すると、選択可能なアクションが増えますのでそのアクションを選択します。

こちらの操作に関しては昔こちらでGifで紹介していますので、動いている画面見たい方はこちらをご参照ください。

koruneko.hatenablog.com

これにより追加されたアクションをみると、以下のように定義が書き換わっています。

{
    "kind": "powerapp",
    "inputs": {
        "statusCode": 200,
        "body": {
            "bool": "@false"
        },
        "schema": {
            "type": "object",
            "properties": {
                "bool": {
                    "title": "bool",
                    "x-ms-dynamically-added": true,
                    "type": "boolean"
                }
            }
        }
    }
}

これでPower Appsから再度フローを呼び出すと

無事エラーなく、「ブール値」の結果を取得することができました!

おわりに

新しいデザイナーでの不具合はちょくちょく目にしますが、古いデザイナーでの不具合(デグレ?)はちょっと珍しいですね。

古いデザイナーでフローの作成をされている方もまだまだ多いと思いますので、皆さまお気をつけくださいー

Power Automateで仕様が変わったSharePointリストのImage列に画像を登録する

はじめに

こちらでも説明している通り、SharePointリストのImage列は、従来のSiteAssets配下に保存されるのではなく、添付ファイル列に保存されるようになりました。
これにより、Image列ではデータとしては添付ファイル列に保存されている画像ファイルのファイル名のみを保持するようになっています。

koruneko.hatenablog.com

koruneko.hatenablog.com

以前のSiteAssetsに保存される仕様に戻す方法についてはこちらをご確認ください。
なお公式よりアナウンスされているような推奨されているやり方ではなく、こうすれば元の仕様の動きになったよ。というだけですので、試される方は自己責任でお願いします。(そもそもこのSharePointリストのImage列の仕様変更に関して明確なアナウンスないですが、、、)

koruneko.hatenablog.com

さて、これまではPower AppsからImage列の情報を操作するやり方を説明してきましたが、今回はPower AutomateからImage列の情報を操作するやり方について記載します。

従来のSiteAssetsへの画像の登録方法は、Hiroさんや出戻りガツオさんの記事を参考にしてください!

Hiroさん
mofumofupower.hatenablog.com

出戻りガツオさん
qiita.com

Power Automateを用いてのImage列の操作

Image列の情報を取得する

まずはPower AutomateでImage列の画像ファイルの情報を取得してみます。

取得するのは以下のようなリストの画像です。

特定のアイテムの取得というと、「項目の取得」アクションで取得可能なように思われるかもしれませんが、これではImage列の情報は取得できません。

出力結果を見てみましょう。

出力

{
    "statusCode": 200,
    "headers": {
        "Cache-Control": "max-age=0, private",
        "Transfer-Encoding": "chunked",
        "Vary": "Origin,Accept-Encoding",
        "X-NetworkStatistics": "0,4204800,0,0,71230,0,20197",
        "X-SharePointHealthScore": "3",
        "X-MS-SPConnector": "1",
        "X-SP-SERVERSTATE": "ReadOnly=0",
        "DATASERVICEVERSION": "3.0",
        "SPClientServiceRequestDuration": "89",
        "SPRequestDuration": "89",
        "X-DataBoundary": "NONE",
        "X-1DSCollectorUrl": "https://mobile.events.data.microsoft.com/OneCollector/1.0/",
        "X-AriaCollectorURL": "https://browser.pipe.aria.microsoft.com/Collector/3.0/",
        "SPRequestGuid": "c3ba7453-b884-433c-9c06-a536c450f608",
        "request-id": "c3ba7453-b884-433c-9c06-a536c450f608",
        "MS-CV": "U3S6w4S4PEOcBqU2xFD2CA.0",
        "Strict-Transport-Security": "max-age=31536000",
        "X-Frame-Options": "SAMEORIGIN",
        "Content-Security-Policy": "frame-ancestors 'self' teams.microsoft.com *.teams.microsoft.com *.skype.com *.teams.microsoft.us local.teams.office.com *.office365.com *.powerapps.com *.yammer.com engage.cloud.microsoft *.officeapps.live.com *.office.com *.microsoft365.com *.stream.azure-test.net *.microsoftstream.com *.dynamics.com *.microsoft.com onedrive.live.com *.onedrive.live.com securebroker.sharepointonline.com;",
        "MicrosoftSharePointTeamServices": "16.0.0.24607",
        "X-Content-Type-Options": "nosniff",
        "X-MS-InvokeApp": "1; RequireReadOnly",
        "P3P": "CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"",
        "X-AspNet-Version": "4.0.30319",
        "X-Powered-By": "ASP.NET",
        "Timing-Allow-Origin": "*",
        "x-ms-apihub-cached-response": "false",
        "x-ms-apihub-obo": "false",
        "Date": "Sun, 25 Feb 2024 08:02:16 GMT",
        "Content-Type": "application/json; charset=utf-8",
        "Content-Length": "1607",
        "Expires": "Sat, 10 Feb 2024 08:02:16 GMT",
        "Last-Modified": "Sun, 25 Feb 2024 08:02:16 GMT"
    },
    "body": {
        "@odata.etag": "\"3\"",
        "ItemInternalId": "1",
        "ID": 1,
        "Modified": "2024-02-25T07:58:35Z",
        "Created": "2024-02-25T07:58:33Z",
        "Author": {
            "@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
            "Claims": "i:0#.f|membership|***@***.***.com",
            "DisplayName": "*** コルネ",
            "Email": "***@***.***.com",
            "Picture": "https://***.sharepoint.com/sites/development/_layouts/15/UserPhoto.aspx?Size=L&AccountName=***@***.***.com",
            "Department": "開発部",
            "JobTitle": null
        },
        "Author#Claims": "i:0#.f|membership|***@***.***.com",
        "Editor": {
            "@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
            "Claims": "i:0#.f|membership|***@***.***.com",
            "DisplayName": "*** コルネ",
            "Email": "***@***.***.com",
            "Picture": "https://***.sharepoint.com/sites/development/_layouts/15/UserPhoto.aspx?Size=L&AccountName=***@***.***.com",
            "Department": "開発部",
            "JobTitle": null
        },
        "Editor#Claims": "i:0#.f|membership|***@***.***.com",
        "{Identifier}": "Lists%252fOperateImage4PowerAutomate%252f1_.000",
        "{IsFolder}": false,
        "{Thumbnail}": {
            "Large": null,
            "Medium": null,
            "Small": null
        },
        "{Link}": "https://***.sharepoint.com/sites/development/_layouts/15/listform.aspx?PageType=4&ListId=c07ad196%2D2eb3%2D409d%2D9af3%2D53d42e2bc1a8&ID=1&ContentTypeID=0x0100F45868826A439E41BCE3DD90F03573440077910247ED328B46BA77225702CAAF90",
        "{Name}": "",
        "{FilenameWithExtension}": "",
        "{Path}": "Lists/OperateImage4PowerAutomate/",
        "{FullPath}": "Lists/OperateImage4PowerAutomate/1_.000",
        "{HasAttachments}": true,
        "{VersionNumber}": "3.0"
    }
}

Image列の情報はないですね。

Power Automateで、Image列の情報を取得したい場合は「SharePoint に HTTP 要求を送信します」アクションで取得する必要があります。

方法

GET

URI

_api/web/lists/GetByTitle('<Your List Name>')/items(<Your List Item ID>)

出力

{
    "statusCode": 200,
    "headers": {
        "Cache-Control": "no-store, max-age=0, private",
        "Transfer-Encoding": "chunked",
        "ETag": "\"df1d8b85-2a76-4247-8eb3-eb7e2cf18f98,3\"",
        "Vary": "Origin,Accept-Encoding",
        "Set-Cookie": "ARRAffinity=72f0058640e8d668f1d9eccaa21b54dfe769c845c67c66321653924dd77a2205;Path=/;HttpOnly;Secure;Domain=sharepointonline-jw.azconn-jw-001.p.azurewebsites.net,ARRAffinitySameSite=72f0058640e8d668f1d9eccaa21b54dfe769c845c67c66321653924dd77a2205;Path=/;HttpOnly;SameSite=None;Secure;Domain=sharepointonline-jw.azconn-jw-001.p.azurewebsites.net",
        "Strict-Transport-Security": "max-age=31536000",
        "X-NetworkStatistics": "0,525568,0,0,31015,0,19590",
        "X-SharePointHealthScore": "2",
        "X-SP-SERVERSTATE": "ReadOnly=0",
        "DATASERVICEVERSION": "3.0",
        "SPClientServiceRequestDuration": "51",
        "SPRequestDuration": "51",
        "X-DataBoundary": "NONE",
        "X-1DSCollectorUrl": "https://mobile.events.data.microsoft.com/OneCollector/1.0/",
        "X-AriaCollectorURL": "https://browser.pipe.aria.microsoft.com/Collector/3.0/",
        "SPRequestGuid": "61170fa1-009d-3000-0442-1e9c12841cfa",
        "Request-Id": "61170fa1-009d-3000-0442-1e9c12841cfa",
        "MS-CV": "oQ8XYZ0AADAEQh6cEoQc+g.0",
        "X-Frame-Options": "SAMEORIGIN,DENY",
        "Content-Security-Policy": "frame-ancestors 'self' teams.microsoft.com *.teams.microsoft.com *.skype.com *.teams.microsoft.us local.teams.office.com *.office365.com *.powerapps.com *.yammer.com engage.cloud.microsoft *.officeapps.live.com *.office.com *.microsoft365.com *.stream.azure-test.net *.microsoftstream.com *.dynamics.com *.microsoft.com onedrive.live.com *.onedrive.live.com securebroker.sharepointonline.com;",
        "MicrosoftSharePointTeamServices": "16.0.0.24607",
        "X-Content-Type-Options": "nosniff,nosniff",
        "X-MS-InvokeApp": "1; RequireReadOnly",
        "P3P": "CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"",
        "X-AspNet-Version": "4.0.30319",
        "X-Powered-By": "ASP.NET",
        "x-ms-request-id": "61170fa1-009d-3000-0442-1e9c12841cfa",
        "Timing-Allow-Origin": "*",
        "x-ms-apihub-cached-response": "true",
        "x-ms-apihub-obo": "false",
        "Date": "Sun, 25 Feb 2024 08:02:16 GMT",
        "Content-Type": "application/json; odata=verbose; charset=utf-8",
        "Content-Length": "3297",
        "Expires": "Sat, 10 Feb 2024 08:02:16 GMT",
        "Last-Modified": "Sun, 25 Feb 2024 08:02:16 GMT"
    },
    "body": {
        "d": {
            "__metadata": {
                "id": "79b6ea57-35b8-48d3-89e6-26dd3665475d",
                "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)",
                "etag": "\"3\"",
                "type": "SP.Data.OperateImage4PowerAutomateListItem"
            },
            "FirstUniqueAncestorSecurableObject": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/FirstUniqueAncestorSecurableObject"
                }
            },
            "RoleAssignments": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/RoleAssignments"
                }
            },
            "AttachmentFiles": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/AttachmentFiles"
                }
            },
            "ContentType": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/ContentType"
                }
            },
            "GetDlpPolicyTip": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/GetDlpPolicyTip"
                }
            },
            "FieldValuesAsHtml": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/FieldValuesAsHtml"
                }
            },
            "FieldValuesAsText": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/FieldValuesAsText"
                }
            },
            "FieldValuesForEdit": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/FieldValuesForEdit"
                }
            },
            "File": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/File"
                }
            },
            "Folder": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/Folder"
                }
            },
            "LikedByInformation": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/LikedByInformation"
                }
            },
            "ParentList": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/ParentList"
                }
            },
            "Properties": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/Properties"
                }
            },
            "Versions": {
                "__deferred": {
                    "uri": "https://***.sharepoint.com/sites/development/_api/Web/Lists(guid'c07ad196-2eb3-409d-9af3-53d42e2bc1a8')/Items(1)/Versions"
                }
            },
            "FileSystemObjectType": 0,
            "Id": 1,
            "ServerRedirectedEmbedUri": null,
            "ServerRedirectedEmbedUrl": "",
            "ContentTypeId": "0x0100F45868826A439E41BCE3DD90F03573440077910247ED328B46BA77225702CAAF90",
            "Title": null,
            "OData__ColorTag": null,
            "ComplianceAssetId": null,
            "Image": "{\"fileName\":\"Reserved_ImageAttachment_[5]_[Image][43]_[コルネ(アリスメイド)_Advanced2023-07-26_01-35-46.234][1]_[1].png\"}",
            "ID": 1,
            "Modified": "2024-02-25T07:58:35Z",
            "Created": "2024-02-25T07:58:33Z",
            "AuthorId": 9,
            "EditorId": 9,
            "OData__UIVersionString": "3.0",
            "Attachments": true,
            "GUID": "b01187bc-beea-4883-8edb-6e4a9ad1384f"
        }
    }
}

上記でImage列のアイテムを取得できましたね!

情報としては、以下のような形式で取得できています。(実際は " がエスケープされて文字列として登録されています。)

{
  "fileName": "Reserved_ImageAttachment_[5]_[Image][43]_[コルネ(アリスメイド)_Advanced2023-07-26_01-35-46.234][1]_[1].png"
}

これでImage列に登録されている情報を取得することができましたが、見てもらった通り登録されているのは画像ファイルの名前だけなんですね。

なのでここから画像ファイルの実態が保存されている添付ファイル列から画像ファイルを取得してくる必要があります。

Power Automateで添付ファイルの情報を取得する場合、

  1. 「添付ファイルの取得」アクションで添付ファイルの一覧を取得
  2. 「添付ファイルのコンテンツの取得」アクションでファイルのコンテンツ情報を取得

で取得してあげる必要があります。

まず「添付ファイルの取得」アクションで特定のアイテムの添付ファイルの一覧を取得します。

Image列が1つかつ、添付ファイル列にファイルが登録されていない場合、添付ファイルは一つしかないですが、そうでない場合、添付ファイル列に登録されているファイルは複数あります。

これのうち、どれが対象のImage列に紐づいている画像ファイルなのか?を特定してあげる必要があります。

これには「アレイのフィルター処理」アクションを利用します。

フィルタ条件としては、Image列に登録されている画像ファイルの名前でフィルタしてあげればいいですね。

ということで以下のように設定します。

From

@{body('添付ファイルの取得')}

Filter Query

@equals(@{item()?['DisplayName']},@{json(body('SharePoint_に_HTTP_要求を送信します')?['d']?['Image'])?['fileName']})

気を付けるべき点は、右辺の式ですね。

@{json(body('SharePoint_に_HTTP_要求を送信します')?['d']?['Image'])?['fileName']}

先ほどもちらっと記載したように、Image列の情報は " が / でエスケープされたJSON形式、つまりテキスト形式で保持されています。

このままでは、Power Automateはテキストとして処理してしまいます。

そのままの情報で "fileName" を参照してもエラーになってしまう。ということですね。

なので json 関数を利用してJSON形式に変換してから "fileName" を参照する必要があります。

最後に「添付ファイルのコンテンツの取得」アクションで画像ファイルのコンテンツ情報を取得してあげます。

ファイル識別子

@{body('アレイのフィルター処理')?[0]?['Id']}

これでImage列に登録された画像ファイルのコンテンツ情報を無事取得することができました。

ちなみに、上記のような文字列は以下で組み立てることが可能です。

data:@{body('添付ファイルのコンテンツの取得')?['$content-type']};base64,@{body('添付ファイルのコンテンツの取得')?['$content']}

これまでの流れをスクショするとこんな感じになります。

Image列に画像を登録する

Image列に画像を登録する際は、画像ファイルの実態は添付ファイル列にあるので

  1. 添付ファイルの作成
  2. Image列に添付ファイルに登録されたファイルの紐づけ

としてあげる必要があります。

ただし、添付ファイルを追加する「添付ファイルの作成」アクションでは追加するアイテムのIDを指定する必要があるため、先に「項目の作成」アクションを実行する必要があります。

今回、画像ファイルは事前にドキュメントライブラリに保存しておいてその画像を使うようにします。

先に全体像を共有しておくとこんな感じになります。

重要なのは「変数を初期化する」以降ですね。

「添付ファイルの追加」アクションから一応解説します。

「添付ファイルの追加」アクションでは、「項目の作成」アクションで作成されたアイテムID、および登録したい画像ファイルの情報を設定します。

ID

@{body('項目の作成')?['ID']}

ファイル名

@{outputs('パスによるファイル_メタデータの取得')?['body/DisplayName']}

ファイル コンテンツ

@{body('パスによるファイル_コンテンツの取得')}

続いて、Image列に登録するための情報を作成します。

前項でImage列の情報を取得したときに得られたような "fileName" の形式ですね。

Value

{\"fileName\":\"@{outputs('添付ファイルの追加')?['body/DisplayName']}\"}

あとはこの情報をもとにアイテムの更新を行います。

ただし、標準アクションではImage列の操作はできないのでHTTP要求で行います。

方法

POST

URI

_api/web/lists/GetByTitle('OperateImage4PowerAutomate')/items(@{body('項目の作成')?['ID']})

ヘッダー

{
  "Accept": "application/json;odata=verbose",
  "Content-Type": "application/json;odata=nometadata",
  "If-Match": "*",
  "X-HTTP-Method": "MERGE"
}

ボディ

{
  "Image": "@{variables('ImageValue')}"
}

これでImage列に画像ファイルが登録できました!

なお、このやり方で画像を登録した場合添付ファイル列の画像が見えてしまいます。
リストから画像を追加した場合、添付ファイルに画像ファイルは表示されないのですが、このやり方だと見えてしまいます。

リストから登録した場合

フローから登録した場合

Image列用のAPIが作成されるか、それか現状添付ファイル列の情報をみてもそれっぽい設定項目がないですが、添付ファイル列、もしくはImage列になんらかの情報がみつかればうまいこと登録できるようになりそうですね。

おわりに

更新と削除の方法はまた今度時間があるときに記載しようと思いますー

Power Appsに新しく追加された関数"ColumnNames", "Column"関数を使って異なるスキーマが設定されたJSONをテーブル形式で表示させる

はじめに

Power Appsで最近 ColumnNames 関数と Column 関数が追加されました。

learn.microsoft.com

※まだ日本語のドキュメントは展開されていないようです。

でたばかりの頃は、Power Appsのバージョンを変更しないと使えない関数でしたが、今新規作成されたアプリの作成バージョンは"3.24015.12"になっているかと思いますので、特にバージョン変更など必要なく使えるようになっているかと思います。

ColumnNames 関数

ColumnNames 関数は型付けされていない(UnTypedObject) レコードの列名を返します。

ここで注意しなくてはいけないのは、

  • 型付けされていない必要があること
  • レコードであること

の2点です。

まずは使い方を見てみましょう。
公式ドキュメントの通りですが以下のように利用します。

ColumnNames(ParseJSON("{ ""name"": ""Seattle"", ""population"": 737000 }"))

設定したJSONには "name" と "population" の2つがありますね。

{
  "name": "Seattle",
  "population": 737000
}

なのでこれら2つの列名が返ってきます。

続いて型が指定されている(わかっている)レコードを設定してみます。

ColumnNames({name: "Seattle", population: 737000})

無効な引数で、UntypedObjectを設定するように。とのエラーがでましたね。

このようにこちらの関数はUntypedObjectな結果を解析する際に利用する関数となっています。

つまりParseJSON関数と組み合わせて利用する関数ということですね。

ParseJSON関数に関しては以下の公式ドキュメントや、私が以前記載した記事を参考にしてみてください。

learn.microsoft.com

koruneko.hatenablog.com

さて、もう一つの気を付けるべき点ですがレコードを設定する必要があるということです。

例えば以下のようなObject形式のデータを設定してみます。

[
  {
    "name": "Seattle",
    "population": 737000
  }
]
ColumnNames(ParseJSON("[{ ""name"": ""Seattle"", ""population"": 737000 }]"))

引数が正しくないとエラーがでていますね。

このようなObject形式のデータを設定する必要がある場合はFirst関数などでレコードに変換してあげる必要があります。

ColumnNames(First(ParseJSON("[{ ""name"": ""Seattle"", ""population"": 737000 }]")))

また、JSON内にあるObject形式のデータの列名は現時点では取得できないようです。

TextInput1.Text

{
    "name": "Seattle",
    "population": 737000,
    "point": {
        "type": "Point",
        "coordinates": [
            47.67053604,
            -122.12073517
        ]
    }
}

Column 関数

Column 関数は型付けされていない(UnTypedObject) レコード内の特定の列の値を返します。

ここで注意しなくてはいけないのは、

  • 型付けされていない必要があること
  • レコードであること

の2点です。

まずは使い方を見てみましょう。
公式ドキュメントの通りですが以下のように利用します。

Column(ParseJSON("{ ""name"": ""Seattle"", ""population"": 737000 }"), "name")

設定したJSONには "name" と "population" の2つがありますね。

{
  "name": "Seattle",
  "population": 737000
}

そのうち"name"を指定していますので、"Seattle"が返ってきます。
なお、このままでは型指定していないので、UntypedObjectになっています。

これをちゃんと型設定する場合は以下のようにする必要があります。

Text(Column(ParseJSON("{ ""name"": ""Seattle"", ""population"": 737000 }"), "name"))

Value(Column(ParseJSON("{ ""name"": ""Seattle"", ""population"": 737000 }"), "population"))

"name"はText型なのでText関数で、"population"は数値型なのでValue関数で型指定している感じですね。
それらにあった型で関数を使い分ける必要があります。

なお最初に示した例のように現在ではUnTypedObjectでもラベルに設定すれば自動で型推測して値を表示してくれます。

続いて型が指定されている(わかっている)レコードを設定してみます。

Column({name: "Seattle", population: 737000}, "name")

無効な引数で、UntypedObjectを設定するように。とのエラーがでましたね。

このようにこちらの関数はUntypedObjectな結果を解析する際に利用する関数となっています。

つまりParseJSON関数と組み合わせて利用する関数ということですね。

ParseJSON関数に関しては以下の公式ドキュメントや、私が以前記載した記事を参考にしてみてください。(再放送)

learn.microsoft.com

koruneko.hatenablog.com

さて、もう一つの気を付けるべき点ですがレコードを設定する必要があるということです。

例えば以下のようなObject形式のデータを設定してみます。

[
  {
    "name": "Seattle",
    "population": 737000
  }
]
ColumnNames(ParseJSON("[{ ""name"": ""Seattle"", ""population"": 737000 }]"))

引数が正しくないとエラーがでていますね。

このようなObject形式のデータを設定する必要がある場合はFirst関数などでレコードに変換してあげる必要があります。

Column(First(ParseJSON("[{ ""name"": ""Seattle"", ""population"": 737000 }]")), "name")

また、JSON内にあるObject形式のデータは現時点では取得できないようです。

TextInput1.Text

{
    "name": "Seattle",
    "population": 737000,
    "point": {
        "type": "Point",
        "coordinates": [
            47.67053604,
            -122.12073517
        ]
    }
}

スキーマが異なるJSON形式のデータをテーブルで表示させる

さて、本題です。

以下のようにJSONデータをPower Apps上でJSONがわからないようなユーザにもわかりやすいようにテーブル形式で表示させる方法についてです。

なお、Object形式のJSONが設定されることを前提としています。

まず例として以下のようなJSONデータを用意します。

[
  {
    "name": "佐藤太郎",
    "age": 22
  },
  {
    "name": "高橋次郎",
    "age": 18
  },
  {
    "name": "田中三郎",
    "age": 21
  }
]

続いてJSONデータから ColumnName 関数と Column 関数を用いて列名とその列のデータを取得します。

Set(jsonData, ParseJSON(JSONTxt.Text));
ClearCollect(jsonKeys, ColumnNames(First(jsonData)));
ClearCollect(
    jsonCol,
    ForAll(
        jsonKeys As name,
        {
            Key: name.Value,
            Value:
                ForAll(
                    jsonData As data,
                    Column(data, name.Value)
                )
        }
    )
)

それぞれ以下のような結果が得られますね。

jsonData

jsonKeys

jsonCol


次にこのデータを表示させるためのコントロールの設定です。

以下のようにギャラリーの中にギャラリーを設定します。

"ParentGallery" が「水平ギャラリー」で "DataGallery" が「垂直ギャラリー」です。

サイズや座標などは各々いい感じに設定してもらうとして、他重要な項目は以下のように設定します。

ParentGallery.Items

jsonKeys

ColumnNameLbl.Text

ThisItem.Value

DataGallery.Items

LookUp(jsonCol, Key = ThisItem.Value, Value)

DataLbl.Text

ThisItem.Value

列数分だけ水平ギャラリーによって横方向に列が増えていき、行数分だけ垂直ギャラリーによって縦方向に行が増えていく。という風な作りですね。

Power Appsで列名を動的に設定できたらよかったんですけどねーーーー

現状そのようなことはできませんので、このようにデータの持ち方と表示方法で工夫しています。

スキーマの異なる他のJSONデータでも試してみます。

[
    {
        "title": "The Great Gatsby",
        "author": "F. Scott Fitzgerald",
        "publication_year": 1925,
        "genre": "Classic Fiction"
    },
    {
        "title": "To Kill a Mockingbird",
        "author": "Harper Lee",
        "publication_year": 1960,
        "genre": "Southern Gothic"
    },
    {
        "title": "1984",
        "author": "George Orwell",
        "publication_year": 1949,
        "genre": "Dystopian Fiction"
    }
]

いい感じに表示できていますね!

おわりに

Power Appsでも生のJSONデータを扱う術が増えてきましたね!

これにより、Power Appsで様々なスキーマAPIの結果を表示/操作することも可能になってきましたねー

2024/02/07時点_【注意喚起】Power Automateでモックテスト(静的な結果)で失敗のケースを実施する場合、フローが利用不能になる場合があるようです

はじめに

この記事は 2024/02/07(水) 時点での検証結果をもとに記載しています。

タイトルの通りです。

2024/02/07(水)時点、Power Automateで"静的な結果"を有効化して、特定のコネクタ(私が再現できた限りでいうとSharePointコネクタ。こちらは要検証が必要。)状態を"Failed"にして特定の操作を行うと、対象のアカウントで既存フローの参照、フローの新規作成が一切行えなくなる事象を確認しました。

これは該当環境だけでなく、すべてのテナントで既存フローの参照、フローの新規作成が一切行えなくなるようでした。

この記事を記載している現在では自力でこの問題を解消する方法を私は発見できていません。。。

恐らくMicrosoftのサポートに依頼して回復してもらうしか方法ないのではないか?と思っています。

こちらの記事と同時にこの問題を報告予定なので、進展があった場合はまた皆さんにもお伝えしようと思います。

モックテスト(静的な結果)とは?

Azure Logic Appのドキュメントになりますが、Power Automateでも概同じです。

learn.microsoft.com

前に私も利用方法などをこちらで紹介していますので、よくわからない方はこちらもご確認ください。

koruneko.hatenablog.com

発生した事象

本問題が発生すると以下のようなエラーが表示されるようになり、既存フローの参照及びフローの作成が一切行えない状態となりました。

また、管理センターからもフローの確認ができなくなります。

その他PowerShellにて

Get-AdminFlow

を実行しても何もかえってこなくなりました。

learn.microsoft.com

正直現時点では手詰まり感が半端ないです。

この事象が発生する操作

恐らく問題ないと思われる操作

あくまで恐らくです。
条件が正確に特定できていませんので、この操作をしても上記の事象が発生する恐れがあります。

試される際は自己責任でお願いします。

"Office 365 Users"コネクタの"マイ プロフィールの取得 (V2)"にて"静的な結果"を有効化して、"状態"を"Failed"にします。

この状態で保存すると以下のようなエラーが発生します。

要求コンテンツが無効なため、逆シリアル化できませんでした: 'Required property 'code' not found in JSON. Path 'properties.definition.staticResults['マイプロフィールの取得(V2)0'].error', line 1, position 1144.'。

続いてJSON編集により以下のように設定します。

この状態で保存すると以下のようなエラーが発生しますね。

フローの保存がコード 'InvalidRequestContent' およびメッセージ 'The request content is not valid and could not be deserialized: 'Error converting value "AuthenticationFailed" to type 'Microsoft.Azure.Workflows.Common.ErrorResponses.ErrorResponseCode'. Path 'properties.definition.staticResults['マイプロフィールの取得(V2)0'].error.code', line 1, position 922.'.' で失敗しました。

続いて以下のように修正します。

この状態で保存しても設定に問題はないのでエラーは発生せず、正常に保存ができます。

これを実行すると、こちらのアクションは失敗して、エラーメッセージとして"Unknown error"が返ってきます。

想定通りの動作ですね。

問題が発生する操作

これ以外にも問題が発生する可能性は十分にありますのでご注意ください。

続いて"ProblemFlow"というフローを新規作成します。
この時点では問題の操作をしていないのでフローを確認することができます。

"SharePoint"コネクタの"項目の取得"アクションにて、以下のように"静的な結果"を有効化して設定します。

この状態でフローを保存すると以下のようなエラーが発生します。

Azure Resource Manager で内部サーバー エラーが発生しました。追跡 ID は '667e71c8-5340-4839-af04-2a4ab991f9f1' です。

恐らくこのエラーが発生した時点でアウトです。

フローはエラーが発生して保存できないので、保存せずに戻るなどします。

そしてフロー一覧画面を表示すると以下のようなエラーが表示されます。

JP

AzureResourceManagerServerError

Azure Resource Manager で内部サーバー エラーが発生しました。追跡 ID は '651453d2-2df8-46e6-8318-a3ba40a8ee18' です。

EN

AzureResourceManagerServerError

Encountered internal server error from Azure Resource Manager. The tracking Id is '2d04befb-141b-4836-94d7-755dc886ab49'.

管理センターにアクセスしてフローを確認しようとすると、以下エラーがでます。

(これはこのエラーを発生させる前に一度コマンドを実行していたおかげで実行できただけかもしれませんが、)このエラーが発生したあとに、PowerShellにて Get-AdminFlow でフローの取得をしてみます。

> Get-AdminFlow

FlowName         : 20b0221d-787e-441d-8318-64b7362cd7d5
Enabled          : True
DisplayName      : ProblemFlow
UserType         :
CreatedTime      : 2024/02/07 11:30:45
CreatedBy        : @{tenantId=d*******-****-****-****-************; objectId=d*******-****-****-****-************; userId=d***
                   c***-****-****-****-************; userType=ActiveDirectory}
LastModifiedTime : 2024/02/07 11:44:27
EnvironmentName  : 0*******-****-****-****-************
WorkflowEntityId :
Internal         : @{name=20b0221d-787e-441d-8318-64b7362cd7d5; id=/providers/Microsoft.ProcessSimple/environments/0*******-**
                   **-****-****-************/flows/20b0221d-787e-441d-8318-64b7362cd7d5; type=Microsoft.ProcessSimple/environm
                   ents/flows; properties=}

FlowName         : 32c23207-ce55-4a72-af74-c3ae372de416
Enabled          : True
DisplayName      : My First Flow
UserType         :
CreatedTime      : 2024/02/07 11:22:47
CreatedBy        : @{tenantId=d*******-****-****-****-************; objectId=d*******-****-****-****-************; userId=d***
                   c***-****-****-****-************; userType=ActiveDirectory}
LastModifiedTime : 2024/02/07 11:24:59
EnvironmentName  : 0*******-****-****-****-************
WorkflowEntityId :
Internal         : @{name=32c23207-ce55-4a72-af74-c3ae372de416; id=/providers/Microsoft.ProcessSimple/environments/0*******-**
                   **-****-****-************/flows/32c23207-ce55-4a72-af74-c3ae372de416; type=Microsoft.ProcessSimple/environm
                   ents/flows; properties=}

一応環境の情報などは '*' でマスクして表示しています。

"ProblemFlow"が問題のフローですので Remove-AdminFlow で削除をしてみます。

learn.microsoft.com

> Remove-AdminFlow -EnvironmentName 0*******-****-****-****-************ -FlowName 32c23207-ce55-4a72-af74-c3ae372de416

Code        : 200
Description : OK
Headers     : {[Date, System.String[]], [Strict-Transport-Security, System.String[]], [x-ms-islandgateway, System.Strin
              g[]], [x-ms-request-id, System.String[]]}
Error       :
Errors      :
Internal    :

削除成功したらしいです。

その後 Get-AdminFlow を再度実行してみます。

> Get-AdminFlow
>

なにも返ってこないです。。。

もう一度Power Automateを開きなおしてみますが同様のエラーが発生し続けています。

この状態でフローを新規作成してみます。

Azure Resource Manager で内部サーバー エラーが発生しました。追跡 ID は '976927c4-1652-46e9-b10c-d14bf33aac17' です。

保存ができない。。。

これは接続情報を利用しないようなフローでも同様の問題が発生します。

また、クラシックデザイナーでも同様です。

おわりに

同様の問題が発生している方へ、そしてこの操作を行ってしまって同様の問題が発生してしまわないようにするための情報共有としてこちらの記事をまとめさせていただきました。

追加情報がわかり次第また追記していきます。

同様の問題が発生して解決された方などいらっしゃいましたら情報共有していただけますと幸いです。

Power Appsでアプリ起動時に定数を作成したい場合はApp.OnStartよりApp.Formulasを利用しよう!

はじめに

昨日X(旧: Twitter)でも投稿しましたが、Power Appsでは App.OnStart に処理を記載するより App.Formulas に処理を記載したほうがパフォーマンスが良いです。

公式ドキュメントでも言及されていますが、OnStartプロパティは、アプリ読み込み時にパフォーマンスの問題を引き起こすことがあります。

learn.microsoft.com

一番わかりやすいのがアプリの読み込みに掛かる時間ですね。

あとは(最近は発生しないのかもですけど、)私が昔やってたころは、OnStartに処理書きすぎて一部読み込まれずに画面読み込まれて表示されちゃったせいでアプリがうまく動作しない!
なんてことがありましたね。(さすがにこれは改善されてそうな気がしますけど)

Formulasプロパティの使い方はこちらです。

learn.microsoft.com

  終
制作・著作
━━━━━
 ⓀⓇⓃ

とここで終わってもブログにわざわざ書く意味もないので、使い方や比較をこの記事では紹介しようと思います。

比較用アプリ

以下のようなアプリを作成します。

どちらもOnStart、Formulasでユーザ情報、ギャラリー内で表示しているカラーパレットを定義して画面に表示させるようにしています。

あくまでもOnStartとFormulasの比較なので、これらのプロパティ以外は全く同じ構成にしています。

初期変数の定義

ユーザ情報は "UserInfo" に、
カラーパレットの情報は "myRandColors" に、
それぞれ設定したいと思います。

ユーザ情報には、"Office365ユーザー"コネクタの"MyProfileV2"アクション及び、"UserPhotoV2"アクションで取得した情報を設定します。

カラーパレットには、500件のカラー情報と、座標情報、その他GUIDや実行したときの時間を設定します。

座標情報を入れているのは、画面に表示させているギャラリーが"TemplateSize = 0"の手法を用いて設定しているからです。

OnStart

上記の要件をOnStartプロパティで定義すると以下のようになります。

OnStart

Set(
    UserInfo,
    AddColumns(
        Office365ユーザー.MyProfileV2(),
        "Photo",
        Office365ユーザー.UserPhotoV2(ThisRecord.id)
    )
);
ClearCollect(
    myRandColors,
    ForAll(
        Sequence(500) As i,
        With(
            {
                red: RandBetween(0, 255),
                green: RandBetween(0, 255),
                blue: RandBetween(0, 255)
            },
            {
                index: i.Value,
                guid: GUID(),
                now: Now(),
                rgba: RGBA(ThisRecord.red, ThisRecord.green, ThisRecord.blue, 1),
                hex: $"#{Dec2Hex(ThisRecord.red)}{Dec2Hex(ThisRecord.green)}{Dec2Hex(ThisRecord.blue)}",
                x: 52 * Mod(i.Value - 1, 25),
                y: 30 * Int((i.Value - 1) / 25),
                width: 52,
                height: 30
            }
        )
    )
)

Formulas

続いてFormulasプロパティで書き直すと以下のようになります。

Formulas

UserInfo = 
    AddColumns(
        Office365ユーザー.MyProfileV2(),
        "Photo",
        Office365ユーザー.UserPhotoV2(ThisRecord.id)
    );
myRandColors =
    ForAll(
        Sequence(500) As i,
        With(
            {
                red: RandBetween(0, 255),
                green: RandBetween(0, 255),
                blue: RandBetween(0, 255)
            },
            {
                index: i.Value,
                guid: GUID(),
                now: Now(),
                rgba: RGBA(ThisRecord.red, ThisRecord.green, ThisRecord.blue, 1),
                hex: $"#{Dec2Hex(ThisRecord.red)}{Dec2Hex(ThisRecord.green)}{Dec2Hex(ThisRecord.blue)}",
                x: 52 * Mod(i.Value - 1, 25),
                y: 30 * Int((i.Value - 1) / 25),
                width: 52,
                height: 30
            }
        )
    );

Formulasプロパティで式を記載する場合は、

<変数名> = <式>

のようになります。

あとはだいたい同じですね。

アプリ内で変数を利用する

OnStart

まずはOnStartでの利用方法です。
といっても普通のグローバル変数とコレクションの利用なので難しいことはないですね。

ユーザの画像を表示

Image.Image

UserInfo.Photo

ユーザの名前を表示

Label.Text

UserInfo.displayName

コレクション内で最も大きい時間最も小さい時間の差を表示

Labl.Text

$"DateDiff: {DateDiff(Max(myRandColors, now), Min(myRandColors, now))}"

カラーパレットの表示

Gallery.Items

myRandColors

Label.Text

ThisItem.hex

Label.X

ThisItem.x

Label.Y

ThisItem.y - (ThisItem.index - 1)

Label.Width

ThisItem.width

Label.Height

ThisItem.height

Formulas

続いてFormulasで宣言した変数の利用方法です。

ユーザの画像を表示

Image.Image

UserInfo.Photo

ユーザの名前を表示

Label.Text

UserInfo.displayName

コレクション内で最も大きい時間最も小さい時間の差を表示

Labl.Text

$"DateDiff: {DateDiff(Max(myRandColors, now), Min(myRandColors, now))}"

カラーパレットの表示

Gallery.Items

myRandColors

Label.Text

ThisItem.hex

Label.X

ThisItem.x

Label.Y

ThisItem.y - (ThisItem.index - 1)

Label.Width

ThisItem.width

Label.Height

ThisItem.height

なんと同じ式で利用できるのですね!

OnStartからFormulasへの移行もスムーズに行えることがわかってもらえたかと思います。

実行速度の比較

モニター機能でそれぞれの実行時間をみてみましょう!

OnStart

Formulas

Formulasの方が圧倒的に処理速度が速いですね!

より多くの処理や複雑な処理、時間の掛かる処理を実行する場合などはより顕著に差が表れると思います。

Formulasプロパティを利用するにあたって理解しておくこと

ドキュメントで利点として記載されていること、および制限事項を理解しておくといいですかね。

名前付き計算式を使用する利点は次のとおりです。

  • 数式の値は常に利用可能です。 タイミング依存関係も、値が設定される前に最初に実行する必要のある OnStart もなく、式の値が不正確になる時間もありません。 名前付き計算式は、循環参照を作成しない限り、任意の順序で相互に参照できます。 それらは並行して計算できます。
  • 数式の値は常に最新です。 数式は、コントロール プロパティまたはデータベース レコードに依存する計算を実行でき、それらが変更されると、数式の値が自動的に更新されます。 変数の場合のように値を手動で更新する必要はありません。 また、数式は必要な場合にのみ再計算されます。
  • 式の定義は不変です。 数式の定義は信頼できる唯一の情報源であり、アプリ内の他の場所で値を変更することはできません。 変数を使用すると、一部のコードが予期せず値を変更する可能性がありますが、名前付きの数式ではこれは不可能です。
  • 数式の計算は延期できます。 値は不変であるため、必要なときにいつでも計算できます。つまり、必要になるまで計算する必要はありません。 アプリのスクリーン 2 まで使用されない数式の値はスクリーン 2 が表示されるまで計算する必要はないと表示されます。 これにより、アプリの読み込み時間を改善できます。 名前付き計算式は宣言型であり、システムが計算方法とタイミングを最適化する機会を提供します。
  • 名前付き計算式は Excel の概念です。 非常に多くの人が Excel をよく知っているので Power Fx は可能な限り Excel の概念を使用します。 名前付き計算式は、名前マネージャーで管理される Excel の名前付きセルおよび名前付き計算式と同等です。 コントロール プロパティと同じように、スプレッドシートのように自動的に再計算されます。

名前付き計算式のいくつかの制限:

  • 動作関数を使用したり、アプリ内で副作用を引き起こしたりすることはできません。
  • 循環参照を作成することはできません。 a = b; と b = a; を同じアプリ内で持つことは許可されていません。

利点として述べられている、値が不変な点と動作関数やアプリ内で副作用を起こすことができない。
という点が特に注意ですかね。

つまり現状OnStartプロパティに記載されていた内容すべてをFormulasプロパティに移植できるわけではありません。

じゃあどうすればいいか?というと、個人的には初回起動画面のOnVisibleに記載することをおすすめします。

要件によっては、初回ロード画面なんてものを作るのもありじゃないですかね?

おわりに

皆さんもOnStartプロパティは卒業して、Formulasプロパティの利用にシフトしましょう!


スポンサードリンク