DOBON.NET DOBON.NETプログラミング掲示板過去ログ

あるCSVの内容を読み取ったデータテーブルの構造を変更して、別のCSVを生成するには?

環境/言語:[WindowsXPProSP2 VB.NET2003]
分類:[.NET]

こんにちは。お世話になります。


Cドライブのマイドキュメントにあるファイル1(CSV)の内容を読み取り、その内容を変更して、マイドキュメントに、ファイル2(CSV)を作りたいと思います。


ファイル1(CSV)の内容は、以下の通りです。


名前1 名前2 住所1      住所2
山森  海川  東京都東京区   東京111


作りたいファイル2(CSV)の内容は、以下の通りです。


名前    住所
山森海川  東京都東京区東京111


まず、ファイル1(CSV)を読み込みます。


(ファイル1読み込みボタン)
Private Sub cmdCSVRead_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCSVRead.Click

Dim csvDir As String = "C:\マイドキュメント"
'CSVファイルの名前
Dim csvFileName As String = "ファイル1.csv"
'接続文字列
Dim conString As String = _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
+ csvDir + ";Extended Properties=""text;HDR=YES;FMT=Delimited"""
Dim con As New System.Data.OleDb.OleDbConnection(conString)
Dim commText As String = "SELECT * FROM [" + csvFileName + "]"
Dim da As New System.Data.OleDb.OleDbDataAdapter(commText, con)
'DataTableに格納する
Dim dt As New DataTable
da.Fill(dt)


これで、dtに、ファイル1の内容が代入されました。
このdtの内容の読み込みや更新だけであれば、DataRowを使って、
出来ると思うのですが、
ファイル2(CSV)を作る際には、
上記のような、新たなテーブル形式(dt2)を作り、使いたいと思います。


dtの内容を、ファイル2形式のデータテーブル(dt2)に加工するためには、
どのような処理を行えばよいのかが、分かりません。


dt2が加工出来たら、これを、パブリック変数(pbdt)に代入し、
下記の、ファイル生成ボタンのクリック時コードで使用します。


Public pbdt As DataTable
pbdt = dt2


(ファイル2生成ボタン)
Private Sub cmdCSVWrite_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCSVWrite.Click

'保存先のCSVファイルのパス
Dim csvPath As String = "C:\マイドキュメント\ファイル2.csv"
'CSVファイルに書き込むときに使うEncoding
Dim enc As System.Text.Encoding = _
System.Text.Encoding.GetEncoding("Shift_JIS")

'開く
Dim sr As New System.IO.StreamWriter(csvPath, False, enc)
Dim colCount As Integer = pbdt.Columns.Count
Dim lastColIndex As Integer = colCount - 1

'ヘッダを書き込む
Dim i As Integer
For i = 0 To colCount - 1
'ヘッダの取得
Dim field As String = pbdt.Columns(i).Caption
'"で囲む必要があるか調べる
If field.IndexOf(ControlChars.Quote) > -1 OrElse _
field.IndexOf(","c) > -1 OrElse _
field.IndexOf(ControlChars.Cr) > -1 OrElse _
field.IndexOf(ControlChars.Lf) > -1 OrElse _
field.StartsWith(" ") OrElse _
field.StartsWith(ControlChars.Tab) OrElse _
field.EndsWith(" ") OrElse _
field.EndsWith(ControlChars.Tab) Then
If field.IndexOf(ControlChars.Quote) > -1 Then
'"を""とする
field = field.Replace("""", """""")
End If
field = """" + field + """"
End If
'フィールドを書き込む
sr.Write(field)
'カンマを書き込む
If lastColIndex > i Then
sr.Write(","c)
End If
Next i
'改行する
sr.Write(ControlChars.Cr + ControlChars.Lf)

'レコードを書き込む
Dim row As DataRow
For Each row In pbdt.Rows
For i = 0 To colCount - 1
'フィールドの取得
Dim field As String = row(i).ToString()
'"で囲む必要があるか調べる
If field.IndexOf(ControlChars.Quote) > -1 OrElse _
field.IndexOf(","c) > -1 OrElse _
field.IndexOf(ControlChars.Cr) > -1 OrElse _
field.IndexOf(ControlChars.Lf) > -1 OrElse _
field.StartsWith(" ") OrElse _
field.StartsWith(ControlChars.Tab) OrElse _
field.EndsWith(" ") OrElse _
field.EndsWith(ControlChars.Tab) Then
If field.IndexOf(ControlChars.Quote) > -1 Then
'"を""とする
field = field.Replace("""", """""")
End If
field = """" + field + """"
End If
'フィールドを書き込む
sr.Write(field)
'カンマを書き込む
If lastColIndex > i Then
sr.Write(","c)
End If
Next i
'改行する
sr.Write(ControlChars.Cr + ControlChars.Lf)
Next row

'閉じる
sr.Close()

End Sub


このコードにより、ファイル2(CSV)がCドライブのマイドキュメントに生成されます。


dt2の作成の部分につきまして、お分かりになられる方がいらっしゃいましたら、誠にお手数と存じますが、
ご教示くださいませ。


どうぞよろしくお願い申し上げます。
■No30223に返信(けいすけさんの記事)
> dtの内容を、ファイル2形式のデータテーブル(dt2)に加工するためには、
> どのような処理を行えばよいのかが、分かりません。

> dt2の作成の部分につきまして、お分かりになられる方がいらっしゃいましたら、誠にお手数と存じますが、
> ご教示くださいませ。

dt2 とは System.Data.DataTable の中身が装填されたインスタンスという理解でよろしいですか?
であれば、けっこう単純に以下のとおりになると思います。

(1) DataTable新しいインスタンスを生成
(2) Column を Add (今回だと「名前」と「住所」)
(3) dt1 から DataRow (1 行) を取り出し
(4) 取り出した DataRow から dt2 追加用に加工 (今回だと文字列を結合するだけ)
(5) dt2 の NewRow メソッドから新しい DataRow のインスタンスを生成
(6) 新しく生成した DataRow に (4) で作成した文字列を詰め込む
(7) dt2 の Rows コレクションに Add
(8) 以後 (3) 〜 (7) を繰り返し

もしかしたら、もっと難しいことをお聞きになられているかもしれませんが、いかがでしょうか?

> dt2が加工出来たら、これを、パブリック変数(pbdt)に代入し、
> 下記の、ファイル生成ボタンのクリック時コードで使用します。

パブリック変数にする必要はないと思うので、蛇足ですけど設計を見直した方がよろしいかと思います。
■No30225に返信(じゃんぬねっとさんの記事)

じゃんぬねっと様


ありがとうございます^^。
頂きましたお答えを参考に、
修正、コードを作成してみます。


出来次第、ご報告させて頂きます^^。


> ■No30223に返信(けいすけさんの記事)
>>dtの内容を、ファイル2形式のデータテーブル(dt2)に加工するためには、
>>どのような処理を行えばよいのかが、分かりません。
>
>>dt2の作成の部分につきまして、お分かりになられる方がいらっしゃいましたら、誠にお手数と存じますが、
>>ご教示くださいませ。
>
> dt2 とは System.Data.DataTable の中身が装填されたインスタンスという理解でよろしいですか?
> であれば、けっこう単純に以下のとおりになると思います。
>
> (1) DataTable新しいインスタンスを生成
> (2) Column を Add (今回だと「名前」と「住所」)
> (3) dt1 から DataRow (1 行) を取り出し
> (4) 取り出した DataRow から dt2 追加用に加工 (今回だと文字列を結合するだけ)
> (5) dt2 の NewRow メソッドから新しい DataRow のインスタンスを生成
> (6) 新しく生成した DataRow に (4) で作成した文字列を詰め込む
> (7) dt2 の Rows コレクションに Add
> (8) 以後 (3) 〜 (7) を繰り返し
>
> もしかしたら、もっと難しいことをお聞きになられているかもしれませんが、いかがでしょうか?
>
>>dt2が加工出来たら、これを、パブリック変数(pbdt)に代入し、
>>下記の、ファイル生成ボタンのクリック時コードで使用します。
>
> パブリック変数にする必要はないと思うので、蛇足ですけど設計を見直した方がよろしいかと思います。
■No30235に返信(けいすけさんの記事)


じゃんぬねっと様


>>(1) DataTable新しいインスタンスを生成
>>(2) Column を Add (今回だと「名前」と「住所」)
>>(3) dt1 から DataRow (1 行) を取り出し
>>(4) 取り出した DataRow から dt2 追加用に加工 (今回だと文字列を結合するだけ)
>>(5) dt2 の NewRow メソッドから新しい DataRow のインスタンスを生成
>>(6) 新しく生成した DataRow に (4) で作成した文字列を詰め込む
>>(7) dt2 の Rows コレクションに Add
>>(8) 以後 (3) 〜 (7) を繰り返し。


これらの流れの部分のコードを書いてみました。


Dim dt2 As New DataTable
Dim dr1 As DataRow()
Dim dr2 As DataRow
Dim st1 As String
Dim st2 As String

dt2.Columns.Add("住所")

dr1 = dt.Select
st1 = dr1(0)("名前1") & dr1(0)("名前2")
st2 = dr1(0)("住所1") & dr1(0)("住所2")

dr2 = dt2.NewRow
dr2(0)("名前") = st1・・・A
dr2(0)("住所") = st2
dt2.Rows.Add(dr2)

このコードを実行しますと、Aの部分で、
'System.MissingMemberException' のハンドルされていない例外が microsoft.visualbasic.dll で発生しました。
追加情報 : 型 'DBNull' の既定メンバが見つかりません。


が出てしましまいました。
引き続き、デバッグしております。
■No30240に返信(けいすけさんの記事)
> このコードを実行しますと、Aの部分で、
> 'System.MissingMemberException' のハンドルされていない例外が microsoft.visualbasic.dll で発生しました。
> 追加情報 : 型 'DBNull' の既定メンバが見つかりません。

デバッグしていて例外情報まで参照されているのであれば自己解決できているかもしれませんが...
スタックトレースから実際のどの部分で起きているか確認しても良いですし、例外が起きている箇所を個別で式ウォッチで見ても良いでしょう。

> Dim dr2 As DataRow
> :
> dr2(0)("名前") = st1
> dr2(0)("住所") = st2

dr2 は dr1 と違って配列じゃあないですよね。
dr2(0)("名前") という書き方はできないのではないでしょうか。
dr2("名前") でないとビルドも通らないような気もしますが...

また dt2 は「住所」列しかない状態です。
その dt2 から NewRow メソッドで作り出された「行」のインスタンスには「名前」という列は存在しません。

以上の理由で「dr2(0)("名前")」という格納先は存在しないですよね。
■No30247に返信(じゃんぬねっとさんの記事)

じゃんぬねっとさん、ありがとうございます^^。
以下のコードで解決できました^^。
ありがとうございました^^。

Dim dt2 As New DataTable
Dim dr1 As DataRow()
Dim dr2 As DataRow
Dim st1 As String
Dim st2 As String
Dim i As Integer

dt2.Columns.Add("名前")
dt2.Columns.Add("住所")

dr1 = dt.Select

i=0

Do Until i = dr1.Length

st1 = dr1(i)("名前1") & dr1(i)("名前2")
st2 = dr1(i)("住所1") & dr1(i)("住所2")

dr2 = dt2.NewRow
dr2("名前") = st1
dr2("住所") = st2
dt2.Rows.Add(dr2)

i = i + 1

Loop
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板