DataGridViewについて

タグの編集
投稿者 コロン  (社会人) 投稿日時 2019/12/8 19:11:44
お世話になっております。
DataGridViewについてお聞きしたいことがあります。


①:商品コード,金額,消費税額の3列で形成されているDataGridViewがあるとします
②:何も条件をしていせず、検索を行った場合、全ての商品コードのデータを呼び出し、それらの合計金額を算出してテキストボックスに表示します。

  例
     商品CD  金額 消費税額 

     001    300     30  
           002        400           40
     003    500     50
     003    600     60

この場合、金額合計テキストボックスには1800 消費税額テキストボックスには180が表示されます。

③:②でデータを照会した後、商品CDでフィルターをかけ、DataGridViewには商品CD「003」のみ
  表示するようにします。(DBからの再呼出しは行わない予定です)
    ただ、その際に金額合計テキストボックス,消費税額テキストボックスの値は変更されないようにしたいです
  また、現在フィルターによって表示している商品CD「003」の金額や消費税額の値を変更した場合は
  金額合計テキストボックス,消費税額テキストボックスの金額も合わせて変更したいです(商品CD001~003の合算です)


普通にグリッド表示行の金額を加算して表示する方法は分かりますが、一旦グリッドに表示されたデータを絞り込みし、
絞り込まれた後のデータの変化を最初に加算して表示した値に反映(加算,減算)する方法が分かりません。

何卒ご教示のほど、よろしくお願いいたします。


投稿者 るきお  (社会人) 投稿日時 2019/12/8 21:58:43
どのようなプログラムの作りになっているかや具体的にわからないポイントがわからなかったので、VB2019でサンプルを作ってみました。

>一旦グリッドに表示されたデータを絞り込みし、
>絞り込まれた後のデータの変化を最初に加算して表示した値に反映(加算,減算)する方法
絞り込んだ結果は普通に作るとDataViewになるのに対し、
データ本体はDataTableなので常に本体のDataTableの方を集計していれば表示とは関係なく合計を計算できます。

Option Strict On

Public Class Form1

    ''' <summary> 
    ''' フォーム表示時の初期処理 
    ''' </summary> 
    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown

        'データ取得 
        Dim table As DataTable = LoadData()

        '初期表示。あとでフィルターをかける予定なのではじめからDataViewを設定しておく。 
        DataGridView1.DataSource = table.DefaultView

        '初期状態の合計値 
        RefreshAmount()

    End Sub

    ''' <summary> 
    ''' 初期データをロードします。 
    ''' 本来はデータベースから読み込む処理が記述されるはずですが、 
    ''' このサンプルでは固定のデータを返します。 
    ''' </summary> 
    ''' <returns></returns> 
    Private Function LoadData() As DataTable

        Dim table As New DataTable
        table.Columns.Add("商品CD", GetType(String))
        table.Columns.Add("金額", GetType(Integer))
        table.Columns.Add("消費税額", GetType(Integer))

        table.Rows.Add("001", 300, 30)
        table.Rows.Add("002", 400, 40)
        table.Rows.Add("003", 500, 50)
        table.Rows.Add("003", 600, 60)

        Return table

    End Function


    ''' <summary> 
    ''' 合計金額と合計消費税額をLabelに表示します。 
    ''' </summary> 
    Private Sub RefreshAmount()

        '現在バインドされているもとのDataTableを取得 
        Dim table As DataTable = DirectCast(DataGridView1.DataSource, DataView).Table
        Dim amount = Summary(table)

        Label1.Text = amount.TotalKingaku.ToString
        Label2.Text = amount.TotalZeigaku.ToString

    End Sub

    ''' <summary> 
    ''' 合計金額と合計消費税額を計算します。 
    ''' </summary> 
    ''' <param name="table"></param> 
    ''' <returns></returns> 
    Private Function Summary(table As DataTable) As (TotalKingaku As Integer, TotalZeigaku As Integer)

        Dim totalKingaku As Integer
        Dim totalZeigaku As Integer

        For Each row As DataRow In table.Rows
            totalKingaku += CInt(row.Item(1))
            totalZeigaku += CInt(row.Item(2))
        Next

        Return (totalKingaku, totalZeigaku)

    End Function


    ''' <summary> 
    ''' 検索ボタン 
    ''' </summary> 
    ''' <param name="sender"></param> 
    ''' <param name="e"></param> 
    Private Sub btnFilter_Click(sender As Object, e As EventArgs) Handles btnFilter.Click

        Dim table As DataTable = DirectCast(DataGridView1.DataSource, DataView).Table

        If Len(Trim(txtShohinCd.Text)) = 0 Then
            '何も入力されていない場合フィルターを解除 
            table.DefaultView.RowFilter = ""
        Else
            table.DefaultView.RowFilter = "商品CD = " & txtShohinCd.Text
        End If

        'ビューをDataGridViewにバインドさせる。 
        DataGridView1.DataSource = table.DefaultView

    End Sub

    Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
        'DataGridView1のセルが編集された場合合計の表示を更新します。 
        RefreshAmount()
    End Sub


End Class
投稿者 (削除されました)  () 投稿日時 2019/12/8 22:34:45
(削除されました)
投稿者 るきお  (社会人) 投稿日時 2019/12/8 22:51:42
2012であれば、Summaryを次のように変更すれば多分動くと思います。

Private Class Amount
    Public TotalKingaku As Integer
    Public TotalZeigaku As Integer
End Class

''' <summary> 
''' 合計金額と合計消費税額を計算します。 
''' </summary> 
''' <param name="table"></param> 
''' <returns></returns> 
Private Function Summary(table As DataTable) As Amount

    Dim totalKingaku As Integer
    Dim totalZeigaku As Integer

    For Each row As DataRow In table.Rows
        totalKingaku += CInt(row.Item(1))
        totalZeigaku += CInt(row.Item(2))
    Next

    Dim result As New Amount
    result.TotalKingaku = totalKingaku
    result.TotalZeigaku = totalZeigaku

    Return result

End Function
投稿者 コロン  (社会人) 投稿日時 2019/12/8 23:01:59
るきお様 

大変ご丁寧にご教示いただき、有難うございます。
また、質問の際に不明瞭な点があったようで申し訳ございません。
本来、私の分からなかった点としましては、グリッド初期表示時の総合計を保持することは可能だが
フィルターをかけて値を変更した際、その変更した値をどのように反映すべきか という点でしたが
根本的にViewという仕組みを理解できていないことが問題でした

また、折角VisualStudio2019にてサンプルコードを作って下さりましたが、私の環境はBisualStudio2012
でして、そのままでは動かなかったので少し改変させていただきました。
この件に関しても環境の記述がなかったためにご迷惑をおかけしていまい申し訳ありません。
以後気を付けます。

以下、改変させていただいた部分のみ記載いたします。


  ''' <summary> 
    ''' 合計金額と合計消費税額をLabelに表示します。 
    ''' </summary> 
    Private Sub RefreshAmount()
        Call Summary()
    End Sub

    ''' <summary> 
    ''' 合計金額と合計消費税額を計算します。 
    ''' </summary> 
    Private Sub Summary()

        Dim totalKingaku As Integer
        Dim totalZeigaku As Integer
        Dim dt As DataTable = Nothing
        Dim i As Integer = 0

        dt = DirectCast(DataGridView1.DataSource, DataView).Table

        For i = 0 To dt.Rows.Count - 1
            totalKingaku = totalKingaku + CInt(dt.Rows(i).Item("金額").ToString)
            totalZeigaku = totalZeigaku + CInt(dt.Rows(i).Item("消費税額").ToString)
        Next

        Label1.Text = totalKingaku.ToString
        Label2.Text = totalZeigaku.ToString
    End Sub



フィルターをかけるとViewになるが、変更はTableにも反映されるということを学べて大変勉強になりました。
重ね重ねになりますが、本当にありがとうございました。
投稿者 コロン  (社会人) 投稿日時 2019/12/8 23:04:15
るきお様

動かないので質問をしようと書き込んだのは良いものの、自身で考えられるところではないのか
と思い、投稿を削除してしまい申し訳ありません。
また、その間にお返事をくださり、ありがとうございます。

るきお様がお答えくださった内容は私の思いつく内容とは異なっているので、そのようなやり方
だと、よりスマートに書けるのだと驚きました。 どのように動いているのか勉強させていただきます!
投稿者 (削除されました)  () 投稿日時 2020/1/7 15:52:00
(削除されました)