質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.36%
LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

2回答

584閲覧

VB.Net LINQを使用した集計方法の条件付与について

msms_ms

総合スコア1

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2024/03/28 03:38

実現したいこと

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()

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

IF文を追加してみたりしましたが、「>」が使用できない等のエラーが出てきました。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

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

表機能等で元データと希望の結果を提示いただくと、他人にも伝わりやすいです。

Column0Column4Column6
Row010Group1
Row1-20Group1
Row230Group1
Row3-100Group2
Row4200Group2

IF文を追加してみたりしましたが、「>」が使用できない等のエラーが出てきました。

ReturnEndがなかった等じゃないですかね?
ラムダ式 - Visual Basic | Microsoft Learn

そのコードや正しいエラー文も提示いただくと、他人にも伝わりやすいです。
ヘルプ|質問するときのヒント

この場合、負の値がデータテーブルに残らなくなってしまいますのでやりたいこととは異なるようです。
正の場合は合算を行い、負の場合は合算を行わずそのまま出力を行いたいという希望になります。

nururiさんの回答でWhereで除外して集計されていますが、その後にマイナス値の行を追加すれば希望通りということでしょうか?

dt.Clone.LoadDataRow

だいぶ無駄っぽい気がします。


VBはよくわからないのでC#で(msms_msさんが「これじゃ全然わからない」ということであれば、頑張ってVBにしてみますけど^^;

cs

1using System.Data; 2 3namespace Qmiaghvxqhdj00i; 4 5public partial class Form1 : Form 6{ 7 public Form1() 8 { 9 InitializeComponent(); 10 11 var dt = new DataTable(); 12 13 dt.Columns.Add("Column0"); 14 dt.Columns.Add("Column4", typeof(decimal)); 15 dt.Columns.Add("Column6"); 16 17 dt.Rows.Add("Row0", 10m, "Group1"); 18 dt.Rows.Add("Row1", -20m, "Group1"); 19 dt.Rows.Add("Row2", 30m, "Group1"); 20 dt.Rows.Add("Row3", -100m, "Group2"); 21 dt.Rows.Add("Row4", 200m, "Group2"); 22 23 24 // 現状 25 var msms_ms = dt.AsEnumerable() 26 .GroupBy(r => r["Column6"].ToString()) 27 .Select(g => 28 { 29 var row = dt.NewRow(); 30 row["Column0"] = g.First()["Column0"].ToString(); 31 row["Column4"] = g.Sum(r => (decimal)r["Column4"]); 32 row["Column6"] = g.First()["Column6"].ToString(); 33 return row; 34 }) 35 .CopyToDataTable(); 36 37 38 // 負の値を除外して集計 39 var nururi = dt.AsEnumerable() 40 .Where(r => (decimal)r["Column4"] >= 0) 41 .GroupBy(r => r["Column6"].ToString()) 42 .Select(g => 43 { 44 var row = dt.NewRow(); 45 row["Column0"] = g.First()["Column0"].ToString(); 46 row["Column4"] = g.Sum(r => (decimal)r["Column4"]); 47 row["Column6"] = g.First()["Column6"].ToString(); 48 return row; 49 }) 50 .CopyToDataTable(); 51 // 後、負の値の行をマージ 52 var minus = dt.AsEnumerable() 53 .Where(r => (decimal)r["Column4"] < 0) 54 .CopyToDataTable(); 55 nururi.Merge(minus); 56 57 58 var tn8001 = dt.AsEnumerable() 59 .GroupBy(r => 60 { 61 // グループ化するキーを負の値でなければそのまま 62 if (0 < (decimal)r["Column4"]) 63 return r["Column6"].ToString(); 64 65 // 負の値だったら何かユニークな値にすれば、別のグループとして扱われる 66 else 67 // ちょっと危ないか?全カラムを連結するとか?? 68 return r.GetHashCode().ToString(); 69 }) 70 .Select(g => 71 { 72 var row = dt.NewRow(); 73 row["Column0"] = g.First()["Column0"].ToString(); 74 row["Column4"] = g.Sum(r => (decimal)r["Column4"]); 75 row["Column6"] = g.First()["Column6"].ToString(); 76 return row; 77 }) 78 .CopyToDataTable(); 79 80 81 dataGridView1.DataSource = dt; 82 dataGridView2.DataSource = msms_ms; 83 dataGridView3.DataSource = nururi; 84 dataGridView4.DataSource = tn8001; 85 } 86}

アプリ画像
下ふたつで順番が違いますが、DataTableの追加順はあまり意味はないので問題ないでしょう(実際はIdや作成日等のカラムがあるでしょうから好きにソートすればいい)

追記

vb.net

1Public Class Form1 2 Public Sub New() 3 InitializeComponent() 4 5 Dim dt = New DataTable 6 dt.Columns.Add("Column0") 7 dt.Columns.Add("Column4", GetType(Decimal)) 8 dt.Columns.Add("Column6") 9 dt.Rows.Add("Row0", 10D, "Group1") 10 dt.Rows.Add("Row1", -20D, "Group1") 11 dt.Rows.Add("Row2", 30D, "Group1") 12 dt.Rows.Add("Row3", -100D, "Group2") 13 dt.Rows.Add("Row4", 200D, "Group2") 14 15 16 '現状 17 Dim msms_ms = dt.AsEnumerable _ 18 .GroupBy(Function(r) r("Column6").ToString) _ 19 .Select(Function(g) 20 Dim row = dt.NewRow 21 row("Column0") = g.First()("Column0").ToString 22 row("Column4") = g.Sum(Function(r) CDec(r("Column4"))) 23 row("Column6") = g.First()("Column6").ToString 24 Return row 25 26 'カラムが多いならこれが手っ取り早いかな(何が入っているかにもよるが... 27 'Dim row = dt.NewRow 28 'row.ItemArray = g.First().ItemArray 29 'row("Column4") = g.Sum(Function(r) CDec(r("Column4"))) 30 'Return row 31 End Function) _ 32 .CopyToDataTable 33 34 35 '負の値を除外して集計後、負の値の行をマージ 36 Dim nururi = dt.AsEnumerable _ 37 .Where(Function(r) CDec(r("Column4")) >= 0) _ 38 .GroupBy(Function(r) r("Column6").ToString) _ 39 .Select(Function(g) 40 Dim row = dt.NewRow 41 row("Column0") = g.First()("Column0").ToString 42 row("Column4") = g.Sum(Function(r) CDec(r("Column4"))) 43 row("Column6") = g.First()("Column6").ToString 44 Return row 45 End Function) _ 46 .CopyToDataTable 47 Dim minus = dt.AsEnumerable _ 48 .Where(Function(r) CDec(r("Column4")) < 0) _ 49 .CopyToDataTable 50 nururi.Merge(minus) 51 52 53 'キー細工 54 Dim tn8001 = dt.AsEnumerable _ 55 .GroupBy(Function(r) 56 'グループ化するキーを負の値でなければそのまま 57 If 0 < CDec(r("Column4")) Then 58 Return r("Column6").ToString 59 60 Else '負の値だったら何かユニークな値にすれば、別のグループとして扱われる 61 'ちょっと危ないか? ハッシュが衝突するというより、 62 '(わたしは)Column6に何が入ってるか知らないという意味で。 63 '(数字が入っていたらぶつかる可能性もあるかも?と) 64 Return r.GetHashCode.ToString 65 66 'あるいは全カラムを連結するとか? 67 68 'Guidがいいか? 69 'Return Guid.NewGuid.ToString 70 End If 71 End Function) _ 72 .Select(Function(g) 73 Dim row = dt.NewRow 74 row("Column0") = g.First()("Column0").ToString 75 row("Column4") = g.Sum(Function(r) CDec(r("Column4"))) 76 row("Column6") = g.First()("Column6").ToString 77 Return row 78 End Function) _ 79 .CopyToDataTable 80 81 82 DataGridView1.DataSource = dt 83 DataGridView2.DataSource = msms_ms 84 DataGridView3.DataSource = nururi 85 DataGridView4.DataSource = tn8001 86 End Sub 87End Class

投稿2024/03/28 15:53

編集2024/03/29 21:56
TN8001

総合スコア9855

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

GroupByの前に、Whereで条件指定すればいいと思います。

vb.net

1Where(Function(row) Convert.ToInt32(row("Column4")) >= 0)

適当にConvert.ToInt32とかしちゃってますが、元が違う型なら別のものを指定してください。

投稿2024/03/28 04:47

編集2024/03/28 04:51
nururi

総合スコア158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

msms_ms

2024/03/28 08:25 編集

この場合、負の値がデータテーブルに残らなくなってしまいますのでやりたいこととは異なるようです。 正の場合は合算を行い、負の場合は合算を行わずそのまま出力を行いたいという希望になります。
nururi

2024/03/29 01:19

であれば、LINQ一行でやろうとか難しく考えずに、シンプルに負と正のデータに分けてマージした方が判りやすいのではないでしょうか。 質問に書いてあるLINQは、横に長すぎて正直読む気がしません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問