魁!! ITブログ

比較的素人向けです。「扇風機、新しいの買っちゃおっかなっ」くらいのノリで「これからちょっと勉強してみようかなっ」くらいの方々向けです。玄人には無駄な時間を費やさせてしまうかもしれません。ご了承ください。

【No.3-MicrosoftTeamsとPowerAppsとPowerAutomateを使ってスケジュールのステータス変更】を実装してみた。その3。

ここに100万円があります。

 

・・・あぁん?

 

f:id:NagoyaITAdmin:20210621151209p:plain

はてなブログからの「今週のお題」。ここに100万円があります。ねぇけど?

ねぇんだけど。

俺の視界、見渡す限りどこにも100万円ねぇんですけど?

 

ねぇモンをお題に出来るかっつーの。

まずは目の前に持ってきてくれ。

話はそれからだ。

 

 

 

 

 

どういたしまして、アキヒサです。

 

 

 

めっきり夏ですね。

むしろ結構前から

けっこう夏でしたけどね。

 

 

みなさん元気にお過ごしですか?

私は今、会社でキンッキンのクーラーと

ゴーゴーの扇風機に当たりながら

このブログを書いています。

一人で。

 

見渡す限り、誰もいない。

し、100万円もいない。

 

始まりますよ。

そう。

僕の週間連載記事ですよ。

え?

「先週は?」って?

先々週が合併号だったので

先週は休載しました。

え?なに?

聞いてた話と違う?

っばっきゃろう!

天下の冨樫義博大先生だって、

ハンターハンター長期お休みになられてるんだぞ!

ガラスの仮面だって、未だに紅天女の決着ついてないんだぞ!

一般人だってそりゃ休載くらいするわいな!

 

・・すいませんでした。

 

 

 

 

ふぅ。

 

きついね。

 

今週は特にきつい。

 

 

これまではPowerAppsを使った

ノーコードでの記事だったんだけど、

今週はガッツリローコード

むしろ普通にコード

覚悟しぃや。

 

~~~ 本題 ~~~

※注※
本内容は私個人の意見や見解等であり、大変恐縮ですが記載内容に関して
誤りがある可能性がございます。
そのような場合、御連絡いただけましたら早急に訂正いたしますので、
よろしくお願いいたします。

 

その1 ー 前々回。作りたいシステムを発表。

その2 ー 前回。PowerAppsのロジックの作りこみは別にするかもしれないけど
         とりあえず画面周りをそれっぽくする。

         ここまではノーコードで出来たね!

その3 ー 今回。PowerAppsと、PowerAutomateでの色々。
          ここが下手すると2週にわたるかもしれないね。
          軽く考えてみても条件分岐とかややこしそう。

         このあたりが一番のハード回。
         ローコードが必要な部分。(全然ローじゃねぇ)

その4 ー 次回。全体的に色々と整える感じ?
           よく考えると履歴データの配置場所とかも事前に
           キメておかなきゃ・・・

その5 ー 次々回。なんだろう。打ち上げパーリーでもしようか。

            各自、つけてみそかけてみそを持参の上、

           みそパしよ。みそパ。

 

さて。

 

みんな元気ですか?

連続でこの一連の記事を読んでる様な人はいないとは思うけど、

どうだろうか。

元気だろうか。

 

僕はあまり元気ではありません。

だって、今回はプログラムをガチガチに組み込んでいく回だから。

 

もうね。

全っ然ローコードじゃない。

コード

うん。

普通にコード。

 

いやいや。

たしかに?

0から?

1から?

プログラム言語を理解して、

プログラム組むよりは、簡単よ?

 

なんちゃらクラスの中に、

なんちゃらってゆー要素があるから、

その値を参照して、

あそこのフィールドの値にぶち込んで、

さらにその結果によって、

あっちのフィールドの選択肢を自動的に切り替える。

で、最終的にログインユーザーの上司が誰かを検索して、

その人宛にメールを送信する。

 

みたいな事を知識0からやろうとしたら

下手すると1週間はかかる。

もっとか?

もっとかかるか?

 

それに比べたら今回のローコードなんて、

へのへのカッパよ。

ちゃらへっちゃらよ。

やることさえハッキリわかっていれば、

1日~2日で出来ちゃったりはするね。

 

 

でも・・・怖いよね。

初心者の皆様にとってはさ。

プログラム書くなんてさ。

 

大丈夫。

俺なんて、

意図せずに、とある大企業のサーバー全停止させたことあっから。

検証環境だったけど。

 

それに比べれば、別に何にも問題ない。

今回あなたがプログラムを間違えてしまったところで、

死ぬわけじゃないし、

作るもの次第だけど、

ニュースに載るわけでもない。

 

とはいえ、もし失敗してニュースに載っても私は責任とりませんけどね?

そこはね。

ちゃんと。

言っとかないと。

 

このふざけたブログを参考にしちゃったのが

運の尽きだと思ってください。

 

さて。じゃあそろそろ本日のお題目。

 

前回までで、

PowerAppsのざっくりとした見栄えは作成できたね。

 

今回は、

実際に

PowerAutomateで、データを取得してきたり、

PowerAppsでそのデータを加工して、画面に表示させたり、

PowerAppsとPowerAutomateで、データを変更したり。

を、やっていこうと思う。

 

手順的にはこんな感じ

1.ログインユーザー情報取得
 (PowerAppsの機能を使って、ログインしてるユーザーの情報をゲット)

 1-1.PowerAppsのホーム画面でユーザー情報を取得

 1-2.取得したユーザー情報からユーザー名(表示名)を表示させる。

2.スケジュールの取得

  (PowerAppsのホーム画面のボタンで、PowerAutomateを起動。
   ログインユーザーの24時間以内のスケジュールを3件ゲットして、
   またPowerAppsちゃんにデータを連携してあげる。)

 2-1.PowerAutomateを作成

 2-2.PowerAppsからPowerAutomateに渡す情報を決める

 2-3.PowerAutomateをガッツリ作りこむ

 2-4.PowerAppsのボタンにPowerAutomateを起動する様にしてあげる

 2-5.PowerAutomateから受け取った情報を、そのままだと使いづらいから
     色々加工して、PowerAppsのビュー画面に表示させる。

3.管理者用画面

 (管理者画面を加工して、凡例の色を指定出来る様にする)

 3-1.DataVerseに新しいテーブルを作る

 3-2.Screen1の画面にDataVerseの各フィールドの値を指定する

4.ビュー画面

 (DataVerseにある凡例の情報をギャラリーに表示させて、

  2-3のPowerAutomateでとってきた情報をギャラリーに表示)

 4-1.DataVerseにある凡例のテーブル情報をギャラリー1に表示

 4-2.PowerAutomateで取得したスケジュール情報の値をギャラリー2に指定する 

5.フォーム画面

 (ビュー画面で選択した情報を表示して、
  変更させたい凡例の色を選択させる。)

 5-1.ビュー画面で選択された情報を、加工してフォーム画面に表示

 5-2.凡例のギャラリーに、PowerAutomate起動用の四角形を付ける

 5-3.データ加工用のPowerAutomateを作る(最初の方だけ)

 5-4.ギャラリーに追加した四角形のOnSelectかなんかに、
     PowerAutomate起動用のロジックを書く

 5-5.PowerAutomateをめちゃくちゃする

 5-6.PowerAutomateで変更した内容を、DataVerseに保存ぬ

 5-7.DataVerseに保存した値をフォーム画面に表示させる

 

こんくらいかしら?

どうかしら。

 

とか言ってるレヴェルじゃないね。

終わってるよね。

圧倒的過積載。

 

だから、もう、細かくは書かない。

うん。

詳細までは書かない。

書かない。

 

PowerAutomateの全体像の画像や、

各パーツでどんなことをしてるとか、

PowerAppsのここらへんにこんな感じで値をゲッツするとか、

そんくらいにする。

 

違う。

 

決して違う。

 

手抜きではない。

 

 手抜きではない。

 

これも読者の皆様の為を思ってのことなのである。

 

全部この記事の通りにして実装しても、

当然能力UPにはつながる。

でも、自分の頭で考えた方が絶対に君の力になるから。

すべてが君の力になる。

 

納得できたかい?

ありがとう。

 

じゃ行こうかベイベー。

 

1.ログインユーザー情報取得
 (PowerAppsの機能を使って、ログインしてるユーザーの情報をゲット)

 1-1.PowerAppsのホーム画面でユーザー情報を取得

簡単に書くね。

まず、これまでやってきたように、一個ギャラリーを追加してほしい。

で、追加したギャラリーの「Items」とゆープロパティに、

office365ユーザー.MyProfile()

という文字列を指定してくれ。

f:id:NagoyaITAdmin:20210629161829p:plain

追加したギャラリーに、ユーザー情報を表示させる。

すると、君の名前(表示名)が表示されたかな?

で、ギャラリーのレイアウトを文字列3行のこれに変更しよう。

f:id:NagoyaITAdmin:20210629162157p:plain

ギャラリーのプロパティ。「タイトル、サブタイトル、本文」

変更出来たら、
今後のメンテナンスの時とかをよく考えて、
ギャラリー名やらラベルの名前を君のセンスでちゃんと変更しよう。
例えばこんな感じ。

f:id:NagoyaITAdmin:20210629162356p:plain

ギャラリー名や各ラベルの名前の変更例。
後から変更するとだるいから、最初から変更しといた方が良いよ。

変更したら、実際に各ラベルに表示する内容を指定しよう。
どのラベルをどれにするかは関係ない。
それぞれの値さえ取得できてさえいれば大丈夫。

上の画像のUserIDStr、UserDisplayName、UserEMailの
それぞれに値を指定していく。

UserIDStr には ThisItem.Id

f:id:NagoyaITAdmin:20210629162756p:plain

UserIDStrのラベルの、Textの値。

UserDisplayName には ThisItem.DisplayName

f:id:NagoyaITAdmin:20210629162952p:plain

UserDisplayName のラベルの、Textの値。

UserEMail には ThisItem.Mail

f:id:NagoyaITAdmin:20210629163038p:plain

UserEMail のラベルの、Textの値。

こんな感じだ。

要領はわかってきたかい?
これまでのブログを読んでいてくれれば、
「あー何回かやったやつね、オーケイ楽勝」

となるだろう。

どう?

うまく出来た?

f:id:NagoyaITAdmin:20210629163832p:plain

それぞれ指定内容が正しければこんな感じになるはず。

もし、このユーザー情報をそのまま使いたいなら、
表示名とメールアドレスのラベルの位置とか変更したほうがいいかもね。
君のセンスが光るところだね。
これでひとまずログインユーザーの情報取得終わり。

 

 1-2.取得したユーザー情報からユーザー名(表示名)を表示させる。

これ。
覚えてる?
ラベル3個作ったの。 

f:id:NagoyaITAdmin:20210629164215p:plain

前回の記事。

 この3つのうちの2個目。

<ユーザー名>

って書いたラベルを、変更してほしい。

UserDisplayName.Text

に。

もうわかるね?
さっきと同じ様に Text の 値に上の文字列を指定するだけ。

これでPowerAppsを保存して、アプリとして起動したら、

もうデキちゃってる。

ユーザーの表示名をしっかりと表示。

f:id:NagoyaITAdmin:20210629164805p:plain

こんな感じで表示されてるべ

はい、じゃあ
 1.ログインユーザー情報取得

は、ここで終了。

簡単しょ。

君みたいな優秀な子なら本気出したら

5秒ありゃできるんだから。

 

2.スケジュールの取得

  (PowerAppsのホーム画面のボタンで、PowerAutomateを起動。
   ログインユーザーの24時間以内のスケジュールを3件ゲットして、
   またPowerAppsちゃんにデータを連携してあげる。)

 2-1.PowerAutomateを作成

わー。めんどくせ

大変そう。

まずは、ブラウザの新しいタブでもう一つTeamsの画面を用意してほしい。
当然新しいウィンドウを開くでもかまわない。

開いたら、同じ様に画面左でPowerAppsを選択してくれ。

開いた時点でPowerAppsが選択されている子がほとんどだと思うけど。
したら、画面の上の方にある「ビルド」を選択してね。

f:id:NagoyaITAdmin:20210629165807p:plain

新規タブで開いたブラウザで「ビルド」を選択。

ビルドを開いたら、アプリを作ってるチームに既にアプリ名が表示されてるから、

そこの下にある「すべてを表示」を押してくれ。

f:id:NagoyaITAdmin:20210629170131p:plain

ビルド画面で「すべてを表示」を選択する

すると画面が切り替わって、こんな感じになるから、
クラウドフロー」を押してくれ。

f:id:NagoyaITAdmin:20210629170324p:plain

「すべてを表示」を押したら表示される画面。

すると、作成されたクラウドフロー一覧の画面が表示される。

クラウドフローって言うのやめて欲しいよね。

PowerAutomateって書いてくれれば良いのに。

そう思うのは僕だけなんだろうか。

PowerAutomate以外にもここに表示される何かがあるのか?

教えて!

誰か!

 

さて、画面は移動できた?

当然、まだ作ってないから何も表示されないだろう。

f:id:NagoyaITAdmin:20210629170637p:plain

クラウドフローの一覧画面。何もない・・・よね?

もう作っちゃってる人は、なんでこんなブログを読んでくれているのか

マジで意味わかんない。

ありがとうございます神様。

これからもごひいきにしてくだせぇ。

よし。

ここまで来れた君たちならもうわかるね。

「+新規」で作成するんだよぉ!

とはいえ、ちゃんとこんな感じで

クラウドフロー」→「すぐに」と選んであげる必要はある。

f:id:NagoyaITAdmin:20210704095658p:plain

クラウドフローの新規作成方法。


どうかな?少し時間がかかってこんな感じのダイアログが表示されたかな?

f:id:NagoyaITAdmin:20210704095211p:plain

クラウドフロー(PowerAutomateのことね)の新規作成画面。

フロー名を入力して、トリガーを選択して、作成すればいい。

名前は、ちゃんとつけてあげようね。

何がいいかな。

 Ver1-24H以内のスケジュール取得

こんな感じでどうだろう。

今後バージョンアップする可能性を含めて僕はこんな感じにします。

 

まあ、名前なんでね。

別に「美紀」とか「アヤノ」とか「ちえみ」とかでも

何でもいいけどね。


トリガーにPowerAppsちゃんを指定してあげればそれで良い。

こんな画面がでたよね?

f:id:NagoyaITAdmin:20210704100105p:plain

PowerAutomateが作れたよー!

 

んでこれだけだと保存も出来ないの。

だから「新しいステップ」押して、
もう一回 PowerApps で検索して「PowerApp または Flow に応答する」を選択。

f:id:NagoyaITAdmin:20210629172217p:plain

新しいステップでPowerAppsを検索。「・・・に応答する」を選択しよう。

追加したら、保存する前にこれの中身も設定してもらいたいのね。

f:id:NagoyaITAdmin:20210709112051p:plain

「・・・応答する」の中身に、「テキスト」⇒「UserDataResult」⇒「UserScheduleResult」
みたいな感じで。

設定する中身は「UserDataResult」でなくても、

当然自分の好きな文字列でもかまわないんだけど、

これを設定してから保存しないと、最悪の場合

もう一度最初からこのPowerAutomateを作り直しになるから、

マジ気を付けて。

 

なんかよくわかんないんだけど、

PowerAppsとPowerAutomateの間で情報を連携する場合、

PowerAppsで利用するPowerAutomateを指定した瞬間の内容しか、

やり取りできないみたいなの。

ちょっとわかりづらいかな?

 

のび「ドラ○もーん、しずかちゃんとデートしたいんだけど着ていく服がないよー

   デートに着ていく服をちょうだいよー!」

ドラ「しょうがないなあ。じゃあ、篠原ともえのデビュー当時の服をあげるよ」

のび「ありがとう!さすがドラ○もんだぁ!じゃ、それ着て行ってくるね!」

 

のび「ドラ○もーん!よく考えたらデートの為のお金がないから

   お金も貸してー!」

ドラ「最初に言ってくれないとダメー。

   服ならまだ志茂田景樹の服には変更してあげれるけど。」

のび「そんなぁー!」

 

ってなるの。PowerAppsとPowerAutomateの関係は。

最初の時に欲しいものを全部指定しないと、後から追加してもダメなの。

世知辛いよね。

 

よし、じゃあ保存出来る様になってるから、保存しよう。

 

はい。

じゃあ、ここで 2-1は終了ね。

 

 2-2.PowerAppsからPowerAutomateに渡す情報を決める

小洒落たバーカウンターで、バーテンダーの方に

「何かオススメ頂戴」

と言ったところで映画の様に

「かしこまりました。」

・・・スッ

「どうぞ。ウィーウィルロッキューです。」

みたいな感じで何も聞かれずに、

いきなりファンタスティックなカクテルが提供されることは

現実ではほぼ無いんですよね。

 

大体は

「どういった物がお好みですか?」

と聞かれ、

「んーそうだねぇ、アルコールがキッツーイのがいいかな」

「フルーツは何でもお好きですか?」

みたいな応答をされるのが普通だと思うのね。

 

だから何ってわけじゃないんだけど、

PowerAutomateとPowerAppsの関係も

バーテンダーと初見の客みたいなモンなのよ。

PowerAutomateで自動化するのはいいんだけど、

自動化するにあたって必要な情報があるわけじゃんか。

 

今回でいうと、PowerAutomateで実行する時に、

目的のユーザー情報が欲しいわけ。

だから、PowerAppsからユーザーの情報を渡してあげる必要があるの。

今回依頼したいユーザーは、アキヒサという男で、

メールアドレスはこれで、AzureADのUserIDはこれで、

名古屋近辺に住む独身のアラフォーで、

最近の趣味は玉ねぎの皮をむく事です。

みたいな。

 

ね?

 

と、いうことで、まず最初に考えてみましょう。

今回必要な情報は何か。

今回PowerAutomateの目的は簡単に言うと

 「ユーザーのスケジュールを取得してくる」

だから、正直ユーザーのメールアドレスだけありゃ良い感じはするよね。

PowerAutomate側でGraph使ってユーザーIDとかユーザーの表示名とか

取得できるし。

ユーザーIDとかメールアドレスとかあれば、

Graphでユーザーのカレンダー情報取得できるし。

 

でも既にPowerApps側でわかってるなら、それを渡してあげちゃおっか。

と、いうことで

今回のPowerAutomateさんには、

さっきラベルに指定した

 UserIDStr、UserDisplayName、UserEMail

の3つの情報を与えてあげたいと思います。

よし、決まったね。

 

といったところで2-2は終了。

 

 2-3.PowerAutomateをガッツリ作りこむ

はい。

ここの項目名だけ見た時点で既に意味わかんなくなりはじめてる人向けに、
まず最初に自動処理するロジックの流れをお見せするね。

f:id:NagoyaITAdmin:20210701125926p:plain

PowerAutomateの処理の流れ。長いね。
でも、よーっく見て御覧。ほとんど「初期化」だから。
そうだね。作り方というか、作り手が悪いね。

わかったかな?

そうだね。

わかんないね。

 

整理して簡単に言ってみるね。

 ① PowerAppsでアクション実行

 ② PowerAppsで得た情報(今回はユーザー情報だけ)を
   変数的なものにぶちこむ

 ③ 色々な変数を初期化していく

 ④ ユーザーのスケジュール(今から24時間以内の分のみ)を取得してくる

 ⑤ スケジュール情報を、さらに3件までに絞込む

 ⑥ 3件のスケジュールの情報を分解して変数にぶちこむ

 ⑦ 変数をPowerAppsにぶん投げる

これだけ。

なんとなく理解できた?

すげぇな。

理解できたのかよ。

俺はここまでくるのに10年かかったよ。

 

ま、アレだけどね。

僕の場合 この地球に生まれてから 

ここまで到達するのに10年だからね。

君たちとは違うんだからね。

 

さて。

この部分だけど、大事なのは

 PowerApps側でPowerAutomate指定する前

 PowerAutomate側で、

  PowerAppsから受け取る情報を指定しておく

 と、いうことなの。

だから1個前の2-2で項目を決めたのね。

さっきのPowerAutomateの中でいうと

最初のこの部分。

f:id:NagoyaITAdmin:20210704083138p:plain

PowerAppsから情報を連携させるのに「JSON」を使うよ。

僕は、後からもっと追加する必要が出てきた時のために、
念のために余分なロジックを追加してる。

で。

JSON」?

はぁ?

JSONてなんやねん。

13日の金曜日に出てくるヤツ?

アイツが使うのPowerAutomateじゃなくて

チェーンソーじゃねぇ?

とか頭ん中が逃げ出そうとしている君に

安心してほしい。

いわゆる「データ」の持ち方を特定の型にハメただけのものである。

日本の企業の会社員の情報を例にするのであれば、

 

本社 に属する

 総務部 の中の

  部長 は

   アキヒサ で、

    メールアドレス はコレである

    趣味 は音楽である

   また、同じく

   ノブナガ も

    メールアドレス はコレである

    趣味 はゲームである

 

みたいな。

そんな感じ。

イメージはついたかな?

じゃあPowerAutomateで早速一つ追加してみよう。

f:id:NagoyaITAdmin:20210704085325p:plain

PowerAutomateで「JSONの解析」の追加。

 

選択したら、こんな感じになったと思う。

f:id:NagoyaITAdmin:20210704085449p:plain

JSONの解析を選択すると「コンテンツ」と「スキーマ」を入力するアレが出てくる。

ここでまずやってもらいたいことは、

素直にコンテンツやスキーマをいじろうとするんじゃなくて、

この四角の中の左上にある名前を変更して欲しいんだ。

f:id:NagoyaITAdmin:20210704085831p:plain

まず名前の変更をしてもらいたい。いや、別に必須ではないが。

え?変えたくない?

めんどくさい?

全然かまわない!

でも、後々見返す時とかにもっとめんどくさくなるかもしれないから、

個人的にはオススメ。

さて、じゃあいよいよコンテンツを設定しよう。

f:id:NagoyaITAdmin:20210704090220p:plain

コンテンツを選択。右に出てくるアレから、「PowerAppsで確認」をチョイス!

ちなみに、僕は名前をJSON1にしました。

はい「コンテンツ」欄はこれで終了。

次。

 

スキーマ

 

・・・?は?スキーマって何だよ。

っざっけんなよ。

わけわかんねぇ言葉使うなや!

そんなんで市民開発者に伝わると思ってんのか!?

わりゃナメとるといわすぞオラァ!

と、激高されてらっしゃる方もいらっしゃると思います。

僕も第一印象はそうでした。

でもね、アレなんです。

ざっくり申し上げると

「どんな感じで情報をくれるのか、教えてくれ」

って意味なんです。

 さっきの

 

本社 に属する

 総務部 の中の

  部長 は

   アキヒサ で、

    メールアドレス はコレである

    趣味 は音楽である

 

コレ。

これが無いとうまく情報取れないんだって、この子は。

手のかかる子だよ。

本当に。

 

今回は、僕はこんな感じで指定してあげました。

 

{

    "type""object",
    "properties": {
        "item1UserDisplayName": {
            "type""string"
        },
        "item2USerID": {
            "type""string"
        },
        "item3UserID2": {
            "type""string"
        },
        "item4EMail": {
            "type""string"
        }
    }
}

 

どうだい?見てわかるかな?

 item1UserDisplayName ってが変数の1個目。

 item2USerID ってのが、変数の2個目。

 item3UserID2 ってのが、変数の3個目。

 item4EMail ってのが、変数の4個目。

これを、PowerAppsから連携させるの。

ちな、全部 string って書いてあるから、数字でも日付でもなく、

ただの文字列ですってこと。

 

ついてこれてるかい?

 

上の{とか(とか)とか}がいっぱい書いてある文字列を、

コピーして貼りつけてくれて大丈夫だよ。

 

で、小心者の僕は、何かあったら嫌だから同じ様な

JSONの解析」をPowerAutomateでもう一個作ったのね。

f:id:NagoyaITAdmin:20210704093414p:plain

名前をJSON2にして、同じ様な内容のやつをもう一個。
スキーマの値も、item1をitem11、item2をitem12とかに変更してね。

これは別に要らないんだけど、なんとなく。

たまに・・・たまにだけど、

わけわからずうまくいかないことがあってさ。

もう一個おんなじようなヤツ作ったらうまくいったことあったから、

ビビりでない皆様は別に作る必要はありません。

 

「サンプルから生成」

ってボタンに関しては、僕の過去記事のどっかに使い方書いてあるから、

それを見てね!

 多分、ここらへんかな。

nagoyaitadmin.hatenablog.com

 

さて。スキーマに文字列入れたら、保存してみよう。 

できたかい?

そしたら、PowerAppsの開発画面は別のタブでまだひらいてるかな?

もう閉じてたら別のタブで開いておいてね!

で、最初のホームScreen(皆はScreen2とかのままかな?適当に名前は変えようね)

にある「スケジュール一覧へ」を押して、PowerAutomateを選択しよう。

f:id:NagoyaITAdmin:20210704101117p:plain

「スケジュール一覧へ」ボタンのOnSelectに、PowerAutomateを実行させる。

すると、さっき作っておいたPowerAutomateが表示されるはずだ。

 

選択してあげよう。

f:id:NagoyaITAdmin:20210704101255p:plain

作成済のPowerAutomateを選択しよう。

 

こんな感じで、中途半端な感じにOnSelectの値が入っているはずだ。

f:id:NagoyaITAdmin:20210704101421p:plain

PowerAutomate選択後の画面。

ここで、作ったPowerAutomateに合わせて連携する情報を

指定してあげる必要があるんだよね。

ここまで僕の言う通り、良い子にしてついて来てくれた皆は、

おそらく下の文字列をそのままコピペでイケルんじゃないかと思う。

 

== OnSelectに挿入する文字列 == 

Set(
UserSchedDataStr,{
StringData: 'Ver1-24H以内のスケジュール取得'.Run(
JSON(
{
item1UserDisplayName: UserDisplayName.Text,
item2USerID: UserIDStr.Text,
item3UserID2: UserIDStr.Text,
item4EMail: UserEMail.Text
}
),
JSON (
{
item11UserDisplayName: UserDisplayName.Text,
item12USerID: UserIDStr.Text,
item13UserID2: UserIDStr.Text,
item14EMail: UserEMail.Text
}
)
)
}
);

== ここまで ==

 

 

f:id:NagoyaITAdmin:20210704092633p:plain

HomeScreenの「一覧画面へ」ボタンのOnSelectに、PowerAutomateへの情報連携。

JSONを使って情報を渡してあげる。

 

さて、これも入れて保存したら、一度クリックしてみるといい。

PowerAutomate動くから。

f:id:NagoyaITAdmin:20210704102056p:plain

PowerAppsの開発画面で「Alt」キーを押しながらボタンをクリックすると、
さっき作ったPowerAutomateが動くよ!

どう?

押せた?

 

じゃ、見てみよう。

クラウドフロー一覧の画面から、今度は「詳細」を押してみよう。

f:id:NagoyaITAdmin:20210704102632p:plain

クラウドフローから「詳細」画面を開く

詳細画面が表示されたねえ。

f:id:NagoyaITAdmin:20210704103503p:plain

実行履歴の欄を見ると、実行履歴が出てるよね!
でてない?それはちゃんとボタンを押せてないんじゃない?
もっかい押してみよう。押してダメなら引いてみよう。
何を引けばいいのかは知らないけど。

 

早速実行履歴の日時のところをクリックしてみると、
実際にPowerAutomateが動いたことがわかる。

f:id:NagoyaITAdmin:20210704103709p:plain

キレイだね。

いや、画面がじゃないよ。君が。

君の笑顔がさ。


さらに、JSON1とかJSON2とかをクリックしてみると、
実際に値をどうやって連携されてきたかがわかる。

 

f:id:NagoyaITAdmin:20210704104355p:plain

JSON1を開いてみた。画像は黒塗りしてあるけど、みんなの画面には名前や

メールアドレスが表示されてるかな?されてるよね。

これでPowerAppsからの情報の連携方法はおわかりいただけただろうか。

また1つ、君のレベルが上がったね。

オジサンはうれしいよ。

AmazonミュージックでMr.Childrenの曲をランダムで流しながら
このブログを書いてるんだけど、CENTER OF UNIVERSE 流れて

ちょっと興奮してきちゃったよオジサンは。

 

で、ここから先は基本的に色んな変数を初期化してるだけだから、

自分で必要だと思う変数指定を適当に初期化祭りしておいてください。

初期化祭りの後、新しいステップでHTTPを選んで、

24時間以内のスケジュールを取得します。

f:id:NagoyaITAdmin:20210704105617p:plain

HTTPの中身。URIの値で24時間以内のスケジュールを取得するロジックを書いています。事前にAzurePortalでアプリケーション登録が必要だよ。

出たねー毎度おなじみMicrosoftGraphのお時間ですよ。

今回は、特定のユーザーのスケジュールを取得してくるだけなので、

比較的簡単だね。

 https://graph.microsoft.com/v1.0/users/で取得したユーザーID>/calendarview?StartDateTime=<@{utcNow()}>&EndDateTime=<@{addDays(utcNow(), 1)}>

※文字列の中の<>でくくってあるのは、式とか

f:id:NagoyaITAdmin:20210704110724p:plain

参考までに 変数の設定StartEndTimeUTC の中身。

StartDateTime=<@{utcNow()}> で今の日時を指定して、

EndDateTime=<@{addDays(utcNow(), 1)} で、

今から1日後の日時を指定してるんだね。

 

さて、みんな気付いてると思うけど、

事前にAzurePortalでアプリケーションの登録が必要だよ!

User.Read と Calendar.ReadWrite くらいかな。

これに関しても過去記事を読んでね!

 

nagoyaitadmin.hatenablog.com

 

 

nagoyaitadmin.hatenablog.com

 

んで、HTTPのステップは終わり。

次のステップでまたJSONの解析のステップを追加して、

コンテンツはHTTPの本文を指定して、

スキーマはこんな感じ。
== スキーマ ==

{
    "type""object",
    "properties": {
        "@@odata.context": {
            "type""string"
        },
        "value": {
            "type""array",
            "items": {
                "type""object",
                "properties": {
                    "@@odata.etag": {
                        "type""string"
                    },
                    "id": {
                        "type""string"
                    },
                    "createdDateTime": {
                        "type""string"
                    },
                    "lastModifiedDateTime": {
                        "type""string"
                    },
                    "changeKey": {
                        "type""string"
                    },
                    "categories": {
                        "type""array"
                    },
                    "transactionId": {},
                    "originalStartTimeZone": {
                        "type""string"
                    },
                    "originalEndTimeZone": {
                        "type""string"
                    },
                    "iCalUId": {
                        "type""string"
                    },
                    "reminderMinutesBeforeStart": {
                        "type""integer"
                    },
                    "isReminderOn": {
                        "type""boolean"
                    },
                    "hasAttachments": {
                        "type""boolean"
                    },
                    "subject": {
                        "type""string"
                    },
                    "bodyPreview": {
                        "type""string"
                    },
                    "importance": {
                        "type""string"
                    },
                    "sensitivity": {
                        "type""string"
                    },
                    "isAllDay": {
                        "type""boolean"
                    },
                    "isCancelled": {
                        "type""boolean"
                    },
                    "isOrganizer": {
                        "type""boolean"
                    },
                    "responseRequested": {
                        "type""boolean"
                    },
                    "seriesMasterId": {},
                    "showAs": {
                        "type""string"
                    },
                    "type": {
                        "type""string"
                    },
                    "webLink": {
                        "type""string"
                    },
                    "onlineMeetingUrl": {},
                    "isOnlineMeeting": {
                        "type""boolean"
                    },
                    "onlineMeetingProvider": {
                        "type""string"
                    },
                    "allowNewTimeProposals": {
                        "type""boolean"
                    },
                    "isDraft": {
                        "type""boolean"
                    },
                    "recurrence": {},
                    "onlineMeeting": {},
                    "responseStatus": {
                        "type""object",
                        "properties": {
                            "response": {
                                "type""string"
                            },
                            "time": {
                                "type""string"
                            }
                        }
                    },
                    "body": {
                        "type""object",
                        "properties": {
                            "contentType": {
                                "type""string"
                            },
                            "content": {
                                "type""string"
                            }
                        }
                    },
                    "start": {
                        "type""object",
                        "properties": {
                            "dateTime": {
                                "type""string"
                            },
                            "timeZone": {
                                "type""string"
                            }
                        }
                    },
                    "end": {
                        "type""object",
                        "properties": {
                            "dateTime": {
                                "type""string"
                            },
                            "timeZone": {
                                "type""string"
                            }
                        }
                    },
                    "location": {
                        "type""object",
                        "properties": {
                            "displayName": {
                                "type""string"
                            },
                            "locationType": {
                                "type""string"
                            },
                            "uniqueIdType": {
                                "type""string"
                            },
                            "address": {
                                "type""object",
                                "properties": {}
                            },
                            "coordinates": {
                                "type""object",
                                "properties": {}
                            }
                        }
                    },
                    "locations": {
                        "type""array"
                    },
                    "attendees": {
                        "type""array",
                        "items": {
                            "type""object",
                            "properties": {
                                "type": {
                                    "type""string"
                                },
                                "status": {
                                    "type""object",
                                    "properties": {
                                        "response": {
                                            "type""string"
                                        },
                                        "time": {
                                            "type""string"
                                        }
                                    }
                                },
                                "emailAddress": {
                                    "type""object",
                                    "properties": {
                                        "name": {
                                            "type""string"
                                        },
                                        "address": {
                                            "type""string"
                                        }
                                    }
                                }
                            },
                            "required": [
                                "type",
                                "status",
                                "emailAddress"
                            ]
                        }
                    },
                    "organizer": {
                        "type""object",
                        "properties": {
                            "emailAddress": {
                                "type""object",
                                "properties": {
                                    "name": {
                                        "type""string"
                                    },
                                    "address": {
                                        "type""string"
                                    }
                                }
                            }
                        }
                    }
                },
                "required": [
                    "@@odata.etag",
                    "id",
                    "createdDateTime",
                    "lastModifiedDateTime",
                    "changeKey",
                    "categories",
                    "transactionId",
                    "originalStartTimeZone",
                    "originalEndTimeZone",
                    "iCalUId",
                    "reminderMinutesBeforeStart",
                    "isReminderOn",
                    "hasAttachments",
                    "subject",
                    "bodyPreview",
                    "importance",
                    "sensitivity",
                    "isAllDay",
                    "isCancelled",
                    "isOrganizer",
                    "responseRequested",
                    "seriesMasterId",
                    "showAs",
                    "type",
                    "webLink",
                    "onlineMeetingUrl",
                    "isOnlineMeeting",
                    "onlineMeetingProvider",
                    "allowNewTimeProposals",
                    "isDraft",
                    "recurrence",
                    "onlineMeeting",
                    "responseStatus",
                    "body",
                    "start",
                    "end",
                    "location",
                    "locations",
                    "attendees",
                    "organizer"
                ]
            }
        }
    }
}

==== 

そしたら、あとは2ステップ!

f:id:NagoyaITAdmin:20210704111836p:plain

ここまできたらあともうちょいだね。

 

と思いきや、作りこみ次第ではあるけど、

「取得したスケジュールの件数分ループ処理」

のApplyToEachの中が大変。

f:id:NagoyaITAdmin:20210704112259p:plain

ApplyToEachの中身。色々。説明しづらい。

 

しかも、Exchangeの予定だとキャンセルされたイベントとかの情報も

削除していないと情報取得してきちゃうから、

キャンセルかどうかの判断を入れたりすると、

さらに分岐が多くなって複雑化する。

どこまで作りこむかは、アナタ次第。

 

とりあえず最低限やっておかなきゃいけないことは、

 ① 件数のカウント

 ② 件数が3件目以内なら情報取得。4件目以降はループ抜ける。

 ③ スケジュールの「分類」の値を取得

 ④ 分類に複数の値が入っていた場合、何かしらの区切り文字で結合
   ( A分類$$B分類$$C分類 みたいに$$で区切ったり。)
   ってか、分類をそんなに複数持たすユーザーは少ない気がするけど。

 ⑤ イベントの開始時刻とか終了時刻とか件名とかイベントIDとかを取得

 ⑥ 1~3件目の情報をまた特別な区切り文字でくっつける。
   <1件目のイベント情報>‘<2件目のイベント情報>‘<3・・
      

こんくらいかな。

 

さ、次いこ。

最後かな?

f:id:NagoyaITAdmin:20210704113604p:plain

PowerAutomateの最後。PowerAppsへ情報を渡してあげる。

僕は最初に UserScheduleResult って変数を初期化して、

1~3件目のスケジュールイベント取得時にこの変数に対して

情報を文字列として追加していきました。

だから、最後はその UserScheduleResult を渡してあげるだけ。

あとはPowerAppsちゃんで、文字列の分解やら何やらをやってもらうことにしました。

パフォーマンス的には、どっちのがいいんだろうか。

 UserScheduleResult1

 UserScheduleResult2

 UserScheduleResult3

みたいにそれぞれのイベント毎に一つの文字列として渡してあげるとか

の方がいいのかもね。PowerAppsでの文字列分解もそっちのが良い気もする。

はい、PowerAutomate終わり(半ば強制的に終わり)。

 

 2-4.PowerAppsのボタンにPowerAutomateを起動する様にしてあげる

はい。これね。

これ、実はさっきヤっちゃたよねー(笑)

OnSelectに書いたやつね。

じゃあ、ここでは更にPowerAutomateから渡された情報を、

このPowerAppsのCollection

(んーなんて説明すればいいかな。箱?パーテーション付の箱)

に入れることをやってみましょう。

 

== コレクションに入れる == 

//UserSchedDataForViewを`で区切り

ClearCollect(
UserSchedDataForView,
Split(
AutomateOutPut.Text,
"`"
)
);

== ここまで ==

 

ClearCollect で仮に今、昔の情報が入ってても一かい全部箱から出して、

もう一回入れるってことをします。

Split で、一つの文字列を複数のパーティション毎に分けて入れます。

僕の場合は、`(バックコーテーション)を区切り文字にしてます。

 

 

 2-5.PowerAutomateから受け取った情報を、そのままだと使いづらいから
     色々加工して、PowerAppsのビュー画面に表示させる。

さて。実は、僕のロジックだと、どうしても3件のデータが欲しいにもかかわらず、

最後に一つ空白の4件目が発生してしまうのね。

やり方が悪いのかもしれないけど。

だから、最後の4件目をぶっ殺してあげます。

 

== 4件目のデータを削除る ==  

//最後にできてしまう、不要な空白データを削除

Remove(
UserSchedDataForView,
Last(UserSchedDataForView.Result)
);

== ここまで ==

 

じゃあ事前準備完了。

あとは、データを必要なフィールドに表示させてあげるだけ。

まずは、別のテーブル(表)にデータを入れてあげます。

 

== 3件のデータを新しいテーブルにセット ==  

ClearCollect(
UserDataCol,
{
No: "1",
Title: '1stSched-Title1'.Text,
StartTime: '1stSched-StartTime1'.Text,
EndTime: '1stSched-EndTime1'.Text,
DocID: '1stSched-SchedID1'.Text,
Categories: '1stSched-Categories1'.Text
},
{
No: "2",
Title: '2ndSched-Title1'.Text,
StartTime: '2ndSched-StartTime1'.Text,
EndTime: '2ndSched-EndTime1'.Text,
DocID: '2ndSched-SchedID1'.Text,
Categories: '2ndSched-Categories1'.Text
},
{
No: "3",
Title: '3rdSched-Title1'.Text,
StartTime: '3rdSched-StartTime1'.Text,
EndTime: '3rdSched-EndTime1'.Text,
DocID: '3rdSched-SchedID1'.Text,
Categories: '3rdSched-Categories1'.Text
}
);

== ここまで ==

 

はい。

よく出来ました。

 

あとは、この値をそれぞれのフィールドに指定してあげるだけ。

でも、どうせならもう一個。

もう一行だけボタンのOnSelectの最後の行に書いてあげよう。


Navigate(ScheduleView)

 

そうね。 

「一覧へ」ってボタンなんだから、画面遷移がないとヒドイよね。

 

 

あーーーーー!

疲れたーーーーー!

と、ゆーことで、今回はここで終了!!!

 

次回は続きをやっていくよ!

3.管理者用画面

 (管理者画面を加工して、凡例の色を指定出来る様にする)

 3-1.DataVerseに新しいテーブルを作る

 3-2.Screen1の画面にDataVerseの各フィールドの値を指定する

4.ビュー画面

 (DataVerseにある凡例の情報をギャラリーに表示させて、

  2-3のPowerAutomateでとってきた情報をギャラリーに表示)

 4-1.DataVerseにある凡例のテーブル情報をギャラリー1に表示

 4-2.PowerAutomateで取得したスケジュール情報の値をギャラリー2に指定する 

5.フォーム画面

 (ビュー画面で選択した情報を表示して、
  変更させたい凡例の色を選択させる。)

 5-1.ビュー画面で選択された情報を、加工してフォーム画面に表示

 5-2.凡例のギャラリーに、PowerAutomate起動用の四角形を付ける

 5-3.データ加工用のPowerAutomateを作る(最初の方だけ)

 5-4.ギャラリーに追加した四角形のOnSelectかなんかに、
     PowerAutomate起動用のロジックを書く

 5-5.PowerAutomateをめちゃくちゃする

 5-6.PowerAutomateで変更した内容を、DataVerseに保存ぬ

 5-7.DataVerseに保存した値をフォーム画面に表示させる

 

 

 

あばよ!

~~~ 本 題 終 了 ~~~

 

 

その1 ー 前々回。作りたいシステムを発表。

その2 ー 前回。PowerAppsのロジックの作りこみは別にするかもしれないけど
         とりあえず画面周りをそれっぽくする。

         ここまではノーコードで出来たね!

その3 ー 今回。PowerAutomateでの色々。

         PowerAppsと、PowerAutomateでの色々。
          ここが下手すると2週にわたるかもしれないね。
          軽く考えてみても条件分岐とかややこしそう。

         このあたりが一番のハード回。ローコードが必要な部分。

その4 ー 次回。全体的に色々と整える感じ?
           よく考えると履歴データの配置場所とかも事前に
           キメておかなきゃ・・・

          今回の続きだよ!

その5 ー 次々回。なんだろう。打ち上げパーリーでもしようか。

            各自、つけてみそかけてみそを持参の上、

           みそパしよ。みそパ。

 

 

 

いやあ、どうだい?

読むほうも疲れただろうけど、

書いてるこっちだって疲れるんだぜ?

もう僕のHPは残り3です。

今オオナメクジに出くわして攻撃1発くらったら

死ぬかギリギリ生きれるかという状態です。

 

来週も生きてたらまた会いましょう。