rksoftware

Visual Studio とか C# とかが好きです

Power Automate で null の動作を確認する

Power Automate の関数には引数に null を渡すとエラーになる関数があります。null を入れたときの挙動はドキュメントに記載されないようで、関数を使うときには事前に null を入れたときの挙動を確認しておく必要があります。

■ null の入れ方

式で null と書くことで null を入れられます。

こんな感じです。

lengh 関数は null を受け取るとエラーになるので、こんな感じになります。

InvalidTemplate. Unable to process template language expressions in action '作成' inputs at line '0' and column '0': 'The template language function 'length' expects its parameter to be an array or a string. The provided value is of type 'Null'. Please see https://aka.ms/logicexpressions#length for usage details.'.

■ null を回避する

データとして null が入ることは頻繁にある通常の動作です。そのたびに例外処理を行うのは現実的ではありません。そこで null をゼロ文字の文字列や数値の 0 に置き換える処理を書くことで回避する式を頻繁に書くと思います。
今夏感じで書けばいいかなと思います。

文字列の場合

文字列の場合はシンプルです。string 関数が null を入れても動作するので次のように string 関数を通せば null がゼロ文字の文字列になって動作します。

length(string(null))

数値などの場合

数値などの場合は少し厄介です。変換関数は使えないので、equals 関数と if 関数を使います。
ここの例では、この式を書く前に処理として 作成 という名前の処理で値を作っている想定です。

if(equals(outputs('作成'), null), 0, outputs('作成'))

■ null を outputs にしたい場合の注意

式に書かなければなりません。直接書くと保存時にエラーになります。こんな感じに。

The workflow run action '作成' of type 'Compose' has a missing 'inputs' property.

通る書き方はこんな感じです。

この時のコードはこうなっています。

"inputs": "@null",

■ 難しいですね

難しいですね。

WinUI 3 と Computer Vision、Power Aotomate でスタバ

エンジニアとは「スタバ」する生き物です。そしてエンジニアとは物事にきちんと理解し知性を持って取り組むものです。

しかし、我々は「スタバ」を理解しているといえるのでしょうか?

十分理解しているとは思います。しかしそれを客観的事実を持って伝えられるでしょうか? 結構そこまでは難しいと思います。そこでエンジニアらしく技術で分析してみます。

■ 概要

「スタバ」ツイートを検索し、それらのツイートの感情 (ポジティブかネガティブか) と「スタバ」ツイートに添付されている写真に写っているものを AI を使って解析するアプリを作成します。

アプリの完成イメージ

■ 構成

  • アプリの UI は WinUI 3 で作成する Windows GUI アプリを作ります。
  • ツイートの感情の分析は Azure の Cognitive Service を使用し AI による分析を行います。
  • 写真の解析に Azure の Computer Vision を使用し AI による分析を行います。
  • これらの分析の実行を Power Platform の Power Automate により行います。

■ 導入記事

これから詳細を綴って行きますが、以前にこの内容で登壇を行った際の記事があります。まずはこちらを見ていただくのも良いかもしれません。

rksoftware.hatenablog.com

Windows GUI アプリの作り方 (WinUI 3)

Windows という OS はやはり Window つまり GUI アプリの作りやすさが特徴でしょう。
歴史としては Visual Basic の存在が非常に大きかったような話を聞きます。しかしそんな Visual Basic も今はあまり使われなくなったと聞きます (まだまだ現役ではありますが)。では現行技術はなんでしょう? そう、WinUI 3 です。

■ WinUI 3

最近までは .NET 技術で Windows デスクトップアプリを作るには二つの選択肢がありました。UWP と WPF です。WinUI はそれに並ぶ新たな選択肢で、WPF と UWP に置き換わるものです。

■ アプリの作り方

WinUI 3 アプリを作るのは簡単ですが少し手間です。
まず手間である理由です。通常 Visual Studio で作ります。これが手間です。まあ、どうせ作った後、Visual Studio でコードも書いていく事が大半だと思うので手間とも思わないことが多いでしょうけれども。
何故手間かというと、dotnet コマンドで現時点では作れないようなので。WPF も何でも最近は dotnet コマンドで作っていたので。

簡単である理由は Visual Studio で作れるからです。画面をポチポチして、プロジェクトのテンプレートで WinUI 3 を選択するだけです。

WinUI 3 で GUI をつくる

WinUI 3 で GUI を作るのは簡単です。現行世代の .NET デスクトップアプリを作る技術である WPF や UWP と同じ XAML という XML で作ることができます。
XAML を使わずにコードで書いても良いのですが、おそらく XAML が圧倒的に多数派だと思います。

■ XAML

参考

参考情報は WPF ですが、構文はかわりません。コントロールが少し違いますが、同じ (名前空間が違ったりはしますが) コントロールがかなり多くあります。

■ こんな UI

ゴールとしてはこんな UI が作りたいと思っています。

一番上に JSON 文字列を入力する文字列入力の枠があります。
その下に 「 click 」 と書かれたボタンがあります。
さらにその下の領域全面に Web ページ (HTML ファイル) を表示する領域があります。

使い方としては JSON 文字列を貼り付けてボタンを押すと、内容を分析/整形して HTML を作成し、表示するアプリです。

■ XAML

こんな感じで 3 つのコントロールを並べた UI は非常に簡単に作れてしまいます。

<Window
    x:Class="stabuwinui3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:stabuwinui3"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" x:Name="textBox" AcceptsReturn="True" Height="100"/>
        <Button Grid.Row="1" Content="click" Click="Button_Click" />
        <WebView2 Grid.Row="2" x:Name="webView2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
    </Grid>
</Window>

こんな感じです。
自分で書いている部分は

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" x:Name="textBox" AcceptsReturn="True" Height="100"/>
        <Button Grid.Row="1" Content="click" Click="Button_Click" />
        <WebView2 Grid.Row="2" x:Name="webView2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />

の部分だけで、他はプロジェクトテンプレートでプロジェクトを作っただけで既に書かれています。

WinUI 3 の動作を作る

WinUI 3 で動作を作るのは簡単です。現行世代の .NET デスクトップアプリを作る技術である WPF や UWP と同じ手法で作ることができます。

■ ご注意

今回は、説明をも短くするために、望ましくない作り方をしています。望ましい作り方をすると説明しなければならないことの量が少々増えてしまいますので。今回書く書き方で実際のコードを書く方は非常にレアで、通常まずありえないと思います。その点をご注意になってお読みください。

■ 完成コード

using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace stabuwinui3
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
        }

        class Score
        {
            public decimal positive { get; set; }
            public decimal neutral { get; set; }
            public decimal negative { get; set; }
        }

        class Stabu
        {
            public string Id { get; set; }
            public string MediaUrl { get; set; }
            public Score Score { get; set; }
            public List<string> Objects { get; } = new();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var json = System.Text.Json.JsonSerializer.Deserialize<dynamic[]>(textBox.Text);
            IList<Stabu> stabus = ToStabus(json);
            // スコア
            decimal positive = stabus.Average(stabu => stabu.Score.positive);
            decimal neutral = stabus.Average(stabu => stabu.Score.neutral);
            decimal negative = stabus.Average(stabu => stabu.Score.negative);
            // オブジェクト
            KeyValuePair<string, int>[] objects = stabus.SelectMany(stabu => stabu.Objects).GroupBy(obj => obj).Select(objs => KeyValuePair.Create(objs.Key, objs.Count())).OrderByDescending(obj => obj.Value).ToArray();
            // HTML 化
            string html = ToHtml(stabus, positive, neutral, negative, objects);
            // ファイルに保存
            string saveFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Environment.ProcessPath), $"{Environment.TickCount64}.html");
            System.IO.File.WriteAllText(saveFilePath, html);
            // 画面に表示
            webView2.Source = new Uri(saveFilePath);
        }

        private IList<Stabu> ToStabus(dynamic[] json) =>
            json.Aggregate(new List<Stabu>(), (stabus, m) =>
                {
                    var value = m.ToString();
                    var stabu = stabus.LastOrDefault();
                    if ("----------" == value) { stabus.Add(new()); return stabus; }
                    if (stabu.Id == null) { stabu.Id = value; return stabus; }
                    if (stabu.MediaUrl == null) { stabu.MediaUrl = value; return stabus; }
                    if (stabu.Score == null) { stabu.Score = System.Text.Json.JsonSerializer.Deserialize<Score>(value); return stabus; }
                    stabu.Objects.Add(value);
                    return stabus;
                }
        );

        private string ToHtml(IList<Stabu> stabus, decimal positive, decimal neutral, decimal negative, IEnumerable<KeyValuePair<string, int>> objects) =>
@$"
<html><body>
positive:{positive}<br />neutral:{neutral}<br />negative:{negative}<br/><br />{string.Join("", objects.Select(obj => $"{obj.Key}:{obj.Value}<br/>"))}
<br /><table>
{string.Join("", stabus.Select(stabu => @$"
<tr><td><div style=""height: 175px; overflow:hidden;""><iframe height=350 style=""transform: scale(0.50);transform-origin: 0 0;"" src=""https://platform.twitter.com/embed/Tweet.html?id={stabu.Id}""></iframe></div></td>
<td>positive:{stabu.Score.positive}<br />neutral:{stabu.Score.neutral}<br />negative:{stabu.Score.negative}</td>
<td>{string.Join("<br />", stabu.Objects)}</td></tr>
"))}
</table>
</body></html>";

    }
}

ちょっと、長く見えるかもしれませんがブログのフォーマットで行間が広いだけです。実際は 84 行しかありません。画像で見るとこんな感じです。

JSON 文字列をパースして中のデータを集計/整形して HTML ファイルを作成して表示する。結構油断ならない難しい処理だと思います。しかし、こんなに短いコードで実現できてしまうのです。いいでしょ。

Power Automate の始め方 (ライセンスの説明)

Power Automate を使うのは意外と難しいです。

■ 始め方

整っていれば Power Automate のホームページに行けば簡単に作り始められます。

Power Automate のホームページ

https://japan.flow.microsoft.com/ja-jp/

■ 何が難しいの?

ライセンスです。コミュニティライセンスのようなものがないので、購入するか期間限定の試用期間を使うことになるようです。
ここが果てしなく高いハードルです。並大抵の覚悟ではここで挫折すると思います。

仕事で試すなら買って試せばいいのですが、普通は個人が自分のスキルとして個人的に自習するのが現代では基本ですから、これは厳しい制約です。どうしても学習が後回しになって、無限に後回しになって名前は知っていても結局導入には至りません。私もそうなります。でも頑張りましょう! Power Automate にはそこまでして頑張る価値があります!

※ 私は偶然個人でライセンスがあったので今回使ってみました。

■ ライセンス

※この項目は私が公開情報を見てそう読んだ、というだけの情報です。実際にはサービスの提供元にお問い合わせください。

情報は価格のページではなくこちらが詳しいようです。少なくとも私の知りたいことは価格のページではなくこちらに掲載されていました。 ちなみに価格はこちら 毎月ユーザーあたり 1,630 円。too expensive。高級品ですね。

ライセンスとしては、価格のページではなく「Power Automate ライセンスの種類」ページの方が重要です。次の 2 種類のプランがある事がわかります。

違いは、スタンドアロン プラン は前述の月額料金を払うライセンスで、シード プラン は別の製品のライセンスを持っている人についているライセンスです。人によっては シードプラン なら持っている可能性は十分にあるでしょう。私も Microsoft 365 を持っているのでこのプランを持っていたようです。

プランの重要な違い

この シードプラン であれば敷居は低く持っている方も少なくないでしょう。完全な一般人である私も持っていました。しかし、油断しないでください。2 つのプランには プレミアム コネクタ が使えるかどうかという大きな違いがあります。

スタンドアロン プラン では プレミアム コネクタ が使えます。シード プラン えは使えません。

コネクタ とはフローに配置できる機能 (処理) のようなもので、例えば「メールを送信する」とか「Web サービスから情報を取得する」とかそういうやつです。シード プラン ではこの コネクタ に使えないものがあります。使えるものだけで取り敢えず......そう考えていた時期が私にもありました。実際にはこの制限のため シード プラン は機能の制限された評価版と思った方が良さそうです。

※業務で使う場合は、Microsoft 製品とは シード プラン で使える コネクタ も割と使えるので活用はできると思います。個人の IT エンジニアが色々と遊ぶにはかなり大きな制約になっています。

プレミアム コネクタ

これが使えないと厳しいという プレミアム コネクタ を個人で学習する IT エンジニアの目線でいくつか選んでみました。

全一覧

まず プレミアム コネクタ の一覧はこちらです。

使えないと厳しい

これが使えないと厳しいという プレミアム コネクタ を選ぶと言いましたがあれは嘘です。
実際にフローの編集画面では出てくるのにコネクタの一覧に見つからないのです。HTTP という コネクタ? アクション? です。要は HTTP のリクエストを送信する機能で、これがないと色々試したい情報のソースにアクセスできません。
コネクタのないサービスとか、Web サイトとか......。

一覧に載っている中だと Azure DevOps はとても使いたいですが、最近は個人では GitHub 優勢ですしね。

トリガーにも

トリガー とは Power Automate が実行されるきっかけです。ここにも プレミアム 限定のモノがあります。
前述の Azure DevOpsプレミアム です。「コードのプッシュ時」「ビルドの完了時」「プル要求が作成されたとき」「プル要求がクローズしたとき」非常に魅力的です。しかし プレミアム です。

他にも 「HTTP Webhook」、「HTTP 要求の受信時」 このあたりも非常に使いたいです。

つまり

別のプログラムや Web の資源と連携した事をしなければ、スタンドアロン プラン が必要ということです。

■ 今回の記事では

ということで、今回の記事では シード プラン の範囲でやっていきます。

しかし実際には プレミアム が使いたいところを我慢しているのが実際です。優先順位の問題で先になるかもしれませんが後で プレミアム なエンジニアになって試してみたいと考えています。

Power Automate のフローを作る

Power Automate のフローを作ります。

■ 始め方

整っていれば Power Automate のホームページに行けば簡単に作り始められます。

Power Automate のホームページ

https://japan.flow.microsoft.com/ja-jp/

■ 作成

左のナビゲーションメニュの 「 作成 」 を選択します。

インスタント クラウド フロー 」 を選択します。

可能であればこうしたかったが......

可能であれば 「 テンプレートから始める 」 で既にフローの組まれたテンプレートから始めたいところですが、今回は残念ながら近い動作のテンプレートから始めることができません。「 ツイートの感情分析を実行して結果を Power BI データセットにプッシュする 」 というやりたいことの一部に近いテンプレートもあるのですが、残念ながら Power BI のライセンスがないと選択しても 「 作成 」 ボタンをアクティブできないようです。

■ 作成

インスタント クラウド フロー 」 を選択するとポップアップでトリガーする方法の選択になります。
手動でフローをトリガーします 」 を選択します。

可能であればこうしたかったが......

可能であれば 「 HTTP 要求の受信時 」 で作りたいところです。実際選択してこんな感じでフローを組めば保存もすることができます。
しかし残念ながら HTTP 要求の受信時 トリガーはプレミアムなトリガーのため、プレミアム プランのライセンスでないとフローをオンにできないようです。

■ フローを保存する (失敗する)

インスタント クラウド フロー 」 を選択するとフローの編集ページになります。

この状態ではまだフローは作成されておらず、このぺーじから離脱すると何もなかったことになってしまいます。そこでまずは 「 保存 」 ボタンでフローを保存したいところです。
しかしこの状態ではエラーになってまだ保存できません。

■ ステップの追加

簡単ステップを追加して保存できるようにしていきます。
新しいステップ 」 を選択します。

コネクタとアクションを検索する 」に 「 作成 」 と入力します。その後 「 組み込み 」 を選択します。そして 「 作成 」を選択。

入力 」 が必須なのでひとまず何か文字列を設定します。今回は 「 ああああ 」 と設定してみます。

■ フローを保存する

保存 」 を選択します。

フローを保存できました。

Power Automate のフローの完成図

Power Automate のフローを組んでいきます。
組むという表現が正しいのか分かりませんが、四角と置いて繋いでいくので組み立てる的な表現で良いかなと思いました。

■ ゴール

こんなフローを組み上げていきます。

■ でかい

でかい

正直でかいですよね。この全体画像を撮るのも一苦労です。実は Power Automate の編集ページの作りのために Web ブラウザのページ全体キャプチャではこの画像は作れません。
そこは力で乗り越えましょう。鍛えていればたいていのことは力で乗り越えられます。

■ パワー!

力とはこういうことです。 rksoftware.hatenablog.com

簡単ですね。

■ アクションの追加操作

でかい全体図の内番上の一個目の箱をトリガーといいます。二つ目以降はアクションです。 ここからアクションを追加していくのですが、アクションの編集はわかりにくいものの画像付きの公式ドキュメントがあるので見ておいてもいいと思います。
docs.microsoft.com

追加するだけなら以前の手順でもすでにやっています。

■ これまでの手順で

これまでの手順で次のように 2 個箱がある状態になっていることになっています。

ここから順次やっていきます。まずは前回作ったフローの名前を変えましょう。

■ フローの詳細ページを表示する

左ペインのメニューで [ マイ フロー ] を選択、右ペインで以前の手順で作ったフローをクリックします。

開かれたページで詳細の編集領域を表示します。[ 編集 ] をクリックします。編集は複数個所にあるので間違えないよう注意してください。

[ フロー名 ] を変更して [ 保存 ] します。今回は 「 スタバ警察 」とでもしておきましょう。

これで名前が変更できました。

Power Automate のフローのアクションを削除する

Power Automate のフローを組んでいきます。
組むという表現が正しいのか分かりませんが、四角と置いて繋いでいくので組み立てる的な表現で良いかなと思いました。

■ メニューから削除

フローの編集ページを開きます。

削除するアクションの右端の 「 ・・・ 」 をクリック、ポップアップメニューで [ 削除 ] を選びます。

[ OK ]

削除されました。

Power Automate のコネクタで使用する Azure の Computer Vision と Azure Cognitive Service を用意する

Power Automate のフローを組む事前準備をしていきます。

これからフローを追加していくのですが、ここで事前準備をしておきます。画像を解析する Azure のサービスや Tweet の感情を解析するための Azure のサービスを呼び出すコネクタは Azure で事前に用意をしておく必要があります。
今回は、Azure の Portal で作業をします。

■ Azure Portal

Azure Portal にアクセスしてサインインします。
https://portal.azure.com/

■ Computer Vision の用意

Computer Vision のリソースを作成します。

Azure Portal の画面の左上の 「 リソースの作成 」 から。

この辺りは今後のバージョンアップで変わる可能性が高いですが、今のところは 「 AI + Machine Learning 」 > Computer Vision の 「 作成 」 。

作成画面ではそれらしく設定をしてください。

設定を完了して作成を始めてもすぐには作成されません。少し待ち時間があります。皆さん大好き Twitter タイムのしましょう。すぐ出来上がります。

出来上がったら 「 リソースに移動 」 。

ここの 「 エンドポイント 」 の値を把握しておきましょう。コネクタを設定する際に把握しておく必要があります。
※ここで覚えておく必要はありません。コネクタの設定をするタイミングでまた見に来れば OK です。

キーを管理するにはここをクリック 」 。

各種キーとエンドポイントが確認できます。ここの 「 キー1 」 と 「エンドポイント」 をコネクタの設定時にコピペします。右端のアイコンでコピーできます。
※コネクタの設定をするタイミングでまたコピーしに来てください。

Computer Vision の事前準備ができました。

■ Azure Cognitive Service の準備

Computer Vison と同じように Azure Cognitive Service のリソースも作成します。今度は テキスト分析 の 「 作成 」 です。

キーの扱いも同様です。
※コネクタの設定をするタイミングでまたコピーしに来てください。

Azure Cognitive Service の事前準備ができました。

Power Automate の変数を宣言する

Power Automate のフローを組んで行きます。

まずフローの先頭でフローで使う変数を宣言します。変数はフローの先頭で宣言するのが一番スタンダードだと思います。 rksoftware.hatenablog.com

■ 変数を 3 つ追加

次の 3 つのステップを追加します。

コネクタ アクション 名前 種類 ステップの名前
変数 変数を初期化する results アレイ [] 配列変数 results (解析結果を格納する)
変数 変数を初期化する tweet 文字列 変数 tweet (現在処理中のツイート本文を格納する)
変数 変数を初期化する mediaurl 文字列 変数 mediaurl (現在処理中の画像の URL を格納する)

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。
※ 3 つの変数を同じ手順で追加します。

[ + 新しいステップ ] をクリックします。

検索枠に 「 変数 」と入力し、[ 組み込み ] をクリック。[ 変数 ] をクリック。[ 変数の初期化 ] をクリックします。

前述の表の内容を [ 名前 ] 、[ 種類 ] 、 [ ] に入力します。

[ ・・・ ] をクリック、「 名前の変更 」 をクリックします。

入力枠に前述の表を参考にステップの名前を入力します。

この手順を繰り返し 3 つの変数を宣言します。

Power Automate で Twitter コネクタを使う

Power Automate のフローを組んで行きます。

Twitter から情報を取得します。Twitter コネクタを使用して Tweet を検索して値を取得するところまで行きます。

■ 「Twitter」 コネクタの 「ツイートの検索」 をアクションを追加

次の 1 つのステップを追加します。

コネクタ アクション 検索テキスト ステップの名前
Twitter ツイートの検索 スタバ from:mishi_cs filter:images ツイートの検索

こんな感じの部分です。

検索テキストについて

今回の例では、私のツイートから画像付きのツイートで「スタバ」というテキストを検索しています。皆さんが試す際には from: のところを皆さんのアカウントに変更してください。変更しなくてもいいですが、自分のアカウントの方がいろいろデバックしやすいと思いますので。

また、この検索テキストにはいろいろなルールに則ったテキストを設定することでいろいろな検索条件を設定できます。 rksoftware.hatenablog.com rksoftware.hatenablog.com

■ ステップの追加

ステップの追加をします。

[ + 新しいステップ ] をクリックします。

検索枠に 「 Twitter 」と入力し、[ ツイートの検索 ] をクリックします。

Twitter へのサインインを求められたらサインインしてください。

前述の表の内容を [ 検索テキスト ] に入力します。

これで Twitter 内の投稿を検索できます。

■ 繰り返しの追加

ツイートを検索すると結果として複数のツイートが得られます (検索でヒットしていれば)。検索結果を扱うためにツイートごとの繰り返しの処理を行っていきます。

ステップの追加をします。

コネクタ アクション 以前の手順から出力を選択 ステップの名前
コントロール Apply to each ツイートの検索 の body ( @{body('ツイートの検索')} ) ツイートごとに繰り返し処理 - 解析、記憶

[ + 新しいステップ ] をクリックします。

検索枠に 「 apply 」と入力し、[ Apply to each ] をクリックします。

前述の表の内容を入力します。

■ 配列に値を追加

Twitter の検索ではありませんが、今回作るフローで必要なのでここで配列に値を追加します。

今回のフローの最終出力にツイートの解析結果を配列として出力する計画です。その仕込みです。今回はツイートの解析結果は複数のデータになるのでツイートごとの区切りを入れる処理になります。

繰り返しの中にステップの追加をします。

コネクタ アクション 名前 ステップの名前
変数 配列変数に追加 result ---------- 結果配列に Tweet ごとの区切りを記録する

[ アクションの追加 ] をクリックします。

検索枠に 「 変数 」と入力し、[ 配列変数に追加 ] をクリックします。

前述の表の内容を入力します。

Power Automate で条件で処理を分岐する

Power Automate のフローを組んで行きます。

Tweet は通常のツイートとリツイートでデータが変わります。この変化に分岐を使用して対応します。

■ 「コントロール」 コネクタの 「条件」 をアクションを追加

2022/08/30 現在、挙動が変わって null の時はエラーになるようになっています。信じていたのに......。
回避案として length(string(item()?['OriginalTweet/TweetId'])) を設定してください。

次の 1 つのステップを追加します。

コネクタ アクション ステップの名前
コントロール 条件 length(item()?['OriginalTweet/TweetId']) 次の値より大きい 0 直ツイートか RT かを評価 - 本文と ID を記録する

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

[ + 新しいステップ ] をクリックします。

検索枠に 「 条件 」と入力し、[ 組み込み ] をクリック、[ 条件 ] をクリックします。

前述の表の内容で条件を入力します。

これでツイートが通常のツイートかリツイートかで条件分岐できます。

■ length 関数について

今回使った length 関数は文字列の文字数が得られる関数です。大事な挙動として、文字列が null の場合に 0 を返してくれます 。これが仕様なのかはドキュメントに記述がありませんでした。この先もずっとそう動くかは不明ですが、今は信じて使うしかありません。
2022/08/30 現在、挙動が変わって null の時はエラーになるようになっています。信じていたのに......。
回避案として length(string(item()?['OriginalTweet/TweetId'])) を設定してください。

IsNullOrEmpty または IsNullOrWhiteSpace 関数を使うべきでは?

読んでくださっている皆様そう思われるでしょう。当然の疑問です。私もそう思います。しかし無念なことにそういった関数は見つけられませんでした。なので古式ゆかしい length での評価を行っています。

■ 評価の意図について

Twitter 検索の結果にはツイートの内容が入る場所が二つあります。普通に投稿したツイートとリツイートしたリツイート元が入る場所です。データによって参照するデータの場所が変わるので、そのデータが普通のツイートなのかリツイートなのかを評価しています。
今回の処理では item()?['OriginalTweet/TweetId'] を評価しています。OriginalTweet がリツイート元のツイートのデータです。ここにツイートの ID があればリツイートという評価をしています。

■ 条件の分岐の はい と いいえ それぞれで変数に値を設定

条件分岐ができました。はいの場合はリツイート元のツイートのテキストと ID を、いいえの場合は通常のツイートのテキストと ID を変数に設定します。

はい の場合

コネクタ アクション 名前 ステップの名前
変数 変数の設定 tweet ツイートの検索 の 元ツイートのテキスト tweet 本文を記憶 (RT 元)
変数 配列変数に追加 result ツイートの検索 の 元ツイート ID tweet の ID を結果配列に追加 (RT 元)

いいえ の場合

コネクタ アクション 名前 ステップの名前
変数 変数の設定 tweet ツイートの検索 の ツイートテキスト tweet 本文を記憶 (直ツイート)
変数 配列変数に追加 result ツイートの検索 の ツイート ID tweet の ID を結果配列に追加 (直ツイート)

こんな感じです。

Power Automate でセンチメントを解析する

Power Automate のフローを組んで行きます。

今回からついにツイートの内容を解析していきます。

■ 解析の前に画像の URL を記録

ツイートの解析の前にここで今後の処理で解析する画像の URL を記録しておきます。

次の 2 つのステップを追加します。

コネクタ アクション 名前 ステップの名前
変数 変数の設定 mediaurl first(item()?['MediaUrls']) 解析する画像の URL を記憶する
変数 配列変数に追加 results 変数 mediaurl 結果配列に解析する画像の URL を記録する

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

変数に値を設定するステップの追加の手順は以前に何度か行っているので、手順の記載は省略します。

■ センチメントの分析

ついに本題です。

次の 2 つのステップを追加します。

コネクタ アクション documents id - 1 documents text - 1 documents language - 1 ステップの名前
Azure Cognitive Service for Langage センチメント (V3.0) 1 first(item()?['MediaUrls']) ja センチメント(V3.0)ツイート分の感情を解析する

 

コネクタ アクション 名前 ステップの名前
変数 配列変数に追加 results first(outputs('センチメント(V3.0)ツイート分の感情を解析する')?['body/documents'])?['sentiment'] 結果配列に感情の解析結果を記録する

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

[ アクションの追加 ] をクリックします。

検索枠に 「 センチメント 」と入力し、[ センチメント (V3.0) ] をクリックします。

以前の手順で用意した Azure Cognitive Service の キー 1エンドポイント を入力します。
rksoftware.hatenablog.com

アカウント キー サイトの URL
キー 1 エンドポイント

前述の表の内容を入力します。

配列変数に追加を設定するステップの追加の手順は以前に何度か行っているので、手順の記載は省略します。

Power Automate で画像に写っているものを検出する

Power Automate のフローを組んで行きます。

今回はついにツイートの画像から物体を検出します。

■ 全体ゴール

連載のゴールの様子です。

■ オブジェクトを検出する (V3) ツイート画像に写っているもの

次の 4 つのステップを追加します。

コネクタ アクション リソースのサブドメインや地域 画像のソース Image URL ステップの名前
コンピューター ビジョン API 画像を分析する (V3) (プレビュー) Use connection settings(xxxxxxxxxx) Image URL 変数 mediaurl オブジェクトを検出する (V3) ツイート画像に写っているもの

 

コネクタ アクション 以前の手順から出力を選択 ステップの名前
コントロール Apply to each オブジェクトを検出する (V3) ツイート画像に写っているもの の objects 検出したオブジェクトで繰り返し処理 - 結果配列に記録

 

コネクタ アクション 名前 ステップの名前
変数 配列変数に追加 results オブジェクトを検出する (V3) ツイート画像に写っているもの の オブジェクト名 結果配列に検出したオブジェクト名を記憶する

 

コネクタ アクション 入力 ステップの名前
データ操作 作成 変数 results 結果の確認

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

[ アクションの追加 ] をクリックします。

検索枠に 「 コンピューター 」と入力し、[ オブジェクトを検出する (V3.0) (プレビュー) ] をクリックします。

前述の表の内容を入力します。

Apply to each、配列変数に追加を設定するステップの追加の手順は以前に何度か行っているので、手順の記載は省略します。

最後の作成も変数の扱いと変わらないので省略します。

■ フローを実行

右上の [ テスト ] をクリックしフローを実行します。




実行結果の確認

最後のステップを開くと解析の実行結果が表示されます。

■ 以前の手順で作った Windows アプリに貼り付け

実行結果をコピーして以前に作った Windows アプリの上部の入力欄に貼り付け、click ボタンを押下します。

分析結果が出ます!

■ 簡単ですね

簡単ですね。

Power Automate で画像に写っているものを検出する

■ 連載目次記事

Power Automate のフローを組んで行きます。

■ 前回の進捗

前回でツイート分の感情を解析するところまで来ました。

■ 今回の概要

今回はついにツイートの画像から物体を検出します。

■ 全体ゴール

連載のゴールの様子です。

■ オブジェクトを検出する (V3) ツイート画像に写っているもの

次の 4 つのステップを追加します。

コネクタ アクション リソースのサブドメインや地域 画像のソース Image URL ステップの名前
コンピューター ビジョン API 画像を分析する (V3) (プレビュー) Use connection settings(xxxxxxxxxx) Image URL 変数 mediaurl オブジェクトを検出する (V3) ツイート画像に写っているもの

 

コネクタ アクション 以前の手順から出力を選択 ステップの名前
コントロール Apply to each オブジェクトを検出する (V3) ツイート画像に写っているもの の objects 検出したオブジェクトで繰り返し処理 - 結果配列に記録

 

コネクタ アクション 名前 ステップの名前
変数 配列変数に追加 results オブジェクトを検出する (V3) ツイート画像に写っているもの の オブジェクト名 結果配列に検出したオブジェクト名を記憶する

 

コネクタ アクション 入力 ステップの名前
データ操作 作成 変数 results 結果の確認

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

[ アクションの追加 ] をクリックします。

検索枠に 「 コンピューター 」と入力し、[ オブジェクトを検出する (V3.0) (プレビュー) ] をクリックします。

前述の表の内容を入力します。

Apply to each、配列変数に追加を設定するステップの追加の手順は以前に何度か行っているので、手順の記載は省略します。

最後の作成も変数の扱いと変わらないので省略します。

■ フローを実行

右上の [ テスト ] をクリックしフローを実行します。




実行結果の確認

最後のステップを開くと解析の実行結果が表示されます。

■ 以前の手順で作った Windows アプリに貼り付け

実行結果をコピーして以前に作った Windows アプリの上部の入力欄に貼り付け、click ボタンを押下します。

分析結果が出ます!

■ 簡単ですね

簡単ですね。

Power Automate でセンチメントを解析する

■ 連載目次記事

Power Automate のフローを組んで行きます。

■ 前回の進捗

前回で Twitter コネクタを使ってツイートを取得するところまで来ました。

■ 今回の概要

今回からついにツイートの内容を解析していきます。

■ 全体ゴール

連載のゴールの様子です。

■ 解析の前に画像の URL を記録

ツイートの解析の前にここで今後の処理で解析する画像の URL を記録しておきます。

次の 2 つのステップを追加します。

コネクタ アクション 名前 ステップの名前
変数 変数の設定 mediaurl first(item()?['MediaUrls']) 解析する画像の URL を記憶する
変数 配列変数に追加 results 変数 mediaurl 結果配列に解析する画像の URL を記録する

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

変数に値を設定するステップの追加の手順は以前に何度か行っているので、手順の記載は省略します。

■ センチメントの分析

ついに本題です。

次の 2 つのステップを追加します。

コネクタ アクション documents id - 1 documents text - 1 documents language - 1 ステップの名前
Azure Cognitive Service for Langage センチメント (V3.0) 1 first(item()?['MediaUrls']) ja センチメント(V3.0)ツイート分の感情を解析する

 

コネクタ アクション 名前 ステップの名前
変数 配列変数に追加 results first(outputs('センチメント(V3.0)ツイート分の感情を解析する')?['body/documents'])?['sentiment'] 結果配列に感情の解析結果を記録する

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

[ アクションの追加 ] をクリックします。

検索枠に 「 センチメント 」と入力し、[ センチメント (V3.0) ] をクリックします。

以前の手順で用意した Azure Cognitive Service の キー 1エンドポイント を入力します。
rksoftware.hatenablog.com

アカウント キー サイトの URL
キー 1 エンドポイント

前述の表の内容を入力します。

配列変数に追加を設定するステップの追加の手順は以前に何度か行っているので、手順の記載は省略します。

■ 簡単ですね

簡単ですね。

Power Automate で条件で処理を分岐する

■ 連載目次記事

Power Automate のフローを組んで行きます。

■ 前回の進捗

前回で Twitter コネクタを使ってツイートを取得するところまで来ました。

■ 今回の概要

Tweet は通常のツイートとリツイートでデータが変わります。この変化に分岐を使用して対応します。

■ 全体ゴール

連載のゴールの様子です。

■ 「コントロール」 コネクタの 「条件」 をアクションを追加

2022/08/30 現在、挙動が変わって null の時はエラーになるようになっています。信じていたのに......。
回避案として length(string(item()?['OriginalTweet/TweetId'])) を設定してください。

次の 1 つのステップを追加します。

コネクタ アクション ステップの名前
コントロール 条件 length(item()?['OriginalTweet/TweetId']) 次の値より大きい 0 直ツイートか RT かを評価 - 本文と ID を記録する

こんな感じの部分です。

■ ステップの追加

ステップの追加をします。

[ + 新しいステップ ] をクリックします。

検索枠に 「 条件 」と入力し、[ 組み込み ] をクリック、[ 条件 ] をクリックします。

前述の表の内容で条件を入力します。

これでツイートが通常のツイートかリツイートかで条件分岐できます。

■ length 関数について

今回使った length 関数は文字列の文字数が得られる関数です。大事な挙動として、文字列が null の場合に 0 を返してくれます 。これが仕様なのかはドキュメントに記述がありませんでした。この先もずっとそう動くかは不明ですが、今は信じて使うしかありません。
2022/08/30 現在、挙動が変わって null の時はエラーになるようになっています。信じていたのに......。
回避案として length(string(item()?['OriginalTweet/TweetId'])) を設定してください。

IsNullOrEmpty または IsNullOrWhiteSpace 関数を使うべきでは?

読んでくださっている皆様そう思われるでしょう。当然の疑問です。私もそう思います。しかし無念なことにそういった関数は見つけられませんでした。なので古式ゆかしい length での評価を行っています。

■ 評価の意図について

Twitter 検索の結果にはツイートの内容が入る場所が二つあります。普通に投稿したツイートとリツイートしたリツイート元が入る場所です。データによって参照するデータの場所が変わるので、そのデータが普通のツイートなのかリツイートなのかを評価しています。
今回の処理では item()?['OriginalTweet/TweetId'] を評価しています。OriginalTweet がリツイート元のツイートのデータです。ここにツイートの ID があればリツイートという評価をしています。

■ 条件の分岐の はい と いいえ それぞれで変数に値を設定

条件分岐ができました。はいの場合はリツイート元のツイートのテキストと ID を、いいえの場合は通常のツイートのテキストと ID を変数に設定します。

はい の場合

コネクタ アクション 名前 ステップの名前
変数 変数の設定 tweet ツイートの検索 の 元ツイートのテキスト tweet 本文を記憶 (RT 元)
変数 配列変数に追加 result ツイートの検索 の 元ツイート ID tweet の ID を結果配列に追加 (RT 元)

いいえ の場合

コネクタ アクション 名前 ステップの名前
変数 変数の設定 tweet ツイートの検索 の ツイートテキスト tweet 本文を記憶 (直ツイート)
変数 配列変数に追加 result ツイートの検索 の ツイート ID tweet の ID を結果配列に追加 (直ツイート)

こんな感じです。

■ 簡単ですね

簡単ですね。

Power Automate で Twitter コネクタを使う

■ 連載目次記事

Power Automate のフローを組んで行きます。

■ 前回の進捗

Power Automate のフローを新規作成し Azure の準備もし、ここからアクションの追加も始めました。いよいよコネクタを活用して処理を作っていきます。

■ 今回の概要

Twitter から情報を取得します。Twitter コネクタを使用して Tweet を検索して値を取得するところまで行きます。

■ 全体ゴール

連載のゴールの様子です。

■ 「Twitter」 コネクタの 「ツイートの検索」 をアクションを追加

次の 1 つのステップを追加します。

コネクタ アクション 検索テキスト ステップの名前
Twitter ツイートの検索 スタバ from:mishi_cs filter:images ツイートの検索

こんな感じの部分です。

検索テキストについて

今回の例では、私のツイートから画像付きのツイートで「スタバ」というテキストを検索しています。皆さんが試す際には from: のところを皆さんのアカウントに変更してください。変更しなくてもいいですが、自分のアカウントの方がいろいろデバックしやすいと思いますので。

また、この検索テキストにはいろいろなルールに則ったテキストを設定することでいろいろな検索条件を設定できます。 rksoftware.hatenablog.com rksoftware.hatenablog.com

■ ステップの追加

ステップの追加をします。

[ + 新しいステップ ] をクリックします。

検索枠に 「 Twitter 」と入力し、[ ツイートの検索 ] をクリックします。

Twitter へのサインインを求められたらサインインしてください。

前述の表の内容を [ 検索テキスト ] に入力します。

これで Twitter 内の投稿を検索できます。

■ 繰り返しの追加

ツイートを検索すると結果として複数のツイートが得られます (検索でヒットしていれば)。検索結果を扱うためにツイートごとの繰り返しの処理を行っていきます。

ステップの追加をします。

コネクタ アクション 以前の手順から出力を選択 ステップの名前
コントロール Apply to each ツイートの検索 の body ( @{body('ツイートの検索')} ) ツイートごとに繰り返し処理 - 解析、記憶

[ + 新しいステップ ] をクリックします。

検索枠に 「 apply 」と入力し、[ Apply to each ] をクリックします。

前述の表の内容を入力します。

■ 配列に値を追加

Twitter の検索ではありませんが、今回作るフローで必要なのでここで配列に値を追加します。

今回のフローの最終出力にツイートの解析結果を配列として出力する計画です。その仕込みです。今回はツイートの解析結果は複数のデータになるのでツイートごとの区切りを入れる処理になります。

繰り返しの中にステップの追加をします。

コネクタ アクション 名前 ステップの名前
変数 配列変数に追加 result ---------- 結果配列に Tweet ごとの区切りを記録する

[ アクションの追加 ] をクリックします。

検索枠に 「 変数 」と入力し、[ 配列変数に追加 ] をクリックします。

前述の表の内容を入力します。

■ 簡単ですね

簡単ですね。

「光ケーブルは半導体か?」 接戦を制したのは?

人類には多くの議題があります。どんなものも常に議論を行は欠かせません。

しかし最後は やはり多数決! 多数決はすべてを解決する!

というわけで Twitter アンケートです。光ケーブルは半導体なのでしょうか? その結果は大きな差をつけて半導体でした!

わずかに得票数で劣ってしまいましたが「タコは哺乳類」も 1/4 を超える得票でがんばりました。タコは哺乳類ということも世間に認められたともいえるのではないでしょうか?

■ いかがでしたか?

いかがでしたか?