Power Automate Desktop .NETスクリプトでデータテーブルを操作する

2023/09/15に公開

.NET コードが使えてありがたいというお話

はじめに

PAD (Power Automate Desktop)でデータテーブルの操作がしたいです。
具体的には、複数のデータテーブルから必要な項目を引っ張ってくる、並べ替える、重複削除、などなど。他には、データテーブルじゃないですけど全角・半角カナ混在している文字列の比較も必要に迫られて困りました。(……話が逸れますが、ぶっちゃけ半角カナ使うの止めて欲しいです。それから、表の見出しで改行するのも止めて欲しい。)

一方、用意されているデータテーブルのアクションは 5 つ (2023/9/15 現在)と少々心もとない感じ。これをどうやって組み立てたらいけるのか想像もつかないのですが、案外やってみたら出来るのでしょうか…………?
出来るの…………?

とりあえず、ここでは出来ないと見切りをつけて他の方法で考えてみます。

目次

  • .NET スクリプトを使ってみる
  • DataTable のサンプル 1
  • DataTable のサンプル 2
  • 文字列の比較のサンプル

.NET スクリプトを使ってみる

言語は C# と VB.NET が選べます。

https://learn.microsoft.com/ja-jp/power-automate/desktop-flows/actions-reference/scripting

.NET スクリプト画面
構成カード - Type
構成カード - Directon

DataTable のサンプル 1

前提

  • データテーブルが 3 つあって、それぞれに共通しているキーが[氏名コード]
  • dt1 [No][氏名コード][氏名]...他にも項目があるけど全然重要じゃないので省略
  • dt2 [メールアドレス]を取得したい。ほかの項目は省略
  • dt3 [組織名]を取得したい。ほかの項目は略
スクリプトパラメーター

(DataTable dt1, DataTable dt2, DataTable dt3, ref dynamic dr)

.NET パラメーター名 種類 方向 入力値 出力変数
dt1 データテーブル 含まれる %DataTable1%
dt2 データテーブル 含まれる %DataTable2%
dt3 データテーブル 含まれる %DataTable3%
dr ダイナミック %DataRow%

スクリプトでの作業

  1. dt1 の[氏名コード]を主キーに設定
  2. dt1 ← dt2 を結合
  3. dt1 ← dt3 を結合
  4. dr ← dt1 の([No]が空じゃないレコードで絞り込み、組織名で並び替える)
実行する.NET コード
dt1.PrimaryKey = new DataColumn[] { dt1.Columns["氏名コード"] };
dt1.Merge(dt2);
dt1.Merge(dt3);
dr = dt1.Select("No <> ''", "組織名");

DataRow で返ってくるので、PAD のアクションで新しいデータテーブルを作って
そこに必要な項目を追加していくことで不要な項目を取り除きます。

PAD での作業

  1. 1 行,4 列の新しいテーブルを作成
  2. 空のレコードが出来るので 1 行目(インデックス 0)を削除
  3. For each で DataRow を取り出す
  4. [氏名],[氏名コード],[メールアドレス],[組織名]を新しいテーブルに追加する
PAD
Variables.CreateNewDatatable InputTable: { ^['氏名', '氏名コード', 'メールアドレス', '組織名'], [$'''''', $'''''', $'''''', $''''''] } DataTable=> 対象者一覧
Variables.DeleteRowFromDataTable DataTable: 対象者一覧 RowIndex: 0
LOOP FOREACH CurrentItem IN DataRow
    Variables.AddRowToDataTable.AppendRowToDataTable DataTable: 対象者一覧 RowToAdd: [CurrentItem['氏名'], CurrentItem['氏名コード'], CurrentItem['メールアドレス'], CurrentItem['組織名']]
END

必要な項目だけのデータテーブルになった。

補足

PAD
- Variables.CreateNewDatatable InputTable: { ^['氏名', '氏名コード', 'メールアドレス', '組織名'], [$'''''', $'''''', $'''''', $''''''] } DataTable=> 対象者一覧
+ Variables.CreateNewDatatable InputTable: { ^['氏名', '氏名コード', 'メールアドレス', '組織名'] } DataTable=> 対象者一覧
- Variables.DeleteRowFromDataTable DataTable: 対象者一覧 RowIndex: 0
LOOP FOREACH CurrentItem IN DataRow
    Variables.AddRowToDataTable.AppendRowToDataTable DataTable: 対象者一覧 RowToAdd: [CurrentItem['氏名'], CurrentItem['氏名コード'], CurrentItem['メールアドレス'], CurrentItem['組織名']]
END

DataTable のサンプル 2

前提

  • なし
スクリプトパラメーター

(DataTable dt1, ref DataTable dt2, ref dynamic dr)

.NET パラメーター名 種類 方向 入力値 出力変数
dt1 データテーブル 含まれる %DataTable1%
dt2 データテーブル %DataTable2%
dr ダイナミック %DataRow%

スクリプトでの作業

  1. 組織名で重複削除して組織名列のみを出力
  2. 組織名で並べ替え
実行する.NET コード
// 重複削除
dt2 = dt1.DefaultView.ToTable(true, "組織名");
// 並び替え
dr = dt1.Select("", "組織名");

単純なコードでも、これをアクションでやろうとするとちょっとわからないです。

文字列の比較のサンプル

前提

  • 組織名の比較。全角カナと半角カナの比較になるのでそのままでは一致しない
スクリプトパラメーター

(string s1, string s2, ref bool isMatch)

.NET パラメーター名 種類 方向 入力値 出力変数
s1 文字列 含まれる %組織['組織名']%
s2 文字列 含まれる %対象['組織名']%
isMatch ブール値 %isMatch%

スクリプトでの作業

  1. 全角カナと半角カナを比較するためのお呪い
  2. 半角カナに濁音がなければ IgnoreWidth だけで十分
  3. 濁音が含まれているなら IgnoreNonSpace も必要
  4. String.Compare で比較して、一致したら true を返す
[2024/5/7] コードがよくなかったので変えました。
- if (String.Compare(s1, s2, jp, opt1 | opt2) == 0)
- {
- 	isMatch = true;
- }
+ isMatch = String.Compare(s1, s2, jp, opt1 | opt2) == 0;
実行する.NET コード
// 日本語カルチャ固有の比較
var jp = new System.Globalization.CultureInfo("ja-JP");
var opt1 = System.Globalization.CompareOptions.IgnoreWidth;
var opt2 = System.Globalization.CompareOptions.IgnoreNonSpace;

// 全角と半角の区別を無視して、s1とs2が等しいか調べる
isMatch = String.Compare(s1, s2, jp, opt1 | opt2) == 0;

PAD のアクションで全角カナと半角カナを比較する方法がわからなかったので、.NET コードの中で比較しています。

追記 [2023/9/17]

.NET スクリプトのインポートに名前空間を使用できます。
(using やセミコロン(;)なし)

.NET スクリプトのインポート: System.Globalization

実行する.NET コード
// 日本語カルチャ固有の比較
var jp = new CultureInfo("ja-JP");
var opt1 = CompareOptions.IgnoreWidth;
var opt2 = CompareOptions.IgnoreNonSpace;

// 全角と半角の区別を無視して、s1とs2が等しいか調べる
isMatch = String.Compare(s1, s2, jp, opt1 | opt2) == 0;

おしまい

使ってみました。難しいことをしていないのでどれも数行で済んでいますが、PAD のアクションでやるとなると、どうなんでしょう。

気になる点

気になる点はやっぱり、C# 5 なところですよね。5 って……なに…………。
using宣言は使えない


感想

.NET スクリプトすごい便利なのに 2023 年 7 月アップデートで追加された機能だっていうんだからびっくりしました。逆に、今までこういうことをどうやって実装していたの。この時期に自分がかかわっていたらどうなっていたの……。
バージョンがちょっと……という問題はありますが、今は C#が使えて良かったです。

Discussion