ここでは、CSVをDataTableに読み込んで、DataGridViewに表示しています。
ちょっと難しいところもあるかもしれないのでコメントを多めに入れています。
ポイントはCSVファイルを読み込むためにTextFieldParserクラスを使用しているところです。
これでCSVの中のフォーマットチェックをすることなく読み込めます。
DataTableのデータをCSVファイルに保存するのは、DataTableをCSVにして保存で紹介しているSaveToCSVメソッドを呼び出していますので、
このフォームのクラスなりにこのメソッドを追加して使用してください。
Visual Studio 2010版はこちらを参考にしてみてください。
(注)TextFieldParserクラスは何も書かれてない行があるとそこは飛ばして結果に表示されない動きをします。
多くの方はこれは好ましくない動作であると捉えているようですが私は悪い動作だとは思いません。
例えば最後のデータがある行でそれと同じ行にEOFがない場合、つまり最後の行がEOFだけの行があった場合、現在の動作であれば空のデータが表示されないので良い動作だと思います。
もし空行を飛ばさない場合はこの場合においては空のデータが最後に表示されてしまいます。
空のデータが必要ならば、きちんとそのCSVのフォーマットに沿った空データを挿入するのが良いと思います。
C#の例
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
//プロジェクトの参照設定でMicrosoft.VisualBasicを設定してください。
using Microsoft.VisualBasic.FileIO;
//dt:データを入れるDataTable
//hasHeader:CSVの一行目がカラム名かどうか
//fileName:ファイル名
//separator:カラムを分けている文字(,など)
//quote:カラムを囲んでいる文字("など)
private void ReadCSV(DataTable dt, bool hasHeader, string fileName,string separator, bool quote)
{
//CSVを便利に読み込んでくれるTextFieldParserを使います。
TextFieldParser parser = new TextFieldParser(fileName, Encoding.GetEncoding("shift_jis"));
//これは可変長のフィールドでフィールドの区切りのマーカーが使われている場合です。
//フィールドが固定長の場合は
//parser.TextFieldType = FieldType.FixedWidth;
parser.TextFieldType = FieldType.Delimited;
//区切り文字を設定します。
parser.SetDelimiters(separator);
//クォーテーションがあるかどうか。
//但しダブルクォーテーションにしか対応していません。シングルクォーテーションは認識しません。
parser.HasFieldsEnclosedInQuotes = quote;
string[] data;
//ここのif文では、DataTableに必要なカラムを追加するために最初に1行だけ読み込んでいます。
//データがあるか確認します。
if (!parser.EndOfData)
{
//CSVファイルから1行読み取ります。
data = parser.ReadFields();
//カラムの数を取得します。
int cols = data.Length;
if (hasHeader)
{
for (int i = 0; i < cols; i++)
{
dt.Columns.Add(new DataColumn(data[i]));
}
}
else
{
for (int i = 0; i < cols; i++)
{
//カラム名にダミーを設定します。
dt.Columns.Add(new DataColumn());
}
//DataTableに追加するための新規行を取得します。
DataRow row = dt.NewRow();
for (int i = 0; i < cols; i++)
{
//カラムの数だけデータをうつします。
row[i] = data[i];
}
//DataTableに追加します。
dt.Rows.Add(row);
}
}
//ここのループがCSVを読み込むメインの処理です。
//内容は先ほどとほとんど一緒です。
while (!parser.EndOfData)
{
data = parser.ReadFields();
DataRow row = dt.NewRow();
for (int i = 0; i < dt.Columns.Count; i++)
{
row[i] = data[i];
}
dt.Rows.Add(row);
}
//ファイルを閉じる
parser.Close();
}
private void btnOpen_Click(object sender, EventArgs e)
{
bool quote = false;
string separator = "";
switch (this.cmbQuote.SelectedIndex)
{
case 0:
case 1:
//クォーテーションあり
quote = true;
break;
case 2:
//クォーテーションなし
quote = false;
break;
}
switch (this.cmbSeparator.SelectedIndex)
{
case 0:
//カンマ区切り
separator = ",";
break;
case 1:
//タブ区切り
separator = "\t";
break;
case 2:
//スペース区切り
separator = " ";
break;
}
if (this.openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.dt.Columns.Clear();
this.dt.Clear();
ReadCSV(this.dt, this.ckOutputColumnName.Checked, this.openFileDialog1.FileName, separator, quote);
this.dataGridView1.DataSource = this.dt;
}
}
VB.NETの例
'プロジェクトの参照設定でMicrosoft.VisualBasicを設定してください。
Imports Microsoft.VisualBasic.FileIO
'dt:データを入れるDataTable
'hasHeader:CSVの一行目がカラム名かどうか
'fileName:ファイル名
'separator:カラムを分けている文字(,など)
'quote:カラムを囲んでいる文字("など)
Private Sub ReadCSV(ByVal dt As DataTable, ByVal hasHeader As Boolean, ByVal fileName As String, ByVal separator As String, ByVal quote As Boolean)
'CSVを便利に読み込んでくれるTextFieldParserを使います。
Dim parser As TextFieldParser = New TextFieldParser(fileName, Encoding.GetEncoding("shift_jis"))
'これは可変長のフィールドでフィールドの区切りのマーカーが使われている場合です。
'フィールドが固定長の場合は
'parser.TextFieldType = FieldType.FixedWidth;
parser.TextFieldType = FieldType.Delimited
'区切り文字を設定します。
parser.SetDelimiters(separator)
'クォーテーションがあるかどうか。
'但しダブルクォーテーションにしか対応していません。シングルクォーテーションは認識しません。
parser.HasFieldsEnclosedInQuotes = quote
Dim data() As String
'ここのif文では、DataTableに必要なカラムを追加するために最初に1行だけ読み込んでいます。
'データがあるか確認します。
If Not parser.EndOfData Then
'CSVファイルから1行読み取ります。
data = parser.ReadFields()
'カラムの数を取得します。
Dim cols As Integer = data.Length
If hasHeader Then
For i As Integer = 0 To cols - 1 Step 1
dt.Columns.Add(New DataColumn(data(i)))
Next i
Else
For i As Integer = 0 To cols - 1 Step 1
'カラム名にダミーを設定します。
dt.Columns.Add(New DataColumn())
Next i
'DataTableに追加するための新規行を取得します。
Dim row As DataRow = dt.NewRow()
For i As Integer = 0 To cols - 1 Step 1
'カラムの数だけデータをうつします。
row(i) = data(i)
Next i
'DataTableに追加します。
dt.Rows.Add(row)
End If
End If
'ここのループがCSVを読み込むメインの処理です。
'内容は先ほどとほとんど一緒です。
While Not parser.EndOfData
data = parser.ReadFields()
Dim row As DataRow = dt.NewRow()
For i As Integer = 0 To dt.Columns.Count - 1 Step 1
row(i) = data(i)
Next i
dt.Rows.Add(row)
End While
//ファイルを閉じる
parser.Close()
End Sub
Private Sub btnRead_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRead.Click
Dim quote As Boolean = False
Dim separator As String = ""
Select Me.cmbQuote.SelectedIndex
Case 0 To 1
'クォーテーションあり
quote = True
Case 2
'クォーテーションなし
quote = False
End Select
Select Me.cmbSeparator.SelectedIndex
Case 0
'カンマ区切り
separator = ","
Case 1
'タブ区切り
separator = "\t"
Case 2
'スペース区切り
separator = " "
End Select
If Me.openFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
Me.dt.Columns.Clear()
Me.dt.Clear()
ReadCSV(Me.dt, Me.ckOutputColumnName.Checked, Me.OpenFileDialog1.FileName, separator, quote)
Me.DataGridView1.DataSource = Me.dt
End If
End Sub
例えば以下のようなsample.csvファイルを使って読み込みと保存を試せます。
No,ひらがな,漢字 1,おはよう,お早う 2,こんにちは,今日は 3,こんばんは,今晩は
