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

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

Microsoft Formsの「事前入力済み URL の取得」を試してみる

はじめに

この前久し振り?にMicrosoft Formsを触っていたら「事前入力済み URL の取得」なる機能があったので紹介兼てこの記事で機能をまとめておきます。

なおちょっと調べてみた感じですが、公式ドキュメントではこの機能は特に紹介されていない??

事前入力済み URL の取得

どんな機能?

その名の通り事前に回答内容が入力されたフォームのリンクを取得することができる機能です。

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

例えば以下のようなフォームがあったとします。

このようなフォームに対して事前入力済みのURLを取得してみます。

するとこのような画面が表示されますので、

「事前入力済みの回答を有効にする」のトグルをオンにします。

例えば設問 1 のイベントIDを入力して、事前入力されたリンクを取得してみます。

リンクを開いてみると、

先ほど定義した値が事前に入力されていますねー

もう少し検証してみる

もう少し内容みてみましょう。

まずは先ほど生成されたリンクをみてみます。

取得されたリンク

https://forms.office.com/Pages/ResponsePage.aspx?id=Eu460AoF1UCloFIvUISahOPL4dTvxztDiz6yvAJKKm1URTJKNTlFVU82TDFQUUlDOTRESDY5S05LWS4u&r2416356411604b6d86afcb9a63c6da6f=MS001

注目する箇所はここですね。

r2416356411604b6d86afcb9a63c6da6f=MS001

左辺の箇所はFormsとPower Automateの連携をやられていて、動的な値の中身を見られている方でしたらお馴染みの、各設問に割り当てれれている内部IDっぽいですね。

こちらの値が右辺の値に設定されるのでしょう。

ということでリンクの値を変えて再読み込みしてみます。

無事変わってくれました!

ただし、、、

先ほどの予測と検証の通り、無事にリンクの内容に従って変わってくれました。

ただし、1点注意が必要です。

どうやらこちらのディープリンクの値よりもキャッシュの結果の方が優先されて表示されてしまうようなのです。
* アンケートに回答しないで再読み込みした場合です。

Microsoft Formsはアンケートに回答中のユーザーが画面を離れて再度フォームにアクセスした際にキャッシュの内容から入力内容を復元してくれるような機能をもってくれています。

今回、こちらの機能が優先してフォームに反映されているようですね。

まぁ、動き的にはこちらの方がいいのかな?
ディープリンクの内容で上書きされるより、自身が先ほどまで入力していた内容が反映された方が嬉しいケースの方が多そうですし。

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

私がこの機能を見つけたときは、おっ?!と思いましたが、周りの方々はあまりピンと来ておらず少し悲しい思いをしたので簡単に利用シーンを記載したいと思います。

  • IDなどを入力してもらいたい場合

    • 例えば先ほどまでの例に利用していたようなイベントIDなどをユーザーに入力してもらいたい場合などにこの機能が使えます。
      定期開催や同時期にイベントや勉強会を開催しており、それらのフィードバック収集には同じフォームを利用している。というのはよくあるケースかと思います。
      そのような場合にこの機能が役立ちますね。
      そのイベントの最後に案内するリンクやQRコードにて事前入力済みリンクを共有してあげれば、ユーザーはIDを入力する手間が減る他、入力ミスを防ぐこともできます。
  • 申請種別を区別したい場合

    • なにかの申請を受け付ける場合に、フォームのメンテナンスの手間を考えて同じ申請フォームを利用しており、ユーザーにどの申請か?を選ばせる。のような運用をとっているようなケースがあるかと思います。
      そのような場合にこの機能が役立ちます。
      申請フォームへの導線はSharePoint サイトなどから「XXXの申請を行いたい場合はこちら」みたいなところから飛ばすような運用にしているところが多いのではないでしょうか?
      そのような導線の場合はユーザーは行いたい申請種別は決まっているはずです。従って、それが事前に入力されたフォームが表示されれば手間が減るので便利になりますね。

などなど、主な利用シーンは上記になるかな?

面白い使い方あれば教えていただけると助かります!

おわりに

Microsoft Formsにも新しい機能がちょくちょく追加されてはいるのですが、他製品程力入れて宣伝されていないような気がするのは、私のアンテナの貼りが弱いからだろうか?

手軽に入力フォームを作成して情報の収集やアンケートの収集が行える便利な機能なので、もうちょっと機能紹介してもいいのでは?と思うんですけどねー

Power Appsで音感神経衰弱を作成

はじめに

6/22(土)にゲーム作成コンテストを開催します!

jppgb.connpass.com

現在上記connpass上でエントリー者募集中ですのでゲーム作成を行っている方はもちろん、ゲーム作成に興味のある方も気軽にエントリーしてください!

イベントは以下のスケジュールで進行します。

スケジュール

そして、なんと今回はスポンサー企業様のご協力により賞品を用意することができました👏
スポンサーとなっていただいた企業様、改めてありがとうございます。

さて、今回は私自身が最近ゲーム作成してないなーと思ったので、簡単なゲームを作成してみました。

名付けて音感神経衰弱です。

今回はこちらの作成方法を簡単に紹介します。

ゲーム作成の参考になればー

音感神経衰弱を作成する

作成するのは神経衰弱の絵柄ではなく、音を揃えるゲームです。

カードを選択すると音がなるので、同じ音を見つけ出して揃えるゲームです。

音感に自身のある方であれば余裕のゲームですね!

素材の用意

素材は魔王魂さんからお借りしました!

maou.audio

いつもお世話になっております。

神経衰弱で場に表示する情報を作成する

まずは、神経衰弱で場に表示される情報を作成します。

私はよくPower Appsの開発時には初期化ボタンを作成することをおすすめしています。
これは、開発時に気軽に変数の初期化を行えるようにするためです。

App.OnStart はパフォーマンスの観点から推奨されていません。

koruneko.hatenablog.com

Screen.OnVisible は画面を毎回切り替えないと実行されません。

従って初期化ボタンを用意しておくことで、パフォーマンスを損なうこともなく開発中も手軽に初期化ができるようになるわけですね。

さて、初期化ボタンを用意したらまずはPower Apps上に取り込んだ音源をコレクションにいれます。

IniBtn.OnSelect

ClearCollect(
    SoundSource,
    {
        Name: "1_1do",
        Audio: maou_se_inst_piano1_1do
    },
    {
        Name: "1_2re",
        Audio: maou_se_inst_piano1_2re
    },
    {
        Name: "1_3mi",
        Audio: maou_se_inst_piano1_3mi
    },
    {
        Name: "1_4fa",
        Audio: maou_se_inst_piano1_4fa
    },
    {
        Name: "1_5so",
        Audio: maou_se_inst_piano1_5so
    },
    {
        Name: "1_6ra",
        Audio: maou_se_inst_piano1_6ra
    },
    {
        Name: "1_7si",
        Audio: maou_se_inst_piano1_7si
    },
    {
        Name: "1_8do",
        Audio: maou_se_inst_piano1_8do
    },
    {
        Name: "1_am_chord",
        Audio: maou_se_inst_piano1_am_chord
    },
    {
        Name: "1_c_chord",
        Audio: maou_se_inst_piano1_c_chord
    },
    {
        Name: "1_f_chord",
        Audio: maou_se_inst_piano1_f_chord
    },
    {
        Name: "1_g_chord",
        Audio: maou_se_inst_piano1_g_chord
    }
);

続いて神経衰弱の場に表示するための情報を作成します。
上記のコレクション * 2を設定すればいいですね!

最近のアップデートでテーブル型のデータも Table 関数 を利用することで複数のテーブルを1つのテーブルにすることができるようになりました!
もう ForAll 関数 や Ungroup 関数 を使う必要がないですね。

learn.microsoft.com

さて、場の情報を作成する際に同時に以下の情報も作成したいと思います。

  • カードを一意に特定するための"id"
  • カードを選択中かを判断する"isSelect"
  • カードを揃えたかを判断する"isCheck"

IniBtn.OnSelect

ClearCollect(
    neurasthenia,
    Shuffle(
        AddColumns(
            Table(
                SoundSource,
                SoundSource
            ),
            id,
            GUID(),
            isSelect,
            false,
            isCheck,
            false
        )
    )
)

AddColumns 関数 も最近使用が変わって、追加する列名にダブルクォーテーションを付ける必要がなくなりましたね。

powerapps.microsoft.com

場にカードを表示させる

場の情報を作成し終えたので、この情報を利用してカードを表示させます。

コレクションをギャラリーを利用して表示させます。
(座標やサイズは割愛)

折り返しの数は 12 * 2 = 24枚のカードがありますので、 "5" にしておきます。

WrapCount

5

ギャラリーの中に四角形とオーディオを追加します。

四角形とオーディオの順序は四角形が先にくるようにしておいてください。(理由後述)

四角形は選択されたら外枠を設定して、選択状態がわかるようにします。

BorderThickness

If(ThisItem.isSelect, 2, 0)

また、選択されたら isSelecttrue に設定するようにします。
すでに選択されていた場合は false ですね。

Patch(
    neurasthenia,
    ThisItem,
    {
        isSelect: !ThisItem.isSelect
    }
)

2枚選択されたら判定を行う

場のカードが2枚選択されたら判定を行うようにします。

判定にはトグルコントロール(切り替えコントロール)を利用します。

場のカードが2枚選択されたらトグルがチェックされるようにします。

Default

CountIf(neurasthenia, isSelect) = 2

トグルがチェックされたら判定を行います。

今回、ここの判定では選択したカードが同じだったかを判定します。

OnCheck

With(
    {_selectedItem: Filter(neurasthenia, isSelect)},
    If(
        First(_selectedItem).Name = Last(_selectedItem).Name,
        UpdateContext({isCorrect: true})
    )
);

選択されたら音を鳴らす

オーディオコントロールには2種類の表示プロパティがあります。

ここで、「オーディオコントロールは表示させておく必要がないので」ということで「表示」を「オフ」にすると音が鳴らなくなります。

これはこちらの設定によるものです。

オーディオコントロールは非表示にしたいが、音は適宜鳴らしたい。という場合は画像のように「表示」は「オン」にして、「コントロールの表示」を「オフ」にします。

これで、コントロールは非表示になるが音は鳴らせる。状態になります。

音は選択されたら鳴らしたいです。
よって以下のように設定すればいいですね。

ThisItem.isSelect

続いて、オーディオが鳴り終わったタイミングで

  • 選択状態の解除
  • 正解判定

を行わせます。

If(
    isCorrect,
    UpdateIf(neurasthenia, isSelect, {isCheck: true});
    UpdateContext({isCorrect: false})
);
If(
    CheckResult.Value,
    UpdateIf(neurasthenia, isSelect, {isSelect: false});
);

Reset(Self)

これで音感神経衰弱の完成です!

課題

このゲームには1点不具合があります。

それは最初に選択したカードの音が最後までなり終わる前に次のカードを選択してしまうと、最初のカードを選択した際に鳴っていたオーディオがなり終わったタイミングで終了判定がされてしまう点です。

もし神経衰弱の作成を考えられている場合はこの点に気を付けてください。

おわりに

ゲーム作成コンテストのエントリー絶賛受付中です!

【JPPGB】ゲーム作成コンテスト #1 - connpass

お気軽にエントリーしてください!

また、当日はオンライン & オンサイトのハイブリット開催となります。

オンサイトに来ることのできる方は是非オンサイトでご参加ください!
なにかいいことがあるかも...?

Power Automateを使ってPower Automateを作成する

はじめに

あまり参考文献がなかったので、この記事ではPower Automateの「フローの作成」アクションを用いてフローを作成する方法について記載しています。

learn.microsoft.com

どういうときに活躍するのか

こちらの記事に辿り着いた方はおそらく利用すべき要件があって辿り着いたかと思います。
そのような方はこちらは読み飛ばして貰えると。

フローの作成アクションは以下のようなシーンに役立ちます。

  • 同じような構成のフローだが、パラメータが異なる場合
    • 例えばトリガーに設定するパラメーターが異なる場合などが最も当てはまります。
      同じような構成だが、実行間隔が異なるものや、SharePoint リストが異なるものなどがこれに該当しますね。
  • 希望者にフローを配布したい場合
    • 作成したフローをそれぞれのマイフロー配下にて動かして欲しい場合などに利用できます。
      zip形式で配布する方法もありますが、これはソリューション化している場合は行えません。
      このようなシーンの対応としてはコピーの送信を利用するやり方もありますね。

フローの作成を行う

パラメーター

「フローの作成」アクションを実行する場合、5つのパラメーターの設定が必要です。

パラメーター 必須 説明
フローの表示名 必須 作成されるフローの名前を設定します
フロー定義 必須 作成するフローの情報
JSON形式で定義
フローの状態 必須 作成されるフローのON/OFFを設定
環境 必須 作成するフローの環境を設定
Flow/Properties/ConnectionReferences オプション 作成されるフローに利用される接続情報
※クラシックだと「connectionReferences」

フローの表示名

作成されるフローの名前を設定します。

ここは説明することもないので割愛。

フローの定義

作成するフローの定義をJSON形式で設定します。

たとえば、以下のようなシンプルなフローですと以下のような定義になります。

{
  "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
  "contentVersion": "undefined",
  "parameters": {
    "$authentication": {
      "defaultValue": {},
      "type": "SecureObject"
    },
    "$connections": {
      "defaultValue": {},
      "type": "Object"
    }
  },
  "triggers": {
    "manual": {
      "type": "Request",
      "kind": "Button",
      "inputs": {
        "schema": {
          "type": "object",
          "properties": {},
          "required": []
        }
      }
    }
  },
  "actions": {
    "作成": {
      "runAfter": {},
      "type": "Compose",
      "inputs": "AAA"
    }
  }
}

ただし、これをソラで0から記載するのはまぁ、時間の無駄ですので、まずは作成したいフローの基をクラウドフロー上で作成した後、「フローの取得」アクションを用いてフローの定義を取得するのが良いと思います。

これで得られた結果をPower Automate上で「作成」アクション内にべた書きしたり、テンプレートとなるフローから「フローの取得」アクションを用いて取得して作成したりすればいいですね。

前者の場合は、動的に変更したいパラメーターは動的なアクションを設定しておけばいいですね。

後者の場合は、「フローの取得」アクションで取得した動的な値の置換が必要です。

replace 関数 を用いて置換したい場合は、 string 関数 を用いてオブジェクト形式から文字列形式に変換した後に置換してあげる必要があります。
その後、 json 関数 を用いてオブジェクト形式に戻してあげます。

例えば以下のような形ですね。

json(
    replace(
        string(outputs('フローの取得')?['body/properties/definition']), 
        '置換前の値', 
        '置換後の値'
    )
)

文字列に戻すことなく、オブジェクト形式のままプロパティの編集を行う場合は setProperty 関数 を利用します。

今回更新するとなると入れ子になった値を更新することになるので、結構面倒です。(もっと楽なやり方あれば教えてください。)

例えばトリガーに設定されているパラメーターの値を変更する場合は以下のようになります。

setProperty(
   outputs('フローの取得')?['body/properties/definition'],
   'triggers',
   setProperty(
       outputs('フローの取得')?['body/properties/definition']?['triggers'],
       'トリガーの名前',
       setProperty(
           outputs('フローの取得')?['body/properties/definition']?['triggers']?['トリガーの名前'],
           'inputs',
           setProperty(
               outputs('フローの取得')?['body/properties/definition']?['triggers']?['トリガーの名前']?['inputs'],
               'parameters',
               setProperty(
                   outputs('フローの取得')?['body/properties/definition']?['triggers']?['トリガーの名前']?['inputs']?['parameters'],
                   '更新対象のパラメーター名',
                   '更新後の値'
               )
           )
       )
   )
)

フローの状態

作成されるフローのON/OFFを設定します。

ONの場合は"Started"
OFFの場合は"Stopped"
を設定します。

環境

フローを作成する環境を設定します。

Flow/Properties/ConnectionReferences

作成されるフローに設定する接続情報の定義を設定します。

こちらの定義はオプションですので、設定しなくともフローの作成自体は行えますが、接続情報が設定されていないフローが作成されますので、このままではフローは動作しません。

なので、だいたいの場合はこちらのパラメーターを設定することになりますが、こちらのパラメーターが少し曲者です。

まず、フローの作成経験がある方だと「フローの作成」アクションで得られた"connectionReferences"を動的な値として設定すればよいのでは?
と思われるかもしれません。

結論からいうとそれではだめです。

以下のようなエラーが表示されます。

OpenApiOperationParameterValidationFailed. The 'inputs.parameters' of workflow operation 'フローの作成' of type 'OpenApiConnection' is not valid. Error details: The API operation does not allow writing a value for parameter 'Flow/properties/connectionReferences[0]/displayName'. This parameter is read only.

"displayName"は読み取り専用だといわれていますね。

では、"connectionReferences"ではどのような値が返されるのかというと、Office 365 Usersコネクタを利用している場合は以下のような値が返されます。

[
  {
    "connectionName": "392f9b91fa9c4f52b1b2037c34108231",
    "displayName": "Office 365 ユーザー",
    "id": "/providers/Microsoft.PowerApps/apis/shared_office365users",
    "source": "Invoker"
  }
]

ここで"displayName"が返ってきていますね。
このパラメーターがダメだといわれています。

正直ドキュメントみてもよくわからんので、実際のアクションからこちらのパラメーターに設定が必要なJSON定義をみてみましょう。

こちらのパラメーターに適当な値を入力して「アレイ全体の入力に切り替える」を選択してみます。

すると以下のようにJSON定義を確認することができますので、この形式に変換してあげればいいということがわかります。

[
    {
        "connectionName": "A",
        "id": "B",
        "source": "C",
        "connectionReferenceLogicalName": "D"
    }
]

このような場合のJSONのキーの変更は「選択アクション」が利用できますね。

Map

{
  "connectionName": @{item()?['connectionName']},
  "id": @{item()?['id']},
  "source": @{item()?['source']}
}

これを「フローの作成」アクションの"connectionReferences"に設定すればフローの作成が行えます。

ただしこれは接続情報に「接続参照」が利用されていない場合のみできるお話です。

例えば、接続情報にDataverseの接続参照を利用している場合、"connectionReferences"は以下のような結果を返します。

[
  {
    "displayName": "Microsoft Dataverse",
    "id": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps",
    "source": "Embedded",
    "connectionReferenceLogicalName": "new_Dataverse"
  }
]

これを"displayName"を"connectionName"に変換したうえで設定すると以下のようなエラーが返ってきます。

XRM API に対する要求が失敗しました。エラー: 'Message: Request failed with: NotFound and error: {\"error\":{\"code\":\"ConnectionNotFound\",\"message\":\"Could not find connection 'new_Dataverse' for API 'shared_commondataserviceforapps'.\"}} and request url https://api.powerapps.com/providers/Microsoft.PowerApps/scopes/service/apis/shared_commondataserviceforapps/connections/new_Dataverse?api-version=2018-10-01&$expand=permissions($filter=maxAssignedTo('e1816e20-9788-43ef-a7f7-a415a67884d7')&$filter=environment eq '0e6b5ffb-79fd-e105-8b2e-8f15038badb6'\nCode: 0x80040265\nInnerError: '。

なぜこのようなエラーが発生してしまうのかというと、接続参照の場合の"connectionName"が異なるからです。

ではなにを設定すべきかというと、Dataverseの「つながり参照」テーブル(論理名「connectionreference」)の「つながり ID」(「ConnectionId」)列の値を設定する必要があります。

こちらのテーブルには「接続参照」の定義が格納されています。

この情報は「フローの取得」アクションでは得られません。

従って、面倒ではありますがDataverseのテーブルから情報を取得してフィルターみたいなことをする必要があります。

Power Automateで組み立てるのは正直面倒なので事前にJSON定義を作成しておくことを個人的にはお勧めします。

またこれはアクション側の問題だと思いますが、"connectionReferenceLogicalName"がうまく動作していないようで、同じ接続情報の接続参照が複数ある場合、どの接続参照が選ばれるかがわかりません。

これは「つながり ID」は接続参照に用いている情報が同じであれば共通のIDになるので、"connectionReferenceLogicalName"で接続参照の特定を行うことになるのですが、、、
これになにを設定しても指定した接続参照が指定できませんでした。。。

どうしてーーーー

また、トラブルシューティングとして私が遭遇した問題を記載しておくと"connectionReferences"の設定に問題がなさそうでも、引き続き上記と同じエラーが発生する場合があります。

XRM API に対する要求が失敗しました。エラー: 'Message: Request failed with: NotFound and error: {\"error\":{\"code\":\"ConnectionNotFound\",\"message\":\"Could not find connection 'new_Dataverse' for API 'shared_commondataserviceforapps'.\"}} and request url https://api.powerapps.com/providers/Microsoft.PowerApps/scopes/service/apis/shared_commondataserviceforapps/connections/new_Dataverse?api-version=2018-10-01&$expand=permissions($filter=maxAssignedTo('e1816e20-9788-43ef-a7f7-a415a67884d7')&$filter=environment eq '0e6b5ffb-79fd-e105-8b2e-8f15038badb6'\nCode: 0x80040265\nInnerError: '。

このような場合の原因のひとつフローの定義に問題がある場合があります。

フローの定義の

['actions']?['アクションの名前']?['inputs']?['host']?['connectionName']

* トリガーの場合は 'triggers' に置き換えてください。

をみてみると、コネクションの名前に "-1" が付与されている場合があります。

このような場合は、 "-1" を除去して試してみてください。

おわりに

思いもよらないところで躓いたーーーーorz

ちょっと調べてみたところあまり情報もなかったし、公式ドキュメントもわかりにくかったし。。。

でまとめてみましたが、他にいいやり方や、ここ違うよーなどあればコメントお願いします。

Power Appsで利用可能な数式であるPower FxがCopilotによってより手軽に利用できるようになります

はじめに

Power AppsではPower Fxという関数式が利用可能です。

Power Appsを利用したことがる方ならお馴染みの、Filter関数やSort関数などの関数式がそれにあたりますね。

そんなPower Fxの利用がCopilotによって強化されます!

powerapps.microsoft.com

Copilotによって以下ができるようになるらしいです。

  • Copilotによる数式の解説
  • 自然言語による数式の提案

GitHub Copilotなどのコーディング時に利用可能だったAI機能の一部がPower Fxでも利用可能になった形ですね。

なおこの機能は現在、英語環境のみで利用可能です。
日本語で利用したい場合はもう少し待ちましょう。

CopilotによるPower Fxの強化を体験してみる

Copilotによる数式の解説

Copilotによって数式の解説ができるようになりました!

実際利用している様子は以下ポストの動画をみてみてください。

Copilotによる数式の解説機能は、数式バーの左端にCopilotアイコンが表示されていますので、こちらを選択して、"Explain this formula"を選択することにより解説を行ってくれます。

解説を行ってくれた結果が"Copy"を選択することでクリップボードにコピーすることが可能です。
数式内に自動でコメントを追加してくれる機能ではないので注意してください。

今回数式は As 演算子の解説に載っている、チェス盤パターンをテキスト文字列として生成する数式を利用させていただきました。

learn.microsoft.com

Concat(
    ForAll( Sequence(8) As Rank,
        Concat(
            ForAll( Sequence(8) As File,
                    If( Mod(Rank.Value + File.Value, 2) = 1, " X ", " . " )
            ),
            Value
        ) & Char(10)
    ),
    Value
)

動画でも行われていますが、こちらの数式を解説してもらうと以下のような結果になりました。

生成された解説-1

This expression concatenates the values of the 'Value' column for each combination of 'Rank' and 'File' where the remainder of the sum of 'Rank' and 'File' divided by 2 is equal to 1, with " X " as the separator. It then concatenates the resulting string with the 'Value' column again, using "." as the separator. Finally, it concatenates the entire string with the 'Value' column one more time.

日本語訳-1

この式は、'Rank' と 'File' の組み合わせごとに、'Rank' と 'File' の合計を 2 で割った余りが 1 になる 'Value' 列の値を、" X " をセパレータとして連結する。次に、". "を区切り文字として、結果の文字列を再び'Value'列に連結する。最後に、文字列全体をもう一度'Value'列に連結する。

こちらの解説ですが、また後日実行すると以下のような解説が返ってきました。

生成された解説-2

This expression concatenates the values in the 'Value' column for each combination of 'Rank' and 'File' where the sum of 'Rank' and 'File' is an odd number, and appends the 'Value' column at the end.

日本語訳-2

この式は、'Rank'と'File'の和が奇数である場合、'Rank'と'File'の各組み合わせの'Value'カラムの値を連結し、最後に'Value'カラムを追加する。

フィードバックなどにより日々精度が改善されているということですね。
皆さんもCopilotによる結果がよければGoodを、悪ければBadをフィードバックするようにしてCopilotの精度改善に協力しましょう!

さて、このようにPower Fxで作成した式をCopilotによって手軽に解説が行えるようになりました。

これにより以下が期待できるようになると思います。

  • 作成した数式にコメントを付ける
  • 三者から貰った or 引き継いだ数式をCopilotによって解説してもらう

ただ、今回例で利用した結果を見てもらえればわかるかと思いますが、あくまでもCopilotで解説可能なのは数式がどのようなことを行っているのかです。

なぜこのような数式を設定しているのか?についての意図や要件については解説してくれません。
それは数式だけではわからないですからね。

例えば今回ですと、この数式によって「チェス盤パターン」をテキスト文字列として生成しています。

これはCopilotにより生成された解説からでは汲み取れないですね。

これはローコード開発に限った話ではありませんが、数式(プログラム)には「実装者しか知り得ない情報を他の開発者にわかりやすく伝えること」を意識して記載するようにしましょう。

自然言語による数式の提案

コメントからの数式の提案

ブログ内にあるこちらの機能ですね。

https://powerappsblogmedia.azureedge.net/powerappsblog/2024/04/Comments-2-Fx-04262024.gif

こちらの機能は、2024/05/04 現在、私の環境ではまだ試すことができませんでした。。。

アイディアパネルによる数式の提案

イデアパネルがサポートされているコントロール (ギャラリー、データテーブル、テキストボックス、ドロップダウン、コンボボックス、テキストラベル) にて、アイディアパネルを利用することでCopilotによる数式の提案を受けることができます。

アイディアパネルとは、以下のように「Copilot」を選択して、その後表示されるポップアップを選択することで表示されるパネルのことですね。
表示されるポップアップの文字列はコントロールによって異なります。

実際の利用イメージとしては以下のようになります。

このようにアイディアパネルで提案された数式を選択して適用することができます。

ギャラリーコントロールですと Items プロパティが対象になりますね。

また提案される数式には式だけでなく、解説までついてきます。

もちろん初期表示されている数式だけでなく、自身が行いたいフィルター/ソート条件を自然言語で生成をお願いすることもできます。

例えば、以下のようなプロンプトを投げてみます。

Filters the table 'DummyPersonalInfo' to include only the rows where the value in the '血液型' column is equal to the string literal "A". It then sorts the filtered table based on the values in the '年齢' column in descending order.

これによって期待される結果は以下になりますね。

Sort(Filter('DummyPersonalInfo', 血液型 = "A"), '年齢', SortOrder.Descending)

ただ上の結果を見てもらえればわかる通り、期待していた結果とは異なる結果が提案されてしまいました。

Sort(Filter('DummyPersonalInfo', 'Title' = "A"), '年齢', SortOrder.Descending)

フィルター条件は 'Title' ではなく、 '血液型' ですね。
'Title' なんて一つも指示していないのにどこから出てきたのだろうか?

フィルター条件の方はミスがありましたが、ソート条件は問題なさそうです。

このような場合は、適応された式を自身で修正してあげる必要がありますね。

一応このようにアイディアパネルが利用可能であればギャラリー以外でももちろん利用可能ですよ。というのを示しておきます。

まぁプロンプトが悪いのか想定通りの提案してくれていないですが。。。

おわりに

以上のように、まだまだCopilotの機能は100%正確とはいえません。

Copilotを利用することで、初学者には開発のハードルが下がり、これまでの利用者にとってはCopilotのサポートを受けることでより生産性が増すことになるかと思います。

しかし、Copilotは言葉の意味の通り「副操縦士」です。
Copilotの提案を受けて最終的な決定を下すのは「操縦士」である、あなたです。

このことをきちんと理解したうえでCopilotを活用しましょう。

開催予定のイベントの宣伝!

イベントの紹介

近日開催予定のイベントの宣伝です!

オフライン開催も行いますので、イベント内容に興味があり当日現地に参加可能な方は是非ご参加ください!

業務改善検討会

「業務改善検討会」という"業務改善"をテーマに参加者全員でアイディアやノウハウを共有するグループで開催するイベントの紹介です。

bpr-tbd.connpass.com

Process Renovation Spark #1

業務改善検討会初のオフラインイベントでアイディアソンを開催します!

bpr-tbd.connpass.com

開催日時

2024/05/18(土) 10:00 〜 17:00

会場

AKKODiSコンサルティング株式会社

東京都港区芝浦3丁目4番1号 グランパークタワー3F

イベント概要

本コミュニティは業務改善方法を皆で共有し、業務改善に関して参加者全員で考えるためのコミュニティです。

今回のイベントでは、与えられた業務課題をもとに最大4人程のチームに分かれて、参加者同士で協力して改善ソリューションを考えるアイディアソンとなっています。

改善のソリューションはIT技術を用いて行ってください。

業務課題に関しては、ページ下部の想定企業をご確認ください。

本イベントでは、Microsoft 365を導入している企業を想定して実施します。
SaaSの導入に関しては、課題解決に使うことのできるリソースの範囲内で行ってください。

このイベントをきっかけに自身の業務の改善に取り組んでいただけたり、日々の改善活動のアイディアとしてもらえたりすると幸いです。

イベントで目指すこと

  1. 業務改善について自身で考えるためのきっかけを作ってもらう
  2. 他の参加者の方のアイディアを吸収してもらう
  3. 工数、コスト、運用保守性などを加味した業務改善案を考えられるようになってもらう

Japan Power Platform Game Builders

Power Platformを利用してゲームを作成するグループで開催するイベントの紹介です。

jppgb.connpass.com

【JPPGB】ゲーム作成コンテスト #1

第0回でも好評だったゲーム作成コンテストの第1回イベントを開催します!
今回はスポンサー企業様,-AKKODiS%E3%82%B3%E3%83%B3%E3%82%B5%E3%83%AB%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE)のご支援により、入賞者には賞品も用意しております!

Power Platformでのゲーム作成に興味のある方は是非ご参加ください!!

jppgb.connpass.com

イベントスケジュール

スケジュール

会場

オンサイトとオンラインのハイブリッド開催を行います。

オンサイトで参加される方は、イベント当日以下までお越しください。

AKKODiSコンサルティング株式会社

東京都港区芝浦3丁目4番1号 グランパークタワー3F

イベント概要

Japan Power Platform Game Builders (JPPGB) では、本来業務アプリを作成するはずのPower Platformを用いてゲームを作成してみよう!ということに取り組んでいるコミュニティです。

今回のイベントでは、皆さんお待ちかね(?)のゲーム作成コンテストを開催します!:party_popper:

今回は前回の第0回とは違いサービスの制限はありません。
Power Platformで開発されたゲームであればOKです!

テーマやジャンルの縛りもありません。
皆さまの作成したいゲームを作成してください!

個人でもチームでのエントリーもOKです。

そしてなんと今回は スポンサー様企業,-AKKODiS%E3%82%B3%E3%83%B3%E3%82%B5%E3%83%AB%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE) のご支援により入賞者には賞品を用意しております!

Power Platformでのゲーム開発を行っている方はもちろん、これを機会にPower Platformでのゲーム開発に挑戦してみようという方の参加もお待ちしております!!

エントリーされる方へ

■エントリー方法

エントリーを検討される方は、connpassのエントリー枠からエントリーをお願いします。
参加登録を行いますとconnpassのアンケートが表示されますので、運営との連絡手段のご記入をお願いします。

後日運営から確認を含めたご連絡をさせていただきます。

■作品の公開について

作成した作品は運営指定の方法で公開をお願いします。

公開いただいた作品を一般参加者及び運営で遊んで投票を行います。

作品と合わせて簡単なもので大丈夫ですので、作品の紹介を行う資料や動画の作成もお願いします。

■禁止事項

以下の行為は禁止とさせていただきます。

  • 過去に公開したものをアップデートを加えずにそのまま作品の公開
  • 著作権に抵触する作品の公開
  • PCFなどのコーディングを用いた開発(あくまでもローコードでの開発をお願いします)
  • 公序良俗に反する作品の公開

おわりに

イベントに興味があり、予定の合う方は是非当日ご参加ください!

会場でお待ちしております!

Power AutomateでSharePoint REST APIを呼び出してSharePoint ListsのImage列を操作する

はじめに

こちらの記事の完全版・最新版になります。

koruneko.hatenablog.com

SharePoint Lists(Microsoft Lists)のImage列の画像の保存先がSiteAssetsから添付ファイル列に変更になりましたので、添付ファイル列に紐づいたImage列のアイテムを操作する方法をまとめています。

なお、現在一部のユーザー(テナントやリスト単位では無い。)はImage列に画像をアップロードしても、添付ファイル列ではなく、SiteAssetsに登録されてしまうようです。

こちらに関しては私の方では状況再現できなかったので、ちゃんと全員にロールアウトされるの待つか、有志の方が情報や対策まとめてくれるのを私は待ちます。(このブログではこちらの問題は触れませんよ)

SharePoint ListsのImage列を操作する

画像を取得する

Image列の画像の取得方法については以下の「Image列の情報を取得する」で記載していますのでこちらを参考にしてください。

Power Automateで仕様が変わったSharePointリストのImage列に画像を登録する - コルネの進捗や備忘録が記されたなにか

画像を新規登録する

画像の登録は前のブログでも紹介していましたが、こちらの方がより良いので改めて記載します。

まずSharePoint ListsのアイテムのImage列に画像ファイルを追加したい場合、先にアイテムを作成してあげる必要があります。

これは画面上でImage列に画像を新規追加するような操作をした後にバージョン履歴を見てあげればわかるかと思います。

  1. アイテムの作成
  2. 添付ファイル列に画像ファイルをアップロード
  3. Image列にアップロードした画像の情報を紐づけ

のように3つのバージョン履歴が追加されているかと思います。

ということで、Power AutomateでImage列に画像を追加する場合でもまずは「項目の作成」アクションでアイテムを作成してあげる必要があります。

以上を踏まえてフローの全体像を共有するとこのような形になります。

前半2つのアクションは登録する画像ファイルの情報をドキュメントライブラリから取得しているだけです。

それでは肝心のSharePoint REST APIでのImage列への画像ファイルの登録方法です。

Power AutomateでSharePoint REST APIを実行する場合は「SharePoint に HTTP 要求を送信します」アクションを利用しますね。

SharePoint REST APIでImage列に画像をアップロードする場合は、 AddThumbnailFieldData リソースを利用します。

URI

_api/web/lists/GetByTitle('<Your List Name>')/Items('@{body('項目の作成')?['ID']}')/AddThumbnailFieldData(imageName='@{outputs('パスによるファイル_メタデータの取得')?['body/DisplayName']}',fieldInternalName='<Your Image Column Field Name>')

header

{
  "Accept": "application/json;odata=verbos",
  "Content-Type": "application/json;odata=verbose"
}

body

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

URIの "<>" 内の項目は自身の環境に合わせて変更してください。

このAPIを実行することで、

  • 添付ファイル列へのアップロード
  • Image列への添付ファイル情報

の2つを実行してくれます。

また前回紹介した方法と異なり、このやり方でアップロードされた場合、添付ファイル列に余計な情報が表示されなくなります。(実際には添付ファイルには画像ファイルはあるけど、「アイテム プロパティ」からは見えなくなるよ。ということ。詳しくは以前のブログみてください。)

画像を削除する

更新の前に削除のやり方を紹介します。

削除の場合でも、新規登録の時と同様に AddThumbnailFieldData を利用します。

違うのは空での更新を行うという点です。

まずは現在Image列に登録されている画像ファイルの名前を取得します。

URI

_api/web/lists/GetByTitle('<Your List Name>')/items(@{triggerBody()?['number']})

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

最後に AddThumbnailFieldData を利用して、現在登録されている画像ファイルを空で更新します。

URI

_api/web/lists/GetByTitle('<Your List Name>')/Items('@{triggerBody()?['number']}')/AddThumbnailFieldData(imageName='@{outputs('作成')}',fieldInternalName='<Your Image Column Field Name>')

header

{
  "Accept": "application/json;odata=verbos",
  "Content-Type": "application/json;odata=verbose"
}

"Body" には何も設定しません。
これにより、 imageName で指定して登録する画像は空と認識され、画像ファイルを削除することができます。

このAPIを実行することで、

  • 添付ファイル列にアップロードされていた imageName の画像名に一致するファイルの削除
  • Image列の情報の削除(nullになります)

の2つを実行してくれます。

画像を更新する

最後に画像の更新ですが、画像の更新でも AddThumbnailFieldData を利用します。

ただし、こちらは一工夫必要です。

実際に画面から画像の更新を行い、その後バージョン履歴を確認してみてください。
4つの履歴が追加されているかと思います。

これは画像の更新の際に、

  1. 添付ファイル列にある画像の削除
  2. Image列のクリア
  3. 添付ファイル列に画像ファイルをアップロード
  4. Image列にアップロードした画像の情報を紐づけ

という操作が行われているからです。

つまりPower Automate(REST AP)でImage列の画像を更新する場合も同じ手順を踏まなくてはいけないということですね。

なので先に削除のやり方を先ほど紹介しました。

フローの流れとしてはこのような感じになります。

新規登録と削除の組み合わせですね。

やっていることは同じなので、スクショでけ貼っておきます。

削除処理

更新処理

おわりに

画面からImage列の情報を操作したときと同じように画像ファイルの操作がPower Automateでもできるようになりました!

SharePoint REST APIを利用するのは少しハードルが高いかもしれませんが、ひとつづつやり方を理解して利用していきましょう。

Visual Studioからカスタム コネクタを作成する

はじめに

こちらの記事を作成したのでおまけに。

koruneko.hatenablog.com

上記の記事ではPower Appsの画面からコネクタの作成を行いましたが、Visual Studioから作成することもできます。

この記事ではVisual Studioからカスタム コネクタを作成する方法を記載します。

なお、Web APIは作成済みの想定で記載しています。(作成から見たい場合は上記記事か下記公式ドキュメントをご確認ください。)

learn.microsoft.com

Visual Studioからカスタム コネクタを作成する

接続サービスとしてPower Platformを追加する

作成したいプロジェクトを開き、ソリューション エクスプローラーにて「Connected Services」で右クリックを行います。
「追加」 > 「Microsoft Power Platform」を選択します。

Power Platfromへの接続情報の作成を行います。

カスタム コネクタを新規作成する場合は、右のプラスアイコンを選択してカスタム コネクタ名を入力します。

パブリック開発トンネルを作成済みの場合は選択し、選択可能なトンネルがない場合は右のプラスアイコンを選択して新規作成します。

「次へ」もしくは「完了」を選択します。

「次へ」を選択すると、追加/変更される情報が表示されるので、問題なければ「完了」を選択します。

作成されるまで待ちます。

作成されると選択したソリューション内にカスタム コネクタが追加されます。

ただ、モデル クラスの追加で追加されたメソッドはうまく読み込めてないですねー。。。

これらはController内の定義が悪いのが原因です。

取り急ぎで簡単なやり方は、「全般」の設定を手動で更新するやり方です。

ただしこれは取り急ぎの一時的な対応です。

正しく対応するのであれば、 TodoItemsController.cs のルート定義を修正します。

以下のようにルート定義を修正しています。(一部)

- [HttpGet]
+ [HttpGet(Name = "Gettodoitems")]

- [HttpGet("{id}"]
+ [HttpGet("{id}", Name = "Gettodoitem")]

その後、「Connected Services」で右クリックして「接続済みサービスの管理」を選択します。

そして、「依存関係の編集」を行い先ほど作成したカスタム コネクタの更新を行いましょう。

その結果カスタム コネクタの更新が行われるはずです。

あとはこちらのカスタム コネクタをPower Platformで用いるだけです。

実行する際は忘れずにVisual Studioにてデバッグを行うようにしましょう。

おまけ

折角なので、アプリもコードベースで作成してみます。

Power Platform CLIをインストールしてください。

learn.microsoft.com

コマンドベースで対象の環境にアクセスできるようにするために認証情報を作成します。

pac auth create --environment "<環境名>"

<環境名> には自身の環境名を入力してください。

もし認証情報が複数ある場合は

pac auth list

で現在保持している認証情報を一覧表示した後に

pac auth select --index <index number>

でこれから利用したい認証情報に切り替えてください。
<index number> には pac auth list で一覧表示したときに表示されたインデックスの番号を入力します。

続いてカスタム コネクタの一覧を表示させます。

pac connector list

次に以下コマンドで .msapp ファイル(Power Appsのファイル)を作成します。

pac canvas create --connector-id <your connector id> --msapp <your file name.msapp>

<your connector id> には pac connector list で一覧表示したときに表示されたコネクタ IDを入力します。

<your file name.msapp> には任意の .msapp ファイル名を入力します。

作成された .msapp ファイルをPower Appsで開くと以下のようなアプリが確認できます。

ただしコネクタは追加されていないので、自身で追加してあげる必要があります。

また、こちらで作成されたアプリにはなぜか "PUT" と "DELETE" メソッドは含まれていませんでした。

おわりに

このようにVisual Studioをベースにカスタム コネクタを作成することも可能です。

また、アプリもCLIベースで作成することもできます。

それぞれに良さがありますので、まずは取れる選択肢を増やしてもらったうえで、自身がやろうとしていることはどのやり方でやるのかベストか考えてから作成を行えるようになるといいですね。

Visual StudioでDev Tunnelsを利用してカスタムコネクタの作成練習を行う

はじめに

Power Platformでは、1,000以上のコネクタが用意されています。
Power Platformではこれらのコネクタを利用することで外部サービスとの連携がノーコード/ローコードで行えるようになっているわけですね。

しかし自身が利用したいサービスのAPIが公開されているにも関わらず、予めコネクタが提供されていないようなサービスもあります。
これは自社サービスなどの独自に作成したAPIサービスなども含まれますね。

そのような場合Power AutomateのHTTP要求で接続する方法もありますが、カスタム コネクタという独自のコネクタを作成して利用、共有を行う方法があります。

learn.microsoft.com

今回はこのカスタム コネクタという機能を勉強するにあたり、利用できる技術を紹介します。

対象者は開発がちょっとわかる方(ネットスラングではなく、文字通りの意味)を対象にしています。

利用する技術

カスタム コネクタを利用するにはAPIが必要です。

APIの利用には一般に公開されているAPIを利用する方法や、自身で開発したAPIをAzure FunctionsなどのAPIサーバーを用意する方法があります。

前者ですと公開されているAPIAPI仕様ベースでしかカスタム コネクタの検証は行えません。
また、対象のサービス利用制限を考慮する必要もあります。

後者ですと、APIを利用するための料金が掛かります。

そこで今回はVisual StudioのDev tunnelsを利用してテスト用のAPIを用意したいと思います。

learn.microsoft.com

Visual Studio 2022のDev Tunnelsを利用する

前提条件

以下が必要です。

Web APIを作成する

Webプロジェクトを作成する

こちらのチュートリアルベースで紹介します。

learn.microsoft.com

「新しいプロジェクトの作成」より「ASP.NET Core Web API」を選択して「次へ」を選択します。

任意のプロジェクト名とプロジェクトを作成するフォルダの場所を選択して「次へ」を選択します。

以下となっていることを確認して「作成」を選択します。

  • フレームワーク: .NET 8.0(長期サポート)
  • 「コントローラーを使用する」にチェックが入ってる
  • 「OpenAPI サポートを有効にする」にチェックが入ってる

「ツール」 > 「NuGet パッケージ マネージャー」 > 「ソリューションの NuGet パッケージの管理」を選択します。

「参照」タブを選択して、「Microsoft.EntityFrameworkCore.InMemory」を選択します。
その後、右側のウィンドウが表示されるので、「プロジェクト」にチェックをして「インストール」を選択してインストールを行います。

プロジェクトをテストする

Ctrl + F5 もしくは、「デバッグ」 > 「デバッグなしで開始」を選択します。

SSL を使用するようにプロジェクトが構成されていないので以下ダイアログが表示されますが、「はい」を選択します。

こちらも「はい」を選択して証明書のインストールを行います。

既定のブラウザーが起動し、以下のような画面が表示されます。

APIのテストをしてみましょう。

「GET」を選択します。

「Try it out」を選択します。

「Execute」を選択します。

その結果以下のような応答が得られるはずです。

Dev Tunnelsを作成する

トンネルを作成する

APIの用意が完了したので、Dev Tunnelsを試してみます。

https」 > 「Dev Tunnels」 > 「トンネルを作成」を選択します。

トンネル作成のダイアログが表示されますので、それぞれ入力を行います。

  • アカウント: トンネル作成に使用するアカウントを選択します。
  • 名前: トンネルの名前を入力します。
  • トンネルの種類: 「一時的」または「永続的」を選択します。
  • アクセス: トンネルのアクセスに必要な認証情報を選択します。カスタム コネクタで利用する場合は公開用を選択します。
    • 非公開: トンネルにアクセスできるのはトンネルを作成したアカウントだけです。
    • 公開用: トンネルへのアクセスには認証は必要ありません。このオプションを選択すると、インターネット上のすべてのユーザーがWebアプリ、またはAPIにアクセスできるようになるので注意してください。
    • 組織: トンネルにアクセスできるのはトンネルを作成したアカウントと同じ組織内のアカウントだけです。「アカウント」でGitHubを選択した場合はこちらのオプションは選択できません。

「OK」を選択すると以下のようなダイアログが表示され、「開発トンネル」で先ほど作成したトンネルが表示されます。

トンネルを使用する

「開発トンネル」にて、先ほど作成したトンネルが選択されていることを確認します。

先ほど作成したトンネルが選択されていることを確認した後、Ctrl + F5 もしくは、「デバッグ」 > 「デバッグなしで開始」を選択します。

既定のブラウザーが起動し、以下のような画面が表示されますので「続行」を選択します。

その結果、先ほどと同じWebアプリが起動するかと思いますが、URLがlocalhostではなくなっているかと思います。

  • デバッグ: https://localhost:7223/swagger/index.html
  • デバッグ: https://50tt58xr-7223.usw2.devtunnels.ms/swagger/indexf.html

Dev Tunnelsで作成されたAPIを利用してカスタムコネクタを作成する

あとはカスタム コネクタの作成方法と同じです。

Power Appsにアクセスして、「カスタム コネクタ」の新規作成を行います。

今回は「一から作成」を行います。

「ホスト」にDev TunnelsのURLを入力します。

要求と応答を入力して、定義の作成を行います。

コネクタを作成して、テストを行います。

問題なければ以下のように応答が返ってくるはずです。

Power Appsから呼び出してみる

先ほど作成したカスタム コネクタをPower Appsに追加して呼び出してみます。

問題なければ以下のようなテーブルが得られるはずです。

APIデバッグを行う

Power AppsやPower Automateから呼び出したカスタム コネクタのデバッグを行うことも可能です。

やり方は、Visual Studioで「デバッグの開始」(F5)を行い、カスタム コネクタの呼び出しを行うだけです。

後は、通常の開発時のデバッグの時のように確認したい箇所にブレークポイントを設定しておくだけです。

作成したAPIがカスタム コネクタから呼び出した場合に想定通りに呼び出されない場合などの検証時に利用できますね。

APIの更新を行う

通常の開発時と同様にホットリロードによる更新も可能です。

モデル クラスの追加

こちらを参考に行います。

learn.microsoft.com

ソリューション エクスプローラーにてプロジェクトを右クリックして、「追加」 > 「新しいフォルダー」を選択します。

作成されたフォルダーを「Models」にリネームし、右クリックして、「追加」 > 「クラス」を選択します。

「TodoItem」という名前のクラスを追加します。

以下コードに更新します。

namespace TodoApi.Models;

public class TodoItem
{
    public long Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
}

データベース コンテキストの追加

先ほど「TodoItem」クラスを追加したときと同様の方法で続いては、「TodoContext」クラスの追加を行います。

追加したクラスには以下のコードに置き換えます。

using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models;

public class TodoContext : DbContext
{
    public TodoContext(DbContextOptions<TodoContext> options)
        : base(options)
    {
    }

    public DbSet<TodoItem> TodoItems { get; set; } = null!;
}

データベース コンテキストの登録

Program.cs を以下のコードで更新します。

using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
    opt.UseInMemoryDatabase("TodoList"));
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

追加されたのは以下3行です。

+ using Microsoft.EntityFrameworkCore;
+ using TodoApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
+ builder.Services.AddDbContext<TodoContext>(opt =>
 +    opt.UseInMemoryDatabase("TodoList"));
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

コントローラーのスキャフォールディング

「Controller」フォルダを右クリックして、「追加」 > 「新規スキャフォールディングアイテム」を選択します。

「Entity Framework を使用したアクションがある API コントローラー」を選択して「追加」を選択します。

ダイアログが表示されるので、以下を選択して「追加」を行います。

  • モデル クラス: 「TodoItem (TodoApi.Models)」 を選択します。
  • データ コンテキスト クラス: 「TodoContext (TodoApi.Models)」 を選択します。

追加が行われるとコントローラー名で設定したコントローラーが追加されます。
スクショの例でいうと TodoItemsController.cs が追加されます。

PostTodoItem 作成メソッドの更新

nameof 演算子を使用するために、PostTodoItem で return ステートメントを更新します。

TodoItemsController.cs の l: 78 あたりを以下のように変更します。

[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
    _context.TodoItems.Add(todoItem);
    await _context.SaveChangesAsync();

    // return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
    return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}

ホットリロード

Alt + F10 もしくはホットリロードボタンを選択して、ホットリロードを行います。

その結果、Webアプリの更新が行われるはずです。

テスト

PostTodoItem のテスト

POST /api/TodoItems のテストを行います。

Bodyに以下JSONを設定して実行を行います。

{
  "name": "walk dog",
  "isComplete": true
}

その結果以下アイテムが追加されます。

Locationヘッダー URI のテスト

GET /api/TodoItems/{id} のテストを行います。

先ほど作成されたアイテムの id を指定して実行を行います。

その結果、先ほど作成されたアイテムが取得されるはずです。

存在しないアイテムを指定した場合、 404 が返ってくるはずです。

GETメソッドのテスト

GET /api/TodoItems のテストを行います。

このメソッドではアプリ実行中に追加されたアイテムをすべて返します。

PutTodoItem メソッドのテスト

PUT /api/TodoItems/{id} のテストを行います。

このメソッドでは指定した id のアイテムの更新を行います。

DeleteTodoItem メソッドのテスト

DELETE /api/TodoItems/{id} のテストを行います。

このメソッドでは指定した id のアイテムの削除を行います。

カスタム コネクタの更新を行う

Power Appsにアクセスして、「カスタム コネクタ」の編集を行います。

先ほど追加したアクションの定義を追加します。

カスタム コネクタを利用中のアプリでは、カスタム コネクタの更新がないので、一度削除してから再度追加を行います。

問題なくアクションが呼び出せていることを確認します。

関連記事

こちらもよければご参照ください。

koruneko.hatenablog.com

おわりに

カスタム コネクタの作成練習だけでなく、自社でAPI開発を行い、そのAPIをPower Platformで利用させたい場合この技術を開発者側は知っていた方が、よりトラブルなくカスタム コネクタの組織への展開ができるようになるかと思います。

プロ開発者と市民開発者とで開発するリソースを分担し、組織の内の開発を効率的に進めましょう!

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関数を用いることができます。

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


スポンサードリンク