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

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

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

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

VB.NET

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

Q&A

解決済

2回答

1607閲覧

VB.NET:DB.Nullを含むテーブルの特定列データ行の小計列、合計列を追加

Kouta2020

総合スコア2

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

VB.NET

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

0グッド

0クリップ

投稿2021/02/07 13:44

編集2021/02/08 22:36

前提・実現したいこと

複数テーブルを結合して特定列データ行の小計列、合計列を追加しようとしています。
ただし、結合テーブルの中にDB.Nullが含まれます。

https://teratail.com/questions/320488
にてDecimal型すべての合計列の追加はDBNull なら 0 に書き換える方法で一旦解決しております。
(希望する結果をそのように指定していたため)

前スレッドでベストアンサーを決定した後、実際のデータでいろいろ試している最中にDB.Nullと0を区別して表示させた方がよいと思うところがありましたので、新しいスレッドを作らせて頂きました。
今回はDB.Nullをテーブル表示として残す方法を模索しております。

結合テーブル
HIN CODE1 CODE2 CODEME1 CODEME2
100 101 102
110 111 112
300 121 142 221 242
310 131 152 231 252
200 201 202
210 211 212

希望する結果(今回はDB.Nullの表示をそのまま残します)
HIN  CODE1 CODE2 CODEME1 CODEME2 subtotal1 subtotal2 total
100 101 102 101 102 203
110 111 112 111 112 223
300 121 142 221 242 342 384 726
310 131 152 231 252 362 404 766
200 201 202 201 202 403
210 211 212 211 212 423

subtotal1はCODE1,CODEME1の合計値(DB.Nullは0として計算)
subtotal2はCODE2,CODEME2の合計値(DB.Nullは0として計算)
totalはCODE1,CODE2,CODEME1,CODEME2の合計値

発生している問題

下記ソースコードでサンプルデータの希望する実行結果は得られていますが、 今後計算する列数が増えた場合に、Decimal型かどうかのIF文が複雑になってしまいます。 列数が増えても複雑にならないスマートな記述方法を探しております。

該当のソースコード

VB

1Imports System 2Imports System.Data 3Imports System.Windows.Forms 4 5Public Class Form1 6 7 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 8 9 Dim table As DataTable = New DataTable() 10 table.Merge(CreateDataTable1()) 11 table.Merge(CreateDataTable2()) 12 table.Columns.Add("subtotal1", GetType(Decimal)) 13 table.Columns.Add("subtotal2", GetType(Decimal)) 14 table.Columns.Add("total", GetType(Decimal)) 15 16 Dim subtotal1 As Decimal = 0D 17 Dim subtotal2 As Decimal = 0D 18 Dim total As Decimal = 0D 19 20 For i As Integer = 0 To table.Rows.Count - 1 21 If TypeOf table.Rows(i).Item("CODE1") Is Decimal And TypeOf table.Rows(i).Item("CODEME1") Is Decimal Then 22 subtotal1 = table.Rows(i).Item("CODE1") + table.Rows(i).Item("CODEME1") 23 End If 24 If TypeOf table.Rows(i).Item("CODE1") Is Decimal And TypeOf table.Rows(i).Item("CODEME1") IsNot Decimal Then 25 subtotal1 = table.Rows(i).Item("CODE1") 26 End If 27 If TypeOf table.Rows(i).Item("CODE1") IsNot Decimal And TypeOf table.Rows(i).Item("CODEME1") Is Decimal Then 28 subtotal1 = table.Rows(i).Item("CODEME1") 29 End If 30 If TypeOf table.Rows(i).Item("CODE2") Is Decimal And TypeOf table.Rows(i).Item("CODEME2") Is Decimal Then 31 subtotal2 = table.Rows(i).Item("CODE2") + table.Rows(i).Item("CODEME2") 32 End If 33 If TypeOf table.Rows(i).Item("CODE2") Is Decimal And TypeOf table.Rows(i).Item("CODEME2") IsNot Decimal Then 34 subtotal2 = table.Rows(i).Item("CODE2") 35 End If 36 If TypeOf table.Rows(i).Item("CODE2") IsNot Decimal And TypeOf table.Rows(i).Item("CODEME2") Is Decimal Then 37 subtotal2 = table.Rows(i).Item("CODEME2") 38 End If 39 40 table.Rows(i).Item("subtotal1") = subtotal1 41 table.Rows(i).Item("subtotal2") = subtotal2 42 table.Rows(i).Item("total") = subtotal1 + subtotal2 43 Next 44 45 Me.DataGridView1.DataSource = table 46 End Sub 47 48 Protected Function CreateDataTable1() As DataTable 49 Dim table As DataTable = New DataTable() 50 Dim idColumn As DataColumn = New DataColumn("HIN", GetType(String)) 51 table.Columns.Add(idColumn) 52 table.Columns.Add(New DataColumn("CODE1", GetType(Decimal))) 53 table.Columns.Add(New DataColumn("CODE2", GetType(Decimal))) 54 table.Rows.Add("100", 101D, 102D) 55 table.Rows.Add("110", 111D, 112D) 56 table.Rows.Add("300", 121D, 142D) 57 table.Rows.Add("310", 131D, 152D) 58 table.PrimaryKey = New DataColumn() {idColumn} 59 Return table 60 End Function 61 62 Protected Function CreateDataTable2() As DataTable 63 Dim table As DataTable = New DataTable() 64 table.Columns.Add(New DataColumn("HIN", GetType(String))) 65 table.Columns.Add(New DataColumn("CODEME1", GetType(Decimal))) 66 table.Columns.Add(New DataColumn("CODEME2", GetType(Decimal))) 67 table.Rows.Add("200", 201D, 202D) 68 table.Rows.Add("210", 211D, 212D) 69 table.Rows.Add("300", 221D, 242D) 70 table.Rows.Add("310", 231D, 252D) 71 Return table 72 End Function 73 74 75End Class

補足情報(FW/ツールのバージョンなど)

OS Windows10
VB.NET

Microsoft Visual Studio Community 2017
Version 15.6.7
VisualStudio.15.Release/15.6.7+27428.2043
Microsoft .NET Framework
Version 4.8.04084

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/02/08 00:21 編集

前回の方法でDBNullを置換し、その後合計すればDecimal判定は不要だと思いますが。DBNullを残したいということ? あと回答ではないですが、table.Rows(i).Item("XXX") みたいなのを使いまくるくらいなら、For Each でDataRow を変数に受けた方がスッキリします。 For Each row As DataRow In table.Rows row("XXX") = … Next
退会済みユーザー

退会済みユーザー

2021/02/07 15:49

前のスレッドの url を書いてその続きであることを明記しよう。
退会済みユーザー

退会済みユーザー

2021/02/07 23:15

前のスレッドで DataTable の中身が DBNull なら 0 に書き換える回答をベストアンサーにしたのだから、その延長でいいのでは?
Kouta2020

2021/02/08 14:46

radian様、前スレッドから続けてのコメントありがとうございます。 希望する結果で示したつもりが、きちんと言葉にしていなかったため分かりづらくてすみません。 おっしゃる通りDB.Nullをテーブル表示として残す方法を得たいため再度新しくスレッドを立ち上げました。
Kouta2020

2021/02/08 14:56

SurferOnWww様、引き続きコメントありがとうございます。 前スレッドで質問した時は希望する結果にDB.Nullに0を入れるテーブルを示していましたので、 それに合っていた回答ということで解決したつもりでした。 前スレッドでベストアンサーを決定した後、実際のデータでいろいろ試している最中にDB.Nullと0を区別して表示させた方がよいと思うところがありましたので、新しいスレッドを作らせて頂きました。 希望する結果で示したつもりだったのですが、説明不足ですみませんでした。
退会済みユーザー

退会済みユーザー

2021/02/08 21:52

質問欄を編集してその事を追記してください。
Kouta2020

2021/02/08 22:38

SurferOnWww様、コメントありがとうございます。 質問欄を編集致しました。ご指摘ごもっともです。
退会済みユーザー

退会済みユーザー

2021/02/08 22:50 編集

上の radian さんのコメント > table.Rows(i).Item("XXX") みたいなのを使いまくるくらいなら、For Each でDataRow を変数に受けた方がスッキリします。 For Each row As DataRow In table.Rows row("XXX") = … Next もよく考えてみることをお勧めします。
Kouta2020

2021/02/11 15:09

SurferOnWww様、お勧めありがとうございます。 上の radian さんのコメントを自分なりによく考えて、遅くなりましたが以下のプログラムに改善してみました。 For Each row As DataRow In table.Rows Dim C1 = row("CODE1") Dim C2 = row("CODE2") Dim CM1 = row("CODEME1") Dim CM2 = row("CODEME2") row("subtotal1") = If(TypeOf C1 Is Decimal, C1, 0) + If(TypeOf CM1 Is Decimal, CM1, 0) row("subtotal2") = If(TypeOf C2 Is Decimal, C2, 0) + If(TypeOf CM2 Is Decimal, CM2, 0) row("total") = row("subtotal1") + row("subtotal2") Next
guest

回答2

0

ベストアンサー

DataColumn に式を設定したらどうでしょう。
DataColumn.Expression プロパティ

vbnet

1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 2 Dim table = New DataTable() 3 table.Merge(CreateDataTable1()) 4 table.Merge(CreateDataTable2()) 5 table.Columns.Add("subtotal1", GetType(Decimal), "ISNULL(CODE1,0) + ISNULL(CODEME1,0)") 6 table.Columns.Add("subtotal2", GetType(Decimal), "ISNULL(CODE2,0) + ISNULL(CODEME2,0)") 7 table.Columns.Add("total", GetType(Decimal), "subtotal1 + subtotal2") 8 Me.DataGridView1.DataSource = table 9 End Sub

投稿2021/02/08 15:35

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Kouta2020

2021/02/08 22:27

radian様、回答ありがとうございます。 回答頂いた内容にて希望する結果が得られました。 とてもシンプルで、DataColumn.Expressionも大変参考になり、今後にとても役立ちそうです。
guest

0

私なら以下のように書きますか。

VBnet

1Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 2 3 Dim table As DataTable = New DataTable() 4 Dim t1 As String = "subtotal1" 5 Dim t2 As String = "subtotal2" 6 Dim t3 As String = "total" 7 8 With table 9 .Merge(CreateDataTable1()) 10 .Merge(CreateDataTable2()) 11 .Columns.Add(t1, GetType(Decimal)) 12 .Columns.Add(t2, GetType(Decimal)) 13 .Columns.Add(t3, GetType(Decimal)) 14 End With 15 16 For i As Integer = 0 To table.Rows.Count - 1 17 18 With table.Rows(i) 19 .Item(t1) = ToDecimal(.Item("CODE1")) + ToDecimal(.Item("CODEME1")) 20 .Item(t2) = ToDecimal(.Item("CODE2")) + ToDecimal(.Item("CODEME2")) 21 .Item(t3) = ToDecimal(.Item(t1)) + ToDecimal(.Item(t2)) 22 End With 23 24 Next 25 26 Me.DataGridView1.DataSource = table 27 28End Sub 29 30Private Function ToDecimal(ByVal o As Object) As Decimal 31 32 If IsDBNull(o) Then Return 0D 33 34 Return If(TypeOf o Is Decimal, CDec(o), 0D) 35 36End Function

投稿2021/02/08 10:16

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Kouta2020

2021/02/08 15:28

sanshimon様、回答ありがとうございます。 回答頂いた内容にて希望する結果が得られました。 ToDecimal関数を作成するアイデアはとても私一人で思いつきませんでした。 後学のため、他の回答も参考にしたいのでもうしばらく待ちたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問