🍧

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

2024/05/25に公開

.NET コード サンプル

.NET スクリプトを使った使用例をいくつか書いてみます。
相変わらず Select を使います。

このへんの続き。
Power Automate Desktop .NET スクリプトでデータテーブルを操作する
Power Automate Desktop Excel ファイルを SQL で操作する


マージ

なにかデータを集約する必要があったらとりあえずマージしとけばいい、みたいな雑な考え方で大変恐縮です。まあ、大量のレコードを扱うわけではないのでこんなので良いと思います。たぶん。

その前に、

  1. ヘッダーを設定したい場合

Excel のデータで見出しに改行を使っている表(データテーブルではない)を扱う場面、実務ではたまにあると思います。(あってほしくはないんですけど)
そういうとき、項目名をこっちで書き換えるコードが以下。

インデックスで指定して項目名を入れます。列番号は 0 始まりです。

ヘッダーの書き換え
dataTable.Columns[0].ColumnName = "項目名";
  1. 日付でフィルターする場合

データテーブルを日付を使って絞り込みたいとき、直接記述なら#2024/1/12#。こういう書き方ならすぐ出てくるのですが、関数を使うとどう記述するのか検索してもいまいちよくわからなかったです。

一応下記のコードが出てきたのですが、SQL の[列名] < DATE()みたいな書き方と比べると、+演算子で結合するのってちょっと微妙……。

日付
DataRow[] rows = newTable.Select("date >= #" + from_date + "# AND date <= #" + to_date + "#");

https://stackoverflow.com/questions/10934615/c-sharp-datatable-select-statement-with-dates

まだ、String.Formatを組み合わせて Select 文の中に入れる方が良いかな……。

var rows = dataTable.Select(String.Format("date < #{0}#", currentDate));

他の方法をご存じでしたら教えてもらえるととても嬉しいです。

C#5 なので文字列補完を使って、$"date < #{currentDate}#"は無理でした。

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

日付型を文字列型にするにはこんな感じ。
DateTime.Now.ToString("yyyy/MM/dd")
DateTime.Now.ToShortDateString()など。

日付で絞り込み。予め日付を文字列にして変数に入れて使っています。

(ref DataTable dt1)
var table = dt1.Clone();
var now = DateTime.Now.ToShortDateString();
var rows = dt1.Select(String.Format("結果 = '未登録' and 予定日 < #{0}#", now));
foreach (var row in rows)
{
	var addRow = table.NewRow();
	addRow.ItemArray = row.ItemArray;
	table.Rows.Add(addRow);
}
dt1 = table;

データテーブルに戻すのに、rows.CopyToDataTable()を使わないで foreach を使っているのは、.NET スクリプトでCopyToDataTable()が使えないからです…………。

+ dt1 = rows.CopyToDataTable();
- foreach (var row in rows)
- {
-	var addRow = table.NewRow();
-	addRow.ItemArray = row.ItemArray;
-	table.Rows.Add(addRow);
- }
- dt1 = table;

試した結果

Error

  1. 必要な列だけ取り出す
    そのまま結合しちゃうと必要ないデータも含まれた横になが~いテーブルになっちゃうので、
    一旦、それぞれのテーブルから必要な列だけ取り出したものを用意して、
    それらを結合することでコンパクトなデータテーブルにします。

    1. 最初に新しいデータテーブルを作る
    2. 列を追加
    3. foreachで1行ずつ新しいテーブルに追加
    
(ref DataTable dt1)
var table = new DataTable();
table.Columns.Add("項目1");
table.Columns.Add("項目2");
table.Columns.Add("項目3");

foreach (DataRow row in dt1.Rows)
{
	table.Rows.Add(row["項目1"], row["項目2"], row["項目3"]);
}
dt1 = table;

同様の作業を他のテーブルにも行います。

  1. 結合
    本題。主キーを設定してマージします。
    例では、 - 項目 1→ 主キー - 項目 2→ 絞り込み - 項目 5, 項目 6→ 昇順で並び替え
(ref DataTable dt1, DataTable dt2, DataTable dt3)
dt1.PrimaryKey = new DataColumn[] { dt1.Columns["項目1"] };
dt1.Merge(dt2);
dt1.Merge(dt3);

var table = dt1.Clone();
var rows = dt1.Select("項目2 <> ''", "項目5, 項目6");
foreach (var row in rows)
{
	var addRow = table.NewRow();
	addRow.ItemArray = row.ItemArray;
	table.Rows.Add(addRow);
}
dt1 = table;

複数のデータテーブルから必要な項目だけ集めたデータテーブルができました。


文字列の比較

前回もやった文字列の比較。
前回は、一致したかどうかを bool で返してあとは PAD で~でした。
今回は、そのままデータテーブルにしちゃいます。

組織名で比較して何かをするイメージ。

全角カナと半角カナの文字列を比較

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

(ref DataTable dt1, DataTable dt2)
var jp = new CultureInfo("ja-JP");
var opt1 = CompareOptions.IgnoreWidth;
var opt2 = CompareOptions.IgnoreNonSpace;

var table = dt1.Clone();
foreach (DataRow row in dt1.Rows)
{
	var s1 = row["組織名"].ToString();
	// 色々処理
	foreach (DataRow line in dt2.Rows)
	{
		var s2 = line["組織名"].ToString();
		if (String.Compare(s1, s2, jp, opt1 | opt2) == 0)
		{
			// 一致したときの処理
		}
	}
	var addRow = table.NewRow();
	addRow.ItemArray = row.ItemArray;
	table.Rows.Add(addRow);
}
dt1 = table;

おわりに

PAD での使い方になりますが、一つのスクリプトにたくさん処理を詰め込んでも、編集画面で見づらいしデバッグし辛いので、分割して書いた方が良いと思います。

Discussion