データテーブルをフィルターアクティビティの不思議な現象について

データテーブル同士で一致したものを抽出したく、
データテーブルを結合でdt1とdt2をFullで結合後、「データテーブルをフィルター」アクティビティを使用しています。

ところが、「キー」=「キー_1」と設定しても双方の一致しているデータは出力されず
逆に「キー」!=「キー_1」と設定すると一致したデータが出力されます。

出力結果だけは後者のデータが欲しいのですが、これで作ってしまうのはなんだか気持ちが悪く、汎用性もなさそうで不安です。

これは一体どのような現象で、どうすれば正しいデータが取得できますでしょうか。

(環境)
UiPath Studio v2021.4.4
UiPath.System.Activities v21.4.0

※追記

逆に「キー」!=「キー_1」と設定すると一致したデータが出力されます。

→これは誤りでした。よく見たらこの条件では一致も不一致も含めすべてのデータが抽出されていました。

こんにちは

データテーブルをフィルターアクティビティのウイザードですが
列と値の比較となりますので、値欄に列名等を指定することはできません。

対応案としては、LINQやDataTable.Selectメソッドを使う、行数が少なければForEachRowアクティビティを使う、前者であれば内部結合で抽出できますのでこれを利用する等が考えられると思います

Excelでフィルターをかけることを考えたら確かにそうですね。

データ数はかなり多いのでこちらを検討したいと思います。
LINQはよくこのforumで見かけるのですがどのようなものなのでしょうか?
そのようなアクティビティがあるわけではないのですよね。

こんにちは

データ数はかなり多いのでこちらを検討したいと思います。
LINQはよくこのforumで見かけるのですがどのようなものなのでしょうか?
そのようなアクティビティがあるわけではないのですよね。

代入アクティビティを用いて、

LINQ

newDt = dt.AsEnumerable.Where(Function(r) r("キー").ToString<>r("キー_1").ToString).CopyToDataTable()

DataTable.Select

newDt = dt.Select("キー<>キー_1").CopyToDataTable()

注:両者とも結果が0行になる可能性がある場合は、CopyToDataTableの前で止めて、行数をチェックする必要があります。

今から覚えるのであればLINQの方が応用範囲が広いので良いように思えます。

ありがとうございます。
.CopyToDataTableの部分で、指定のDatatable変数に格納することも可能なのでしょうか?

こんにちは

すみません、質問の意味が良く把握できないのですが、かみ砕いて説明いただけますでしょうか?

もしかしたら解釈を間違えているかもしれませんので改めて確認させていただきます。

newDt = dt.AsEnumerable.Where(Function(r) r(“キー”).ToString<>r(“キー_1”).ToString).CopyToDataTable()

これは指定した条件で抽出し、結果を.CopyToDataTableでDatatable型変数に格納しているという解釈で合っていますか?

もしこの解釈で合っていれば、格納先のデータテーブルに任意のデータテーブルを使用できるかという意味になります。

【追記】
すみません、そもそも代入アクティビティを指定しているのでした。。
大変失礼いたしました!!

概ねあっていますが、「結果を.CopyToDataTableでDatatable型変数に格納している」
→CopyToDataTableはDataTable型で値を返しているだけですので、変数に格納する
機能はありません。変数に格納しているのは代入アクティビティになります。
代入アクティビティの左辺の変数を変更すれば、任意のDataTable変数に代入可能です。

ありがとうございます。
代入アクティビティを使っていることがなぜかすっぽり抜けておりました;;

抽出条件を、
「"キー"と"キー_1"にデータがあり、かつ"変更日"と"変更日_1"の値が一致している」という条件にしたく、UiPath公式ドキュメントのTips集を見て下記のようにしてみたのですがデータがありませんでした。(データのほとんどがこれに該当します)

dt.AsEnumerable.Where(Function(r) r("キー").ToString<>"" AndAlso r("キー_1").ToString<>"" AndAlso r("変更日").ToString=r("変更日_1").ToString).CopyToDataTable()

AndAlsoをAndにしてみても同じ結果となりました。

どこを修正すれば良いかご教示いただけないでしょうか。
度々申し訳ございません。

こんにちは

式だけですと特段問題ないように思えますが、実データがないと何とも言えませんね。
とりあえず条件を減らしていって、どの条件が期待通りに動いていないかを特定した方が良いように思えます。

条件を減らしてみると、「列名=空白」や、「列名=空白でない」という条件は有効なのですが
列の値同士を比較する部分のみ残してみると、すべて0件になってしまいました。

比較演算子の=は、
「変更日と変更日_1の値が一致している」の意味にしたいのですが
「変更日の値が"r(“変更日_1”).ToString"である」と区別することはできますか?
というか、Function rの引数なので区別できていますよね。。。

元々のデータテーブルをフィルターアクティビティとまったく同じ結果になっている状況です。
生データとは別のサンプルデータを作って再現するか試してみます。

色々試した結果、変更日列の形式が影響しておりうまく判断できていないようでした。
列の値を適当な文字列に変えてみたら意図する結果となりました。

このデータは元々"キー"で結合しているため変更日しか差別化できるデータがなく、なんとか変更日列のまま抽出できないか引き続き検討したいと思います。
もしくはデータは多いですが行のループにすることも視野に入れます。

こんにちは

具体的にそれぞれどのような形式になっていますでしょうか?
式の中で変換もかけることができますので、単純な形式違いなら何とかなるケースも多いです。

ありがとうございます。

2021/7/3 17:18

どちらのデータもテキストで確認するとこのような形式になっております。

こんにちは

r("変更日").ToString

の形で比較していますので、
例えばテスト的にForEachRowで

row("変更日").ToString
row("変更日_1").ToString

をそれぞれ出力したときに、どのような文字列になっているか確認できますでしょうか?

これが一致しているのであれば上記の式でも一致と判断されるべきになります。

ご提案ありがとうございます。
たしかにそちらで実行してみたら

変更日→2021/7/3 17:18
変更日_1→2021/07/03 17:18:10

このように出力されました。

こんにちは
ありがとうございます。
厳密にみると分単位でことなりますので、仮に桁数等をあわしても異なるデータとなるかと思います。比較したい単位はどこまでになりますか?(日付まででしょうか?)

ありがとうございます。
日付まででの比較で進めたいと思います。

こんにちは

それでは以下試してみてください。

dt.AsEnumerable.Where(Function(r) r("キー").ToString<>"" AndAlso r("キー_1").ToString<>"" AndAlso DateTime.Parse(r("変更日").ToString).Date=DateTime.Parse(r("変更日_1").ToString).Date).CopyToDataTable()
1 Like

ありがとうございます。
こちらで抽出できました。
LINQを自由に使えるようになればデータテーブルの扱いもかなり楽になりそうな気がしました。
引き続き習熟を深めていきたいと思います。
この度は本当にありがとうございました!

1 Like