普通にやるなら、RowのItemを結合して作ると思いますが、それでは面白くない。
DataTable の Column 情報から出力フォーマットを先に作っておいて、Row の ItemArray を配列にしたもので行データを一気に作るという案でやってみました。結構スッキリかけたと思います。
/// <summary>
/// データテーブルからCSVファイル出力
/// </summary>
/// <param name="table">データテーブル</param>
/// <param name="filePath">出力ファイルパス</param>
public void DataTableToCsv(DataTable table, string filePath)
{
var columns = table.Columns;
var formatList = new List<string>();
for (int i = 0; i < columns.Count; i++)
{
// columns[i].DataType で出力対象外の型があれば、formatList.Add("");
formatList.Add("{" + i + "}");
}
var rowFormat = string.Join(",", formatList.ToArray());
using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
// ヘッダ出力する場合は下記をコメントアウト
//var columnNames = string.Join(",", columns.Cast<DataColumn>().Select(column => column.ColumnName).ToArray());
//writer.WriteLine(columnNames);
//writer.Flush();
foreach (DataRow row in table.Rows)
{
var array = row.ItemArray.Select(item => itemConverter(item, "yyyy-MM-dd HH:mm:ss")).ToArray();
writer.WriteLine(string.Format(rowFormat, array));
writer.Flush();
}
}
}
/// <summary>
/// 値変換
/// </summary>
/// <remarks>
/// 型に応じて出力内容を変換する
/// </remarks>
/// <param name="item">値</param>
/// <param name="dateTimeFormat">日時フォーマット</param>
/// <returns>変換後の値</returns>
private static object itemConverter(object item, string dateTimeFormat)
{
var result = item;
if (item is byte[])
{
result = BitConverter.ToString((byte[])item).Replace("-", "");
}
else if (item is string)
{
result = "\"" + item + "\"";
}
else if (item is DateTime)
{
result = "\"" + ((DateTime)item).ToString(dateTimeFormat) + "\"";
}
return result;
}
0 件のコメント:
コメントを投稿