投稿者 魔界の仮面弁士  (社会人) 投稿日時 2012/11/26 22:07:34
> いろいろな書き方があるとは思いますが、Linq を使った例をひとつ。

今度は、Linq を使わずに、ループで処理する手法で書いてみました。

『CSVをStreamReaderで読み込んで配列データとして行いたいと思ってます。』
という要望に逆らって、あえて今回は System.IO.StreamReader ではなく、
Microsoft.VisualBasic.FileIO.TextFieldParser で読み込ませています。

Imports System.IO
Imports System.Text
Imports Microsoft.VisualBasic.FileIO

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim srcFile As String = "C:\temp\1.csv"
        Dim dstFile As String = "C:\temp\2.csv"
        Dim sjis As Encoding = Encoding.GetEncoding("Shift_JIS")

        Dim tbl As New DataTable() With {.PrimaryKey = {.Columns.Add("名前")}}
        Dim cols = tbl.Columns
        Dim rows = tbl.Rows

        'csv を読み込んで DataTable を作成。 
        Using reader As New TextFieldParser(srcFile, sjis)
            reader.SetDelimiters(",")
            Do Until reader.EndOfData
                Dim fields() As String = reader.ReadFields()
                If fields.Length <> 3 Then
                    Continue Do
                End If
                Dim row = If(rows.Find(fields(0)), rows.Add(fields(0)))
                If Not cols.Contains(fields(1)) Then
                    cols.Add(New DataColumn() With { _
                        .ColumnName = fields(1), _
                        .DataType = GetType(Integer), _
                        .AllowDBNull = False, _
                        .DefaultValue = 0 _
                    })
                End If
                row.SetField(fields(1), CInt(fields(2)))
            Loop
        End Using

        '確認用。今回の変換処理とは無関係。 
        DataGridView1.ReadOnly = True
        DataGridView1.DataSource = tbl

        '読み取った DataTable を csv 保存。 
        Using writer As New StreamWriter(dstFile, False, sjis)
            'ヘッダー部 
            For c As Integer = 0 To cols.Count - 2
                writer.Write(cols(c).ColumnName)
                writer.Write(","c)
            Next
            writer.Write(cols(cols.Count - 1).ColumnName)

            'データ本体部 
            For Each row As DataRow In rows
                For Each col As DataColumn In cols
                    If col.ColumnName = "名前" Then
                        writer.WriteLine()
                        writer.Write(row(col))
                        Continue For
                    End If
                    writer.Write(","c)
                    writer.Write(row(col))
                Next
            Next
            writer.Close()
        End Using
    End Sub
End Class



なお、先に書いたサンプルで出力される csv ファイルのフォーマットは
「レコード末尾に CrLf を付与」という仕様でしたが、今回のサンプルでは
「レコード間が CrLf で区切られる」という仕様に変更してみました。

(出力した csv ファイルの最後に改行があるか無いかの違いです)