11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【UiPath】データテーブルの操作(3)絞り込み(フィルタ)

Last updated at Posted at 2022-05-30

はじめに

この投稿は、RPAツール「UiPath」で Datatable からデータを絞り込む方法について、個人的にまとめたものです。

データテーブルの操作 シリーズ

DataTable の操作方法について記載した記事が、他にもあります。参考まで。

絞り込み方法

UiPath で、データテーブルから条件指定してデータを取得するには、以下の方法があります。

No 方法 評価 コメント
1 「データ テーブルをフィルター」
アクティビティを使用
UiPath では一般的 SelectやLinqの方が見やすい
比較時に型変換(型揃え)が出来ない
2 Datatableの「.Select」メソッドを使用 VB では一般的 比較時に型変換(型揃え)が出来る
列の加工・削除ができない
3 「LINQ to Object(メソッド構文)」 を使用 .NET では一般的
(少し難しい)
基本何でもできる
横に長くなりがち
4 「LINQ to SQL(クエリ式)」 を使用 .NET では一般的
(少し難しい)
基本何でもできる
縦横に長くなりがち

以下で、説明していきます。

1)データ テーブルをフィルター アクティビティ

標準アクティビティで提供されている「データ テーブルをフィルター」アクティビティで、絞り込みが出来ます。機能的には十分です。

「フィルタを指定」ボタンを押すと、ウィザードが表示され、条件を設定します。複数の条件の指定も可能で、絞り込み後に「残す/削除する」列の指定も可能です。
image.png

残念な点としては「フィルタを指定」ボタンを押さないと、フロー上での絞り込み内容が見れません。(ボタンを押さないでも見えるようになってほしい)

また、データの型が「DateTime型」等の「書式によっては値比較が正確にできない」ものは、絞り込みができない事があります。(値の比較時に、右辺左辺の型変換ができない)

(上記のように「厳格に型を意識する必要がない」場合)基本的には、このアクティビティで絞り込みをすれば良いのですが、「処理が遅い」場合あります。
また「少し凝った操作をしたい」場合は、以下で紹介する「Selectメソッド」か「LINQ」で操作することになります。

要するに「標準アクティビティでは出来ない」ことがあり、その場合「Selectメソッド」か「LINQ」で操作する必要があるということです。
(アクティビティに欲しい機能の追加がされるまでは・・・。)

また、類似アクティビティで「データ テーブルを検索」アクティビティがありますが、検索結果と合致した行番号しか取れないので、絞り込むには少し機能が足りません。

2)Datatableの「.Select」メソッド

Datatable が提供する Select メソッドを使用して、DataRow オブジェクトの配列を取得できます。
Select メソッドには、4種類の指定方法があります。

No メソッドの指定 内容
1 .Select() すべての 行を取得
※稀に使う(ほぼ使わない)
2 .Select("絞込条件") 絞込条件に合致する 行を取得
3 .Select("絞込条件", "並替指定") 絞込条件に合致する 行を 並替して取得
4 .Select("絞込条件", "並替指定", "行の状態指定") 絞込条件と行状態指定に合致する 行を 並替して取得
※UiPathでは使うことは無い

以下のような式を、代入アクティビティ等にセットして使用します。

'// .Select("絞込条件") のサンプル
dt.Select("id='A001'")              '// IDが「A001」
dt.Select("width>20 AND height=10") '// 幅が20より大きく、高さが10
dt.Select("width>20 OR  height=10") '// 幅が20より大きい、または、高さが10

'// .Select("絞込条件", "並替指定")) のサンプル
dt.Select("width>20", "width ASC") '// 幅の昇順で、幅が20より大きい
dt.Select("width>20", "width DESC") '// 幅の降順で、幅が20より大きい
dt.Select("width>20", "width, height DESC") '// 幅の昇順・高さの昇順で、幅が20より大

SELECTで、複数列指定で絞り込みをする場合、データ件数によっては処理が遅くなります。
列の指定を 2 回以上に分けて、SELECTで絞り込むと改善します。

配列/DataRow ではなく DataTable で取得したい場合は、後ろに「.CopyToDataTable」を付けます。

dt.Select("width>20", "width, height DESC").CopyToDataTable

ですが、絞り込み結果が0件の場合に「DataRow が含まれていません」エラーになります。「CopyToDataTable」を実行するためには、必ずデータ1件以上必要なためです。
これを回避するには、一度「配列型」に格納したあとで「配列の件数が0で無い」場合に「CopyToDataTable」するようにします。

'// 件数は悪用の変数を用意
enum_row As IEnumerable<DataRow>

'// 代入1回目(件数把握)
enum_row = dt.Select("id='A001'") 

'// 代入2回目(データが0件なら、空のDataTableをセット)
dt = If(enum_row.Count = 0, dt.Clone, enum_row.CopyToDataTable)

System.Collections.Generic.IEnumerable

3)LINQ to Object(メソッド構文)

LINQ to Object は、繰り返し型(IEnumerableインターフェース)のオブジェクトに対して、一括で処理する方法です。以下のように「 . 」で繋ぎながら、配列操作します。

'// region が tokyo のデータを取得
dt.AsEnumerable().Where(function(r) r("region").ToString.ToLower = "tokyo")

'// region が t で始まるデータを age が低い順 で取得
dt.AsEnumerable().Where(function(r) r("region").ToString.ToLower.StartsWith("t")
                ).OrderBy(function(r) r("age"))

'// region が Tokyo で age が 31以上 のデータを age が高い順 で取得
dt.AsEnumerable().Where(function(r) r("region").ToString = "Tokyo" _
                      AndAlso CType(r("age"), Int32) > 30
                ).OrderByDescending(function(r) r("age"))

'// region が Tokyo または Osaka のデータを age の高い順、名前順 で取得
dt.AsEnumerable().Where(function(r) r("region").ToString = "Tokyo" _
                             OrElse r("region").ToString = "Osaka"
                ).OrderByDescending(function(r) r("age")
                ).ThenBy(function(r) r("name"))

. の後ろは Linq拡張メソッド で、指定できるものがいくつかあります。以下は比較的よく使います。

種類 メソッド 戻り値
絞り込み Where 条件を満たすデータ
並び替え OrderBy 昇順データ
並び替え OrderByDescending 降順データ
並び替え ThenBy 昇順データ(2回目以降の並び替え)
並び替え ThenByDescending 降順データ(2回目以降の並び替え)
選択/射影 Select 指定した要素
集計 Max 最大値
集計 Min 最小値
集計 Sum 合計値
集計 Average 平均値
集計 Count 合致数
判定 All すべて が条件を満たすか
判定 Any いずれか が条件を満たすか
判定 Contains 含むか
要素取得 FirstOrDefault 1件目または初期値

取得結果を、列配列ではなく DataTable で取得したい場合は、後ろに「.CopyToDataTable」を付けます。

'// region が Tokyo のデータを取得
dt.AsEnumerable().Where(function(r) r("region").ToString = "tokyo").CopyToDataTable

横に長くなるため、フローの可読性は落ちます。区切りのいい位置で、改行を挟む等の工夫が必要です。
「.Where・・・」のようにドットが先頭になると構文エラーになるので注意が必要です。
アンダースコア(_)を最後に書くと、エラーを回避できます。

4)LINQ to SQL(クエリ式)

LINQ to SQL は SQLクエリのようにデータを絞り込む方法です。「SELECT・FROM・WHERE」などの式を使用します。

SQLクエリとの比較で言うと、以下のようになります。

SQL式 LINQ式
SELECT select
FROM from in
WHERE where
ORDER BY orderby
GROUP BY group by into

書き方の順ですが、LINQ式の場合、SELECT は後ろ(Orderbyの前)に来ます。

'// region が Tokyo のデータを取得
From r In dt.AsEnumerable()
Select r
Where r("region").ToString = "tokyo"

'// age が高い順 で取得
From r In dt.AsEnumerable() 
Select r 
Order By r.Field(Of Integer)("age") Descending

'// region が Tokyo で age が 31以上 のデータを age が高い順 で取得
From r In dt.AsEnumerable()
Where r("region").ToString = "Tokyo" AndAlso r.Field(Of Integer)("age") > 30
Select r
Order By r.Field(Of Integer)("age") Descending

'// region が Tokyo または Osaka のデータを age の高い順、名前順 で取得
From r In dt.AsEnumerable()
Where r("region").ToString = "Tokyo" OrElse r("region").ToString = "Osaka"
Select r
order by r.Field(Of Integer)("age") Descending,  r("name")

クエリ構文は「遅延バインディング」という仕組みを使用するため「型の明確化」が必要で、列の型「Of XXX」を指定しています。

横に長くなるため、フローの可読性は落ちます。改行を挟む等の工夫が必要です。

終わりに

いかがでしたでしょうか。なにかの役に立てば幸いです。
この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。

11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?