QA@IT

データテーブルの登録について

2740 PV

VS2010PROで、宛名印刷プログラムを作っています。
フォームで取引先情報をアクセスから検索し、データテーブルにしています。
印刷する取引先が単数(1社)でも複数(2社以上)でも、1つのデータテーブルにしていますが、
複数(2社以上)の取引先を印刷する場合に関して、複数のデータテーブルとして登録することは出来るのでしょうか?
(現状のコードですと、印刷する得意先が単数でも複数でも、1つのデータテーブルに登録されます)

たとえば、3社の取引先を印刷する場合、異なる取引先を3件登録し、印刷枚数も異なる枚数にして、
それを1つのデータテーブル(DT)にしていますが、DT1、DT2、DT3と言ったように登録したく思いますが
可能でしょうか?DT1と2と3ですが、それぞれ異なる得意先で、それぞれ印刷枚数も異なります。
以下コードになります。

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=" & Form3.TextBox4.Text & ";" & _
"Persist Security Info=False"
Command.Connection = OLEDBCon
Command.CommandText = "select 郵便,住所①,住所②,取引先コード,取引先名,0 as 枚数 from 取引先T where 取引先コード = @取引先コード "
Command.Parameters.AddWithValue("@取引先コード", TextBox1.Text)
Dim Adapter As OleDbDataAdapter = New OleDbDataAdapter
Adapter.SelectCommand = Command
Adapter.Fill(dt)

Fillする度に動的にdtのインスタンスを作成して、管理する方法を検討しておりますが、
全く見当が付きません。
ご教授ください。
宜しくお願いします。

  • いまは、dtのインスタンスをどうやって生成しているのですか? -
  • パラメータを@取引先コードにしています。複数の取引先があった場合、上記に掲載されたコードを、その取引先数分の回数、実行しています。 -

回答

こんばんは。

勝手ながら提示されたコードを少し整理&拡張してみました。
たとえば以下の様なメソッドで複数の取引先に対応させた場合、
以下のソースではDataTableのListを返却するようにしてみましたが、
そういう「DataTableを量産するようなやり方で良いのか?」という質問でよろしいですか?

Public Function SelectTarget(datasourceName As String, _
               tcodeList As List(Of String)) As List(Of DataTable)


  Dim datatables = New List(Of DataTable)()
  'Dim ds As New DataSet()

  For Each tcode In tcodeList


    Using oleDbCon = New OleDb.OleDbConnection( _
      "Provider=Microsoft.Jet.OLEDB.4.0;" & _
      "Data Source=" & datasourceName & ";" & _
      "Persist Security Info=False")

      Using command = oleDbCon.CreateCommand()

        command.CommandText = _
          " select 郵便, 住所①, 住所②, 取引先コード, 取引先名, 0 as 枚数 " _
          & " from 取引先T " _
          & "  where 取引先コード = @取引先コード "
        command.Parameters.AddWithValue("@取引先コード", tcode)

        Dim dt = New DataTable(tcode)
        dt.Load(command.ExecuteReader())

        'Dim adapter As OleDbDataAdapter = New OleDbDataAdapter
        'adapter.SelectCommand = command
        'adapter.Fill(dt)

        datatables.Add(dt)
        'ds.Tables.Add(dt)

      End Using
    End Using
  Next

  Return datatables

End Function

' SelectTarget("<データソース>", New List(Of String)({"001", "002"})
' みたいに使います
' ただし上記コードは一度も動かしたことありません。コンパイルはしたけど。

やり方はいろいろあり、ケースバイケースではありますが、
件数がそれほどでもない場合はデータテーブルを複数作成しても良いでしょう。

複数のDataTableをどうまとめるかについては、普通はListや配列を使うよりはDataSetを使うでしょうかね(上記コードではコメントアウトしてありますが)。

それ以外には一つのDataTableに今回出力する分を(取引先が複数であっても)全て格納して取得してしまい、
宛名を出力するときにDataTableのFilter機能でフィルタリングしたり、ループで回す時に必要なデータだけ見るという手もあります。

' 001 の出力
For Each r In dt.Rows
  If r("取引先コード").ToString() = "001" Then

  End If
Next
' 上と同じ事を違う書き方で1
For Each r In dt.AsEnumerable() _
  .Where(Function(x) x("取引先コード").ToString() = "001")

Next
' 上と同じ事を違う書き方で2
For Each r In dt.Select("取引先コード = '001'");

Next

取得件数が多い場合は他にも考えることが出てきますが、
想定件数が多くないのであればどれを選んでもよいでしょう。
(たとえば検索結果が1000万件のデータを扱う場合は、1000万件をDataTableに
全てロードするとメモリがたりませんので、ページングしたりDataReaderで操作したりします)

どれを選ぶかは、メソッドに切り出しやすい(ロジックを分離しやすい)だとか、
テストしやすそうだとか、(チーム全員が)読みやすいとか、そういった基準でよろしいかと思います。

編集 履歴 (0)
  • 質問者がID変えて質問が放置されたようなので補足。上記サンプルではループ中にConnectionがあるので、気になる場合は外に出す。Selectしかしていないし外側にあったほうが良い。接続プロバイダによってはキャッシュされてる事もあるけどね。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。