none
VS2010PROでtextbox2.textに入力した数値だけ同じレコードのコピーをDataTableに追加したい RRS feed

  • 質問

  • 下記のコードを用いて得意先を抽出しデータテーブルを作成し、その内容をデータグリッドビューで表示させています。
    抽出したレコードのコピーをTextBox2.Textに入力した数値だけ抽出したレコードのコピーをDataTableに追加したい のですが、どうすれば良いでしょうか?
    作業は複数回行いますので、上書きではない方法になります。現状、どんな数値を入れても1になります。8と入力なら8になります。その後9と入力したなら9となります。つまり8+9で17になります。

    抽出したレコードのコピーとそれをデータテーブルに追加方法がわかりません。

    Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
    'プログラムコード
    Dim Cn As New OleDbConnection
    Dim Command As OleDbCommand = New OleDbCommand
    Dim OLEDBCon As OleDb.OleDbConnection = _
    New OleDb.OleDbConnection
    OLEDBCon.ConnectionString = _
    "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source=" & Form1.TextBox1.Text & ";" & _
    "Persist Security Info=False"
    Command.Connection = OLEDBCon
    'データテーブルに印刷枚数を保持する列
    Command.CommandText = "select 郵便番号,住所1,住所2,得意先コード,得意先名,0 as 印刷枚数 from 得意先T where 得意先コード = @得意先コード "
    Command.Parameters.AddWithValue("@得意先コード", TextBox1.Text)
    Dim Adapter As OleDbDataAdapter = New OleDbDataAdapter
    Adapter.SelectCommand = Command
    Adapter.Fill(dt)

    'レコード取得
    TextBox3.Text = CStr(dt.Rows(dt.Rows.Count - 1).Item(0))
    TextBox4.Text = CStr(dt.Rows(dt.Rows.Count - 1).Item(1))
    TextBox5.Text = CStr(dt.Rows(dt.Rows.Count - 1).Item(2))
    TextBox6.Text = CStr(dt.Rows(dt.Rows.Count - 1).Item(3)

    '印刷枚数
    Dim d As String = TextBox2.Text
    TextBox8.Text = d
    Dim Row As DataRow = dt.Rows(count)
    Row("印刷枚数") = TextBox2.Text
    count = count + 1

    '敬称区分
    Dim b As DataColumn = dt.Columns.Item("敬称")
    If b Is Nothing Then
    dt.Columns.Add("敬称", GetType(String))
    End If
    If RadioButton1.Checked = True Then
    Row("敬称") = RadioButton1.Text
    ElseIf RadioButton2.Checked = True Then
    Row("敬称") = RadioButton2.Text
    ElseIf RadioButton3.Checked = True Then
    Row("敬称") = RadioButton3.Text
    End If
    'データテーブルの内容をDGVで確認
    DataGridView1.DataSource = dt
    End Sub

    以上、宜しくお願いします

    2013年1月19日 9:15

回答

  • とりあえず基本的なコードを載せますので、考え方を理解して下さい。

    Imports System.Data.OleDb
     
    Public Class 名簿印刷
     
        Dim dt名簿 As DataTable = New DataTable()
        Dim dt印刷用 As DataTable
     
        Private Sub cbttn_名簿データ読み込み_Click(sender As System.Object, e As System.EventArgs) Handles cbttn_名簿データ読み込み.Click
     
            Dim cnn = New OleDbConnection
            Dim cmd = New OleDbCommand()
            Dim adapter = New OleDbDataAdapter
      
            cnn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\db1.mdb;Persist Security Info=Fals"
            cmd.Connection = cnn
     
            'データテーブルに印刷枚数を保持する列
            cmd.CommandText = "select ID, 氏名, 住所, '様' as 敬称, 0 as 印刷枚数 from 名簿"
     
            adapter.SelectCommand = cmd
            adapter.Fill(dt名簿)
     
            DataGridView1.DataSource = dt名簿
      
        End Sub
     
        Private Sub cbttn_印刷データ作成_Click(sender As System.Object, e As System.EventArgs) Handles cbttn_印刷データ作成.Click
     
            dt印刷用 = dt名簿.Clone
     
            For Each dr In dt名簿.Rows
     
                For i = 1 To dr("印刷枚数")
                    dt印刷用.ImportRow(dr)
                Next
     
            Next
     
            DataGridView2.DataSource = dt印刷用
     
        End Sub
     
    End Class


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kix7 2013年1月23日 5:59
    2013年1月22日 7:52
    モデレータ

すべての返信

  • 一つのデータテーブルに追加するのではなく、印刷用に別のデータテーブルを作成し、そこで印刷枚数分のレコードを増やしましょう。以下に、同じ構造を持ったの他のテーブルへレコードをコピーする方法が載っています。これを参考にし、DataGridView1に表示しているデータテーブルを1行ずつ読みながら、その行の印刷枚数カラムに応じた数のImportRowメソッドを実行すれば、印刷用データテーブルには、その数分のレコードが増えることになります。
    あとはこの印刷用データテーブルをクリスタルレポートに渡すだけです。

    Visual Basic .NET を使用して DataTable 間で DataRow をコピーする方法
    http://support.microsoft.com/kb/305346/ja


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2013年1月21日 10:51
    モデレータ
  • trapemiya様

    ありがとうございます。コードを考えました。テキストボックス2に、3を入力すると、プレビューで5枚表示されます。続けて5を入力すると、プレビューで7枚表示されます。
    本来であれば、3+5なので8枚表示されるはずのなのですが、プレビューでは12枚になります。

    '抽出したレコードをデータテーブルに追加

    Dim i As Integer = TextBox2.Text
    For i = 0 To TextBox2.Text

    Dim workRow As DataRow
    workRow = dt.NewRow()
    workRow(0) = TextBox3.Text

    workRow(1) = TextBox4.Text

    workRow(2) = TextBox5.Text
    workRow(3) = TextBox6.Text

    workRow(4) = TextBox7.Text
    workRow(5) = TextBox8.Text

    workRow(6) = TextBox9.Text
    dt.Rows.Add(workRow)
    Next

    上記のコードですと、抽出したレコード(得意先)が複数表示され、データグリッドビューに表示されるのですが、テキストボックス2に入力した数値とDataTableに追加する数値が一致しません。ご教授の程宜しくお願い申し上げます

    2013年1月21日 11:52
  • For文のインデックスは、i = 0ですから、0から始まっています。3を入力すれば、以下のようになります。
    For i=0 To 3
    つまり、0, 1, 2, 3と、4回繰り返されることになります。よって、4行増えることになりますから、元からあった1行と合わせて合計で5枚になるのでしょう。5を入力した場合も同様に、7枚になります。(元からあった1行と6行増えた合計で7枚)
    よって、プレビューでは5行+7行で12行になっているのだと思います。(掲載されたコードしかみていないので、想像です)


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2013年1月21日 14:27
    モデレータ
  • trapemiya様

    ありがとうございます。下記コードに変更しテキストボックスの値を取得する事ができました。

    '抽出したレコードをデータテーブルに追加
            Dim m As Integer
            If Integer.TryParse(TextBox2.Text, m) Then
                For i = 1 To m
                    Dim workRow As DataRow
                    workRow = dt.NewRow()
                    workRow(0) = TextBox3.Text
                    workRow(1) = TextBox4.Text
                    workRow(2) = TextBox5.Text
                    workRow(3) = TextBox6.Text
                    workRow(4) = TextBox7.Text
                    workRow(5) = TextBox8.Text
                    workRow(6) = TextBox9.Text
                    dt.Rows.Add(workRow)
                   Next
            End If

      'データテーブルの内容をデータグリッドで確認
            DataGridView1.DataSource = dt
            DataGridView1.Rows(0).Visible = False ※

    得意先毎に印刷枚数が異なります。元にある1行を消すために※を追加しましたが、現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。と表示されます。

    得意先毎で表示される1行目を削除するにはどうすれば良いでしょうか?

    2013年1月22日 4:31
  • データテーブルがバインドしている場合、DataGridViewの現在の行(カレント行)は、CurrenyManagerによって管理されています。カレント行の位置はCurrenyManagerのPositionプロパティで表されますし、DataGridViewのカレント行はDataGridViewのCurrentRowプロパティで得られます。
    カレント行は今現在の行ですから、それを非表示にすることはできないのです。
    ここは発想を変えて非表示にするのではなく、3枚であれば最初から2つのレコードのみを追加するようにすれば良いように思いますが、いかがでしょうか?


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2013年1月22日 4:48
    モデレータ
  • trapemiya様

    ありがとうございます。

    >3枚であれば最初から2つのレコードのみを追加するようにすれば良いように思いますが、いかがでしょうか?

    →得意先毎に設定する事が可能という事でしょうか?

    ただテキストボックス2に数値を入れ、for~next構文で繰り返しをしているのですが。

    その発想が全くなく、まだまだであると痛感しております。

    ご教授の程お願いします。

    2013年1月22日 5:08
  • とりあえず基本的なコードを載せますので、考え方を理解して下さい。

    Imports System.Data.OleDb
     
    Public Class 名簿印刷
     
        Dim dt名簿 As DataTable = New DataTable()
        Dim dt印刷用 As DataTable
     
        Private Sub cbttn_名簿データ読み込み_Click(sender As System.Object, e As System.EventArgs) Handles cbttn_名簿データ読み込み.Click
     
            Dim cnn = New OleDbConnection
            Dim cmd = New OleDbCommand()
            Dim adapter = New OleDbDataAdapter
      
            cnn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\db1.mdb;Persist Security Info=Fals"
            cmd.Connection = cnn
     
            'データテーブルに印刷枚数を保持する列
            cmd.CommandText = "select ID, 氏名, 住所, '様' as 敬称, 0 as 印刷枚数 from 名簿"
     
            adapter.SelectCommand = cmd
            adapter.Fill(dt名簿)
     
            DataGridView1.DataSource = dt名簿
      
        End Sub
     
        Private Sub cbttn_印刷データ作成_Click(sender As System.Object, e As System.EventArgs) Handles cbttn_印刷データ作成.Click
     
            dt印刷用 = dt名簿.Clone
     
            For Each dr In dt名簿.Rows
     
                For i = 1 To dr("印刷枚数")
                    dt印刷用.ImportRow(dr)
                Next
     
            Next
     
            DataGridView2.DataSource = dt印刷用
     
        End Sub
     
    End Class


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kix7 2013年1月23日 5:59
    2013年1月22日 7:52
    モデレータ
  • trapemiya様

    詳しい回答ありがとうございます。大変参考になりました。

    今後も宜しくお願い致します。

    2013年1月23日 5:59