CSV形式の規則は、「CSV形式のファイルをDataTableや配列等として取得する」で紹介したものと同じとして、話を進めます。つまり、4,6の規則に従い、フィールドにカンマ、改行文字が含まれる場合は、ダブルクォートで囲みます。また5の規則に従い、フィールドにダブルクォートが含まれる場合は、これを2つのダブルクォートに置換して、ダブルクォートで囲みます。さらに規則7に従い、フィールドの前後にスペースがある場合も、ダブルクォートで囲みます。
このような方針により、DataTableをCSV形式のファイルに保存する例(ConvertDataTableToCsvメソッド)を以下に示します。フィールドの型を考慮せず、単純にToStringメソッドで文字列にして保存しています。ヘッダも書き込んでいますが、ヘッダの書き込みと、レコードの書き込みが全く同じコードになっており、コードとしてはあまり良くありません。あくまでサンプルということで、ご了承ください。
またこの例では、いちいち一つ一つのフィールドを調べてダブルクォートで囲むか調べていますが、これが面倒であれば、すべてのフィールドをダブルクォートで囲むようにしても結構です。
''' <summary> ''' DataTableの内容をCSVファイルに保存する ''' </summary> ''' <param name="dt">CSVに変換するDataTable</param> ''' <param name="csvPath">保存先のCSVファイルのパス</param> ''' <param name="writeHeader">ヘッダを書き込む時はtrue。</param> Public Sub ConvertDataTableToCsv( _ dt As DataTable, csvPath As String, writeHeader As Boolean) '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 = dt.Columns.Count Dim lastColIndex As Integer = colCount - 1 Dim i As Integer 'ヘッダを書き込む If writeHeader Then For i = 0 To colCount - 1 'ヘッダの取得 Dim field As String = dt.Columns(i).Caption '"で囲む field = EncloseDoubleQuotesIfNeed(field) 'フィールドを書き込む sr.Write(field) 'カンマを書き込む If lastColIndex > i Then sr.Write(","c) End If Next '改行する sr.Write(vbCrLf) End If 'レコードを書き込む Dim row As DataRow For Each row In dt.Rows For i = 0 To colCount - 1 'フィールドの取得 Dim field As String = row(i).ToString() '"で囲む field = EncloseDoubleQuotesIfNeed(field) 'フィールドを書き込む sr.Write(field) 'カンマを書き込む If lastColIndex > i Then sr.Write(","c) End If Next '改行する sr.Write(vbCrLf) Next '閉じる sr.Close() End Sub ''' <summary> ''' 必要ならば、文字列をダブルクォートで囲む ''' </summary> Private Function EncloseDoubleQuotesIfNeed(field As String) As String If NeedEncloseDoubleQuotes(field) Then Return EncloseDoubleQuotes(field) End If Return field End Function ''' <summary> ''' 文字列をダブルクォートで囲む ''' </summary> Private Function EncloseDoubleQuotes(field As String) As String If field.IndexOf(""""c) > -1 Then '"を""とする field = field.Replace("""", """""") End If Return """" & field & """" End Function ''' <summary> ''' 文字列をダブルクォートで囲む必要があるか調べる ''' </summary> Private Function NeedEncloseDoubleQuotes(field As String) As Boolean Return field.IndexOf(""""c) > -1 OrElse _ field.IndexOf(","c) > -1 OrElse _ field.IndexOf(ControlChars.Cr) > -1 OrElse _ field.IndexOf(ControlChars.Lf) > -1 OrElse _ field.StartsWith(" ") OrElse _ field.StartsWith(vbTab) OrElse _ field.EndsWith(" ") OrElse _ field.EndsWith(vbTab) End Function
/// <summary> /// DataTableの内容をCSVファイルに保存する /// </summary> /// <param name="dt">CSVに変換するDataTable</param> /// <param name="csvPath">保存先のCSVファイルのパス</param> /// <param name="writeHeader">ヘッダを書き込む時はtrue。</param> public void ConvertDataTableToCsv( DataTable dt, string csvPath, bool writeHeader) { //CSVファイルに書き込むときに使うEncoding System.Text.Encoding enc = System.Text.Encoding.GetEncoding("Shift_JIS"); //書き込むファイルを開く System.IO.StreamWriter sr = new System.IO.StreamWriter(csvPath, false, enc); int colCount = dt.Columns.Count; int lastColIndex = colCount - 1; //ヘッダを書き込む if (writeHeader) { for (int i = 0; i < colCount; i++) { //ヘッダの取得 string field = dt.Columns[i].Caption; //"で囲む field = EncloseDoubleQuotesIfNeed(field); //フィールドを書き込む sr.Write(field); //カンマを書き込む if (lastColIndex > i) { sr.Write(','); } } //改行する sr.Write("\r\n"); } //レコードを書き込む foreach (DataRow row in dt.Rows) { for (int i = 0; i < colCount; i++) { //フィールドの取得 string field = row[i].ToString(); //"で囲む field = EncloseDoubleQuotesIfNeed(field); //フィールドを書き込む sr.Write(field); //カンマを書き込む if (lastColIndex > i) { sr.Write(','); } } //改行する sr.Write("\r\n"); } //閉じる sr.Close(); } /// <summary> /// 必要ならば、文字列をダブルクォートで囲む /// </summary> private string EncloseDoubleQuotesIfNeed(string field) { if (NeedEncloseDoubleQuotes(field)) { return EncloseDoubleQuotes(field); } return field; } /// <summary> /// 文字列をダブルクォートで囲む /// </summary> private string EncloseDoubleQuotes(string field) { if (field.IndexOf('"') > -1) { //"を""とする field = field.Replace("\"", "\"\""); } return "\"" + field + "\""; } /// <summary> /// 文字列をダブルクォートで囲む必要があるか調べる /// </summary> private bool NeedEncloseDoubleQuotes(string field) { return field.IndexOf('"') > -1 || field.IndexOf(',') > -1 || field.IndexOf('\r') > -1 || field.IndexOf('\n') > -1 || field.StartsWith(" ") || field.StartsWith("\t") || field.EndsWith(" ") || field.EndsWith("\t"); }
このような方法以外に、XSLTを使ってCSVに変換する方法もあります。この方法については、掲示板の過去ログの「DatasetのデータをCSV保存する」や、次のリンク先をご覧ください。
私個人の意見としましては、このような方法ではCSVの規則に従うファイルを出力するのが難しく、柔軟性にも乏しいため、お勧めはできません。
(この記事は、「.NETプログラミング研究」で紹介したものを基にしています。)