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

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

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プロパティの利用にシフトしましょう!

Power Appsで住所入力フォームを作成する

はじめに

Power Appsで簡単にかつ、表記揺れ少なく住所の登録を行うとしたらどういう方法があるかな?
とちょっと考えてみたので、いくつか案を記載します。

もっといい案などあればコメント等していただけると嬉しいです!

入力想定

入力想定としてはこんな感じ。

よくある郵便番号を入力したら、その結果をもとに都道府県、市区町村、町名までの入力を補完してくれるやつです。

郵便番号から住所を検索する

Bing Mapsコネクタの利用

Power PlatformのコネクタにはBing Mapsコネクタがあります。

learn.microsoft.com

こちらは標準コネクタなので追加のライセンスなしで利用することができます。

ただし利用にはAPI Keyが必要になります。

API Keyの発行はこちらで行うことができます。

www.bingmapsportal.com

とりあえず開発目的で試してみるだけでしたら無料で発行することが可能です。

今回郵便番号から検索を行いたいので「住所で場所を取得する(GetLocationByAddress)」を利用します。

例えば以下のように取得することできますね。

BingMaps.GetLocationByAddress({postalCode:Form1.Updates.部屋番号,countryRegion:"JP"})

今回欲しい(と思われる)情報はaddressにあるので以下のように取得します。

UpdateContext({getAddress: BingMaps.GetLocationByAddress({postalCode:Form1.Updates.部屋番号,countryRegion:"JP"}).address})

とりあえず日本マイクロソフト本社がある住所で試してみました。

その結果はこちらです。

うーーん。。。

一応参考までに.addressを指定せずに生の値をそのまま取得した場合はこちらになります。

欲しい情報とれてないですねー。。。

ということで、このコネクタを利用することでは今回の目的は達成できなさそうです。

ちなみにこれ、日本だからできないのかな?と思いましたが、USでもなんか上手く動いてないっぽい?

国コードを"US"に変更して、Microsoft US本社の住所で検索してみます。

UpdateContext({getAddress: BingMaps.GetLocationByAddress({postalCode:Form1.Updates.部屋番号,countryRegion:"US"})})

結果はこちら

うーん。残念!

ちなみにこちらのAPIの元になっていると思われるこちらのAPIを実行した場合の結果も参考までに以下で載せておきます。

learn.microsoft.com

日本Microsoftの郵便番号で検索

url

https://dev.virtualearth.net/REST/v1/Locations/JP/1080075?o=json&key={BingMapsKey} 

Result

{
  "authenticationResultCode": "ValidCredentials",
  "brandLogoUri": "https://dev.virtualearth.net/Branding/logo_powered_by.png",
  "copyright": "Copyright © 2024 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
  "resourceSets": [
    {
      "estimatedTotal": 1,
      "resources": [
        {
          "__type": "Location:http://schemas.microsoft.com/search/local/ws/rest/v1",
          "bbox": [
            35.623119354248047,
            139.7376708984375,
            35.6387825012207,
            139.7593994140625
          ],
          "name": "108-0075, Japan",
          "point": {
            "type": "Point",
            "coordinates": [
              35.63023758,
              139.74839783
            ]
          },
          "address": {
            "countryRegion": "Japan",
            "formattedAddress": "108-0075, Japan",
            "locality": "Tokyo",
            "postalCode": "108-0075"
          },
          "confidence": "High",
          "entityType": "Postcode1",
          "geocodePoints": [
            {
              "type": "Point",
              "coordinates": [
                35.63023758,
                139.74839783
              ],
              "calculationMethod": "Rooftop",
              "usageTypes": [
                "Display"
              ]
            }
          ],
          "matchCodes": [
            "Good"
          ]
        }
      ]
    }
  ],
  "statusCode": 200,
  "statusDescription": "OK",
  "traceId": "26207454a1105398697042f88fe1c17b|PUS000DE1E|0.0.0.1|Ref A: 112EC9BA7E5642DAAAC907663DE1764B Ref B: SEL20EDGE0205 Ref C: 2024-01-30T17:47:30Z"
}

US Microsoftの郵便番号で検索

url

http://dev.virtualearth.net/REST/v1/Locations/US/98052?o=json&key={BingMapsKey}

Result

{
  "authenticationResultCode": "ValidCredentials",
  "brandLogoUri": "https://dev.virtualearth.net/Branding/logo_powered_by.png",
  "copyright": "Copyright © 2024 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
  "resourceSets": [
    {
      "estimatedTotal": 1,
      "resources": [
        {
          "__type": "Location:http://schemas.microsoft.com/search/local/ws/rest/v1",
          "bbox": [
            47.626979827880859,
            -122.16493225097656,
            47.734012603759766,
            -122.07723236083984
          ],
          "name": "98052, WA",
          "point": {
            "type": "Point",
            "coordinates": [
              47.67053604,
              -122.12073517
            ]
          },
          "address": {
            "adminDistrict": "WA",
            "adminDistrict2": "King County",
            "countryRegion": "United States",
            "formattedAddress": "98052, WA",
            "locality": "Redmond",
            "postalCode": "98052"
          },
          "confidence": "High",
          "entityType": "Postcode1",
          "geocodePoints": [
            {
              "type": "Point",
              "coordinates": [
                47.67053604,
                -122.12073517
              ],
              "calculationMethod": "Rooftop",
              "usageTypes": [
                "Display"
              ]
            }
          ],
          "matchCodes": [
            "Good"
          ]
        }
      ]
    }
  ],
  "statusCode": 200,
  "statusDescription": "OK",
  "traceId": "a455e74cba328865371503122ff44e28|PUS000DE25|0.0.0.1|Ref A: 24130242C72E483CACE4E5068CCC4967 Ref B: SEL20EDGE0405 Ref C: 2024-01-30T17:51:47Z"
}

仮にこちらのAPIを用いてカスタムコネクタを自作しても、日本語の住所は取れなさそうですので日本向けに利用することを考えると、ちょっと微妙ですかね。。。

郵便番号APIサービスからカスタムコネクタを作成する

郵便番号検索APIサービスを利用してカスタムコネクタを作成し、それを用いて郵便番号から住所の検索を行ってみます。

今回は"zipcloud"というサービスを利用してみようと思います。

zipcloud.ibsnet.co.jp

選定理由は無料で使えて、またリクエストやレスポンスがシンプル、欲しい情報が取れそう。というだけですので、もちろん他にもいいサービスはあるとは思います。
これじゃなきゃダメってわけじゃないですよ。

カスタムコネクタを作成する

  1. 「カスタムコネクタの新規作成」より「一から作成」を選択します。
  2. 適当なコネクタ名を入力します。
  3. ドキュメントより、ベースとなるURLは以下のように記載されています。

    ベースとなるURLは以下になります。
    https://zipcloud.ibsnet.co.jp/api/search
    このURLにリクエストパラメータを加え、リクエストを行います。

  4. ということで以下のように設定します。
  5. こちらのAPIは認証情報を特に必要としないので、続いて定義を作成します。

  6. 最後に接続情報を作成した後にテストをしましょう。

アプリから呼び出す

あとは、こちらのコネクタをアプリに追加して使ってみます。

UpdateContext({searchAddress: zipcloud.SearchAddress({zipcode: Form1.Updates.郵便番号}).results})

結果はこんな感じ

いい感じに取得できてますねー

おまけ

Microsoft Listには列の種類で「場所」というものがあります。

ここに郵便番号を入力すると、候補がでてきます。

どれ選べばいいんだ...?

まず上の北品川を選んだ場合

北品川区ってどこですか...?というか日本Microsoftは品川区にあった...?

続いて港南

港南は区ではないですね。おしい。

続いて最後

ダメな気がしましたがダメですね!

ちなみにこちらPower Appsから更新することはできません。

おわりに

現状Power Appsで日本の住所検索を行う場合は外部APIを利用するのが一番欲しい結果が得られそうですね。

【Power Apps】Preview機能で追加されたユーザー定義関数(UDF)を試してみる

はじめに

Power AppsのPreview機能にユーザー定義関数(UDF)が追加されました!

今回はこちらのユーザー定義関数について記載しています。

なおまだPreview機能ですので、今後変更になる可能性があります。

前提条件

こちらのユーザー定義関数を利用するには、Power Appsの作成バージョンが"3.24013.14"以上である必要があります。

設定 > サポート > 作成バージョン
より、変更が可能です。

また、ユーザー定義関数を利用するためには、"新しい分析エンジン"も有効化する必要があります。

こちらは
設定 > 近日公開の機能 > 試験段階
より、有効化することができます。

"ユーザー定義関数"も同様に
設定 > 近日公開の機能 > 試験段階
から有効化できます。

有効化後アプリを再読み込みする必要があります。

ユーザー定義関数の使い方

ユーザー定義の作成方法

ユーザー定義関数は"App"の Formulas に記載します。

関数を作成する際は、以下のような構文で作成します。

<関数名>(<パラメータ名>:<パラメータの型>):<関数の型> = ;

実際の例を見てもらった方がわかりやすいかもです。

ということで以下DAX関数にある PDURATION 関数を作成します。

learn.microsoft.com

この関数は以下のような財務関数です。

投資が指定された値に到達するまでに必要な期間数を返します。

早速作成してみると、以下のようになります。

PDURATION(rate:Number, pv:Number, fv:Number):Number = (Log(fv) - Log(pv)) / Log(1 + rate);

式の最後にはセミコロン";"が必要な点に注意してください。

"型"に指定可能な型の種類は現在10種類あります。

テーブルやレコードは指定できないようですね。

ユーザー定義関数を利用する

作成したユーザー定義関数を呼び出す際は以下のように利用します。

PDURATION(0.025, 2000, 2200)

通常の関数利用と同じですね。

Tips

複数のユーザー定義関数の作成

ユーザー定義関数は複数作成することも可能です。

複数のユーザー定義関数を作成したい場合は、セミコロン区切りで作成してあげればよいです。

"UntypedObject"に値を渡す

"UntypedObject" なパラメータに対して値を渡したい場合は ParseJSON 関数を利用します。

learn.microsoft.com

例えば以下のようなユーザー定義関数を作成したとします。

UntypedObject(val:UntypedObject):Number = val;

パラメータの "val" を "UntypedObject" に指定しています。

この関数に対して、普通に(?)値を渡すと以下のような型エラーが発生します。

現在Power AppsでUntypedObject型の値を作成するには ParseJSON 関数を利用する必要があります。

これで "UntypedObject" に対して値を渡すことができるようになります。

Table型のデータを渡す

先ほどの "UntypedObject" を活用すればテーブルも渡すことができます。

以下のような式を記載することで、"UntypedObject" であるが中身としてはテーブル形式のデータを作成することができます。

ParseJSON("[3, 2, 6, 6, 4, 5]")

このようにすればテーブル型のデータもユーザー定義関数に含めることができます。

例えば以下のような中央値を求めるユーザー定義関数をみてみましょう。

Median(values:UntypedObject):Number = 
Index(
    Sort(
        ForAll(
            Table(values),
            Int(ThisRecord.Value)
        ),
        Value
    ),
    RoundUp(CountRows(Table(values)) / 2, 0)
).Value;

上記のように受け取った値を Table 関数を利用して、Table型に変換してあげればTableデータも利用できるようになります。

ただし、これで型変換を行っても中の値は "UntypedObject" のままなので注意してください。
この制限があるので、Sortを行う前にForAllでテーブル内の値に対して型を明示的に設定しているわけです。

できないこと

式には動作関数を含めることができません。

例えば Patch 関数や Collect 関数などは設定できないということですね。

カスタムコンポーネントとの違い

Power Appsでは以前からカスタムコンポーネントでプロパティの型に関数を指定することでカスタム関数を作成することができました。

learn.microsoft.com

カスタムコンポーネントってなに?という方は去年の資料なのでちょっと古いですが、M365VMで登壇した資料をみてみてください。

www.docswell.com

ユーザー定義関数とカスタムコンポーネントの違いを書き出すと以下ですかね。

データ型

パラメータに利用できるデータ型の種類に差異があります。

ユーザー定義関数

カスタムコンポーネント

ユーザー定義関数は返される値のデータ型とパラメータに設定可能なデータ型が同じなのに対し、カスタムコンポーネントは異なります。("画面"が増えてる)

ユーザー定義関数

カスタムコンポーネント

パラメータの設定方法

カスタムコンポーネントでは以下のようにパラメータをGUI操作で1つずつ設定していきます。

たいしてユーザー定義関数は式を記載するだけで簡単に設定できます。

まぁ、カスタムコンポーネントの設定方法の方が後から見たときに比較的わかりやすい。という見方もできますけどね。

あとは、カスタムコンポーネントだとパラメータの説明を記載でき、また必須かオプションかも設定が可能です。
対してユーザー定義関数はこれらができません。(まだ実装されていないのか、私がやり方理解できていないだけなのかわかりませんが。。。)

カスタム関数の共有

カスタムコンポーネントコンポーネントを公開して共有すれば、そのコンポーネントの中身を再開発しなくとも、またコンポーネントの中身の処理を理解していなくとも、他のユーザーも利用することができます。

対して、ユーザー定義関数はそもそも共有する術がありません。

共有するとすれば、作成したカスタム関数をコピペで共有するぐらいですね。

おわりに

こちらの機能はPreview機能なので、本番環境で利用する際は自己責任になりますのでご注意ください。

(2024/01/14)Power AppsでSharePoint リスト(Microsoft リスト)の画像列を利用する場合の注意点

はじめに

SharePoint リスト(Microsoft リスト)の画像列の仕様がここ最近変更になりましたね。

変更内容に関してはこちらの記事で紹介していますので、まだ確認されていない方は確認してみてください。

koruneko.hatenablog.com

前の仕様に戻したい方はこちらを試してみてください。

koruneko.hatenablog.com

さて、今回はそんなSharePoint リストの画像列をPower Appsで利用する場合の注意点を追記します。

上記のブログで触れていることは再度は触れないのでご了承ください。

Power Appsからリストに画像を登録できないケースがある

リストの設定

以下のような3種の画像列を用意しました。

  1. 表示名と内部名が同じもの
  2. 日本語でフィールドを作成したもの
  3. 表示名と内部名が異なるもの
内部名 表示名
Image Image
画像 x753b__x50cf
Pic Picture

これらのフィールドに対してPower Appsから画像を登録してみます。

Power Appsから画像列に画像を登録する

さて、それでは画像の登録を行ってみます。

チェックアイコンを選択して SubmitForm を実行します。

SubmitForm(Form1)

その結果は以下のようになりました。

日本語で作成したフィールドだけ画像が登録されていないですね。

ちなみにPower Apps側でみた場合もこのような感じ。

画像列に登録した画像は添付ファイル列に紐づくことになりますが、添付ファイル列には画像ファイルは2枚しか登録されていないですね。

このように、現在(2024/01/14)日本語などの内部名に使用できない名前でフィールドを作成した場合、画像列に画像を登録できないようです。

モニターをみてみる

Power Appsのモニター機能を利用して処理を確認してみましょう。

Power Appsのモニター機能に関しては以前にこちらで紹介していますのでよろしければみてみてください。(後半あたり)

www.docswell.com

公式ドキュメントはこちら

learn.microsoft.com

さて、先ほどの処理(SubmitForm)をモニターでみてみると、1か所失敗している処理があることがわかります。

こちらの処理をみてみると、以下のような応答結果を確認することができます。

どうやら列を特定できてないようですね。

API Management経由で処理が呼ばれているので確かなことはわからないですが、他二つの呼び出し方法をみるに"OData__"で呼び出してるのがダメなんじゃないかな?

回避策

このように、現在(2024/01/14)日本語などの内部名に使用できない名前でフィールドを作成した場合、画像列に画像を登録できないようです。

現時点での回避策としては、フィールド作成時に内部名に使用できる文字列でフィールドを作成してもらって、あとで表示名を変更する。
ですかね。

回避って書いといてなんですが、リストを利用するのであればこのような問題なしにしても、上記のようなやり方でフィールドを作成するように癖をつけた方が良いです。

OData__~~みたいに記載されていても、後から見たとき何の列かわからなくなりますからね。

おわりに

最近色々なところでアップデートきていますが、製品間での整合性やこれまでできたことができなくなっている or 使いにくくなっている。ということがいくつか確認できていますね。(Power Appsに限った話ではなく)

このような不具合や要望は積極的にフィードバックをあげるようにしましょう。

最近ですとフィードバックの甲斐があって(?)、Power Appsの数式バーのサイズが可変に変更できるように戻りましたね。(新しいバージョンでの動作かな)

私もフィードバックちゃんとあげなきゃ。。。

Power Appsで月末の計算が簡単にできるようになりました!

はじめに

Power Fxに EDate 関数と EOMonth 関数が追加されました!

learn.microsoft.com

これによりPower Appsで簡単に月末の計算ができるようになりました。

Power Appsで月末を求める

これまでは

これまではPower Appsで月末を求めようとすると以下のような式で計算する必要がありました。

DateAdd(Date(Year(DatePicker1.SelectedDate), Month(DatePicker1.SelectedDate) + 1, 1), -1)

ちなみに月初めはこちらですね。

Date(Year(DatePicker1.SelectedDate), Month(DatePicker1.SelectedDate), 1)

これからは

しかしこれからはこんな式書かなくとも EOMonth 関数を利用して簡単に月末を求めることができるようになりました!

例えば対象の月の月末を求めたい場合は以下のようになりますね。

EOMonth(DatePicker1.SelectedDate, 0)

EOMonth 関数は第一引数に元となる日付を、第二引数に第一引数に加算する月の数を設定します。

なので対象の日付の月末を求めたい場合は上記のように

// "DatePicker1.SelectedDate"の月末
EOMonth(DatePicker1.SelectedDate, 0)

となり、3か月後の月末だと

// "DatePicker1.SelectedDate"の3か月後の月末だと
EOMonth(DatePicker1.SelectedDate, 3)

となり、5か月前の月末だと

// "DatePicker1.SelectedDate"の月末
EOMonth(DatePicker1.SelectedDate, -5)

となります。

簡単に月末を求められるようになりましたねー

EDate

同時に追加された EDate 関数も一応紹介しておきます。

こちらは第一引数に指定した日付に、第二引数で指定した月を加算した結果を返します。

これにより加算された結果は月末を超えない限りは日付の箇所は変更されません。
例えば、7月31日に1か月加算すると、6月30日になります。

EDate(Date(2024, 1, 31), 1)

上記に結果は "2024/02/29" となります。

EDate(Date(2024, 1, 31), 2)

上記に結果は "2024/03/31" となります。

EDate(Date(2024, 1, 31), 3)

上記に結果は "2024/04/30" となります。

EDate(Date(2024, 1, 31), 0)

上記に結果は "2024/01/31" となります。

EDate(Date(2024, 1, 31), -1)

上記に結果は "2023/12/31" となります。

EDate(Date(2024, 1, 30), 2)

上記に結果は "2024/03/30" となります。

EDate(Date(2024, 1, 30), 3)

上記に結果は "2024/04/30" となります。

ただPower Appsでの日付計算に慣れている方はここまでみて気づいたかもしれませんが、これ既存の DateAdd 関数で月を加算したときと同じ動作なんですよね。

DateAdd(Date(2024, 1, 31), 2, TimeUnit.Months)

EDate 関数に関しては、 DateAdd 関数との使い分けがいまいちわからなかったです。。。
どなたか知見のある方いたら、こういうことができるようになったよ!などご教示いただけると幸いです。

おまけ

最近の更新でPower Automate DesktopでもPower Fxを利用できるようになりました。

learn.microsoft.com

そして、 EOMonth 関数はデスクトップフローでも利用することができます。

つまり今回のアップデートにより、PADでも月末の計算が容易になったというわけです。

例えばこんなフローを作成します。

すると、以下のように月末を表示してくれる。というわけですね。

おわりに

Power Fxにはこの関数の他にもいくつか関数が追加されています。

気になった方は是非見てみてくださいねー

learn.microsoft.com

Power Platformのソリューションのインポート時に環境変数が常に表示され、編集できるようになりました

はじめに

Power Platformのソリューションのインポート時及びパイプラインのデプロイ時に、環境変数が表示され、また編集もできるようになりました!

powerapps.microsoft.com

これまではソリューション内で環境変数を利用していた場合、エクスポート前に環境変数の既定の値を削除しないとソリューションインポート時及びパイプラインでのデプロイ時に環境変数の値を変更することができませんでした。

パイプラインのお話でいうとこの前にJPPC2023でお話した資料のP.30がそのことについて触れていますね。

www.docswell.com

以前まではこのように環境変数の既定の値をつけたままマネージドソリューションとしてエクスポートしてしまうと、環境変数が変更しにくくて困る。っていう問題がありました。
(一応既定のソリューション内で無理矢理変更できないこともない)

これが今回のアプデで解消されたってわけですね。

この記事ではその動きを簡単にみていきます。

環境変数の更新

元のソリューションはこのようなオブジェクトを用意しました。

$"CurrentValue: {LookUp('Environment Variable Values', 'Environment Variable Definition'.'Schema Name' = "korune_CurrentValue", Value)}"
$"StayCurrentValue: {LookUp('Environment Variable Values', 'Environment Variable Definition'.'Schema Name' = "korune_StayCurrentValue", Value)}"

環境変数"CurrentValue"は「現在値」をソリューション内から削除して、環境変数"StayCurrentValue"は「現在値」をそのままにしています。

(記事かいているときにタイポしているの気が付いたけど、面倒なのでそのままでw)

ソリューションのインポート時の動き

マネージドソリューションとしてエクスポートしたソリューションファイルをインポートしてみます。

結果以下のようになりました。

環境変数を変更できそうですね。

ただ「現在値」をそのままにしていた方は、この段階でエクスポート時の値が見えてしまっています。

したがって、Publicに公開する際などは公開しては困るような値は現在値から消してからエクスポートするようにしたほうがよさそうです。

続いて環境変数の値をセット、変更してみます。

「現在値」が設定されていた方は「リセット」ボタンが表示されていますね。  

これを選択すると、元の値に戻ります。(「現在値」が設定されていたほうだけ)

一応インポートされたソリューションもみておきます。

ちゃんと変更されていますね!

パイプライン

パイプラインでデプロイをしてみます。

こちらもソリューションインポート時と同様に環境変数の変更ができるようになっていますね。

ただし、「現在値」がそのまま設定されていた環境変数に関しては、値が見えています。

パイプラインは異なるテナントへは対象はできず、同じテナント内の異なる環境を対象にしないといけないので、公開しちゃいけない値を不特定多数に公開しちゃった~なんてインシデントは起こらないとは思いますが、まぁ運用としては変更が必要な値は消しておいて、任意もしくそのままの値を利用する場合は現在値を設定したままにしておく。
というのがいいんじゃないでしょうか?(デプロイ時のミス減るかな?)

パイプラインについては、冒頭で紹介した私のJPPC2023の資料みてみてね。

こちらも同様に「リセット」がありますね。

デプロイされたソリューションはこんな感じ。

パイプラインでのデプロイだと「現在値」がそのままだった場合でも「現在値」見えなくなるんだ?

インポート時と動作に差異があるのが若干気になりますね?
別に困りはしないけど。

おわりに

2023年最後の記事でした!(ギリギリ!)

2024年も引き続き皆様よろしくお願いいたしますー

良いお年をーーーーーー

(2023/12/26時点)SharePointリストの画像列と添付ファイルが紐づかないようにする

はじめに

こちらの記事でも紹介しましたが、最近のアップデートでSharePointリストの画像列に画像を追加したときの内部挙動が変更になりました。

koruneko.hatenablog.com

これまではリストの画像列に画像を追加した場合、画像ファイルは"SiteAssets"(サイトのリソースファイル)配下に作成されていました。
しかし最近のアップデートにより、リストの画像列に追加した画像ファイルは同じレコードの添付ファイル列に紐づくようになりました。

このアップデート自体はリストの運用という面で考えると良いアップデートだと思っています。

しかし、Power AppsをはじめとしたPower Platformとの連携を考えると現状(2023/12/26)手放しで喜べるアップデートとはいえません。

上記記事でも記載していますが、まだPower Apps側がこの更新に対応できていなかったりするからですね。

そこでこの記事では、リストの画像列に画像を追加した場合に添付ファイル列に画像ファイルが紐づくのではなく、"SiteAssets"に紐づくようにするやり方を紹介します。

SharePointリストの画像列と添付ファイルが紐づかないようにする

リストの設定を変更する

やり方はいたって簡単です。

リストの設定から添付ファイル列を無効にするだけです。

  1. リストの設定を開きます
  2. 「詳細設定」を開きます
  3. 「リスト アイテムへのファイルの添付」を「無効」にします
  4. 「OK」を選択して変更を適用します

これでこのリストでは添付ファイルは使えなくなります

添付ファイルが利用できなくなることによって(?)画像ファイルは"SiteAssets"配下に作成されるようになります。

実際に動きを見てみましょう。

まず添付ファイルを無効にしているわけですから、当然「ビューの列の編集」には「添付ファイル」列は見当たりません。

試しに以下のような画像を追加してみます。

画像ファイルを開いてみると以下のようにdrives配下にファイルがあることがわかります。
添付ファイルの配下ではないですね。

比較用に画像列の画像ファイルが添付ファイル列に紐づいていた場合のURLも載せておきます。

"SiteAssets"の配下も確認してみましょう。
その前にリストのIDを確認しておきます。

"a2ca97a5-6e7c-49fa-9fda-4b36441b05de"ですね。

"SiteAssets"(サイトのリソースファイル)を確認してみると、上記リストのフォルダが作成されており、もちろん画像ファイルも作成されていることが確認できます。

以上により、SharePointリストの画像列と添付ファイルが紐づかないようになり、前の仕様である"SiteAssets"配下に画像ファイルが作成されるようになりました。
しかし当然ではありますが、このやり方をしてしまうと添付ファイル列を無効にしているため添付ファイルはこのリストでは利用できなくなります

余談ではありますが、もちろんこのやり方にした場合、リスト側の設定がそもそも変わっているので例えばPower Appsから画像ファイルを更新した場合でも"SiteAssets"配下に画像は作成されます。

おわりに

細かい検証まではできていないので、ご利用は自己責任でお願いします。(今後のアップデートで変な挙動になったりしても責任は取れません。)

(2023/12/23時点)仕様が変わったSharePointリストの画像列をPower Appsで利用してみる

はじめに

この記事は、Power Apps Advent Calendar 2023 12/18 担当分の記事です。

SharePointリストの画像列に画像を追加したときの挙動ですが、(私が確認した限りでは)11/11時点では変更されていました。

恐らくこちらのアップデートに関連した更新なのですが、公式で詳しく説明されているドキュメントは私は見つけられなかったです。
(なんかこれだけ書くと、いかがでしたでしょうか?の情報のない記事みたいになっちゃいますねw)

www.microsoft.com

もし公式での詳しいアナウンスをご存知の方はコメントなどでご教示いただけますと幸いです。

アップデート後の仕様

さて、肝心のアップデート内容です。

何が変わったか?というとアップロードした画像ファイルの保存先です。

これまでは、SiteAssets(サイトのリソースファイル)のListsフォルダ配下に、リストIDの名前で作成されたフォルダ配下にそれぞれ画像が格納されていました。

しかしこれからは既存のリストも含めてSiteAssets配下には画像ファイルは作成されなくなりました。

*注意*
これまで保存していた画像は変わらずSiteAssets配下にあります。

ではどこに保存されるようになったか?というと、その行の「添付ファイル」フィールドに保存されるようになりました。

このアップデートによりリストのデータはリスト内だけで完結できるようになりました。
一々SiteAssetsを参照して~ということや、誤ってSiteAssets内のファイルやフォルダを消してしまうという事故がこれでなくなりましたね。

Power Appsで新しくなった画像列を利用する

画像列にアイテムを登録する

登録はこれまでと同じようにできます。

データソースから作成された新しい方のアプリを例に見てみましょう。

チェックアイコンを押してSubmitFormを行ってみます。

SubmitForm(Form1)

無事登録されましたね。

そして見ていただければわかるかと思いますが、添付ファイルフィールドにはなにも登録していなかったのに、添付ファイルにアイテムがあることがわかりますね。

比較用に添付ファイルなしの場合の行も置いておきます。

ただしこちらの画像列に紐づいた添付ファイルですが、リスト上で編集することはできません。

画像列のアイテムを表示する

画像列のアイテムもこれまでと同じように参照して表示が可能です。

もちろん画像のサイズを指定することもこれまで同様可能です。

気を付けないといけないのは添付ファイル項目です。

リスト上では表示されないようになっていましたが、Power Appsから参照すると普通に表示できます。
またこちらPower Appsから編集もでき、削除もできちゃいます。

削除しちゃうと、画像列は添付ファイルのアイテムを参照しているだけなので画像は表示されなくなります。
ただし、画像列には画像の情報はある...というおかしなデータになっちゃいます。

Note
添付ファイルの画像ファイルを消してもリストではしばらく画像は表示できるかと思います。(多分キャッシュかな?)
ただし画像ファイルを選択して、画像の保存されているリンクを開くと対象のファイルが見つからない旨のエラーが返ってくるかと思います。

Power Appsで見るとこんな感じ。

したがって、ユーザの操作ミスや知識不足による誤操作を避けるためにもアプリで添付ファイル列を表示/編集できるようにする場合は、画像列に紐づいたファイルを表示しないようにする必要があります。

さて、フィルタの方法ですが"Reserved_ImageAttachment"で始まらない添付ファイルのアイテム名でフィルタするしか現状対策はないです。

Power AppsからSharePoint Listに接続して得られる情報、ThisItem.添付ファイルではそれが添付ファイルに紐づいたアイテムなのかを確実に判断する術はありません。

画像列の画像ファイル名から判断する。という手もありますがこれには2つ問題があります。

  1. 画像ファイルのファイル名を取得するのがちょっと面倒
  2. Power Appsから画像ファイルを更新した場合、添付ファイルに前のアイテムが残ったままになる

まず1つ目のファイル名の取得ですがファイル名そのままの形式では取得できません。

このような形式から頑張ってファイル名を取得してあげる必要があります。

詳しいやり方は今回の本筋から離れるので割愛。

続いて2つ目の添付ファイルが残ったままの件ですが、リストから画像ファイルを変更した場合は元々設定されていた画像ファイルも添付ファイルから置き換わってくれます。
ただし、Power Appsから変更した場合は添付ファイル列に元々あった画像ファイルは変更されずに、新規画像ファイルが添付ファイルに登録されます。

画像列の画像の向き先は追加された添付ファイルの画像を向いてくれるので、見た目的には問題ないんですけどね。

さて、そんなわけでPower Appsから画像を5回変更した場合添付ファイル列には、
 新規登録時の画像ファイル1枚 + 画像を変更した回数分の画像ファイル5枚
の計6枚の画像ファイルが添付ファイル列に登録されることになります。

IP Manager呼び出して更新してるっぽいですけど何とかしてくれないですかね。。。

上記の理由より"Reserved_ImageAttachment"で始まらない添付ファイルのアイテム名でフィルタして添付ファイルは表示してあげる必要が現状はあります。

Filter(ThisItem.添付ファイル, !StartsWith(DisplayName, "Reserved_ImageAttachment"))

お察しの方もいらっしゃると思いますが、"Reserved_ImageAttachment"で始まるファイルがもしユーザからアップされた場合はこのやり方はアウトです。

より厳密にするのであれば、もうちょっとフィルタ条件を絞るぐらいですかね。。。

どこかで妥協する必要はあります。
100点は求めないでください。

画像列のアイテムを削除する

これまでは画像列にBlank()を渡せば画像ファイルを削除することができていました。

しかし、現時点ではそれでは画像の削除はできなくなっています。

画像ファイルの持ち方の仕様が変わっているので呼び出されるAPI Manager側も変更を加えなきゃいけないはずなんですが、それがまだ(?)行われてないからですね。(多分)

deleteFileAsyncが呼び出されてるっぽいですが、ファイル削除じゃないんじゃないかな。。。

暫定対応として一番簡単なのは、削除用の画像を用意してその画像に置き換えることですね。
実際画像ファイルが削除されるわけではないですが、削除されているように見せかけることでユーザに「ここに登録されている画像はないんだな」と認識してもらう運用です。

  1. 削除用画像を用意
    (動き揃えるために空白の画像でもいいです。今回は説明用に×アイコンの画像を利用。)
  2. 画像の削除を行うためのアイコンやボタンを追加
    (画像の追加コントロールには画像の削除を行う機能はないので独自で実現する必要があります。
    これは今回の仕様変更に関係ありません。)
  3. 画像削除用アイコンやボタンが選択されたときは画像削除用フラグをオンにする

DeleteIcon.OnSelect

UpdateContext({isDeleteImage: true})
  1. 画像削除用フラグが立っていた場合は画像を削除用画像に切り替える

Image.Image

If(
    isDeleteImage,
    Delete,
    // else
    IsBlank(AddPicture1.Media), 
    Parent.Default,
    AddPicture1.Media
)
  1. 画像変更時は画像削除用フラグをオフにする

AddPicture.OnChange

UpdateContext({isDeleteImage: false})

添付ファイルコントロール列をユーザが直接コントロールを弄ることなく既存の添付ファイル列のファイルを消す。
なんてことは現状API直接叩かないとできないはずですので、Pathc()やSubmitForm()では実現できないはずですね。

なにかいい案あれば教えてくださいー

おまけ

他できるようになったこと

Hirano AIさんもおっしゃっていますが、リストに対してドラッグ&ドロップで画像列にファイルを追加できるようになりました!

ただしこれは、SharePoint Listではできません。

Microsoft Listでのみできます。

SiteAssetsに画像が作成されるようにする

---2023/12/27 追記---

以下記事でリストの画像列に追加した画像が添付ファイル列ではなく"SiteAssets"配下に作成される方法を追記しました。
もちろんデメリットもあります。

koruneko.hatenablog.com

おわりに

SharePoint Listの仕様がそもそも変わったことや、それによる変更点などがまとめられたような記事が公式にもないっぽかったので今回まとめました。

Power AuotmateやPower BIでにこれ関連の変更は気が向いたらまとめます。

こうした方が良いよー。や、ここ違うくない?などあればご指摘お待ちしております。


スポンサードリンク