データテーブルの集計で条件を付けたい

やりたいこと
Column6でグルーピングを行い、Column4の値が正の場合のみ集計したい(=負の値は集計しない)

質問事項
以下のソースコードで集計と必要項目の出力はできているのですが、負の値を除外する方法が分かりません。

dt = dt.AsEnumerable.GroupBy(Function(r) r("Column6").ToString).Select(Function(g) dt.Clone.LoadDataRow({g.First().Item("Column0").ToString,g.First().Item("Column1").ToString,g.First().Item("Column2").ToString,g.First().Item("Column3").ToString,g.Sum(Function(r) CDec(r("Column4"))),g.First().Item("Column5").ToString,g.First().Item("Column6").ToString},False)).CopyToDataTable()

If文を追加してみたのですが、「>」が使用できない等のエラーが発生してしまいます。
方法をご教示いただけますと幸いです。

Hi @117

Try this:

dt = dt.AsEnumerable() _
    .Where(Function(r) CDec(r("Column4")) >= 0) _ 
    .GroupBy(Function(r) r("Column6").ToString()) _
    .Select(Function(g) dt.Clone().LoadDataRow({g.First().Item("Column0").ToString(), g.First().Item("Column1").ToString(), g.First().Item("Column2").ToString(), g.First().Item("Column3").ToString(), g.Sum(Function(r) CDec(r("Column4"))), g.First().Item("Column5").ToString(), g.First().Item("Column6").ToString()}, False)) _
    .CopyToDataTable()

Cheers!!

こんにちは

元データがどのようになっているかわかりませんので一概には言えませんが、例えばGroupByの前にWhereをいれて先にColumn4の値に応じてフィルターすれば良いかと思います。例えば下記の様になるのではと思います。

dt = dt.AsEnumerable.Where(Function(r) CInt(r("Column4"))>0).GroupBy(Function(r) r("Column6").ToString).Select(Function(g) dt.Clone.LoadDataRow({g.First().Item("Column0").ToString,g.First().Item("Column1").ToString,g.First().Item("Column2").ToString,g.First().Item("Column3").ToString,g.Sum(Function(r) CDec(r("Column4"))),g.First().Item("Column5").ToString,g.First().Item("Column6").ToString},False)).CopyToDataTable()

このフィルターの場合、負の値がデータテーブル上から消えてしまうと思うのですが、できれば行の並びを変えずに「正の値は合算、負の値はそのまま出力」ということをしたいです。
説明が不足しており申し訳ございません。

それではSumの前でフィルターすれば良いかと思います。可能であれば、ダミーでも良いので、入力となるデータと期待する出力を共有いただくとより良いかと思います。

dt = dt.AsEnumerable.GroupBy(Function(r) r("Column6").ToString).Select(Function(g) dt.Clone.LoadDataRow({g.First().Item("Column0").ToString,g.First().Item("Column1").ToString,g.First().Item("Column2").ToString,g.First().Item("Column3").ToString,g.Where(Function(r) CDec(r("Column4"))>0).Sum(Function(r) CDec(r("Column4"))),g.First().Item("Column5").ToString,g.First().Item("Column6").ToString},False)).CopyToDataTable()

度々すみません。先ほどの式ですと、グルーピングした行について負だけの行しかないときに例外となるように思えますので以下の方が良いかもしれません。

dt = dt.AsEnumerable.GroupBy(Function(r) r("Column6").ToString).Select(Function(g) dt.Clone.LoadDataRow({g.First().Item("Column0").ToString,g.First().Item("Column1").ToString,g.First().Item("Column2").ToString,g.First().Item("Column3").ToString,g.Sum(Function(r) If(CDec(r("Column4"))>0,CDec(r("Column4")),0)),g.First().Item("Column5").ToString,g.First().Item("Column6").ToString},False)).CopyToDataTable()

そちらを試してみましたが、マイナスのデータが消えてしまいました。

g.Sum(Function(r) If(CDec(r("Column4"))>0,CDec(r("Column4")),0)) //マイナスの値の場合、0になっている?

例えば、以下の(集計後)のような結果としたいです。

こんにちは

確認になりますが、負の値と正の値でグルーピングを分けるということでしょうか?
そして正の値のみで合算、負の値のみで合算ということでしょうか?

あと可能でしたら入力データをファイルで共有いただけないでしょうか?
(データ作るのが手間ですので)

正の値のみで合算、負の値は合算しずにそのまま出力を希望しています。

サンプルファイルを共有いたします。
dummy.xlsx (10.4 KB)

サンプルではColumn5が集計されていますが、上記のオリジナルの式ではされていません。どちらが正でしょうか?

申し訳ございません。オリジナルの式の方が正となり、Column5は集計対象外となります。

以下いかがでしょうか?

dt.AsEnumerable.GroupBy(Function(r) Tuple.Create(r("Column6").ToString,CDec(r("Column4"))>0)).SelectMany(Function(g) If(g.Key.Item2,{dt.Clone.LoadDataRow({g.First().Item("Column0").ToString,g.First().Item("Column1").ToString,g.First().Item("Column2").ToString,g.First().Item("Column3").ToString,g.Sum(Function(r) CDec(r("Column4"))),g.First().Item("Column5").ToString,g.First().Item("Column6").ToString},False)},g.ToArray)).CopyToDataTable()

サンプル
Sample20240328-3.zip (11.1 KB)

こちらでやりたいことが実現できました。
誠にありがとうございます。

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.