Skip to content

Instantly share code, notes, and snippets.

@ryz310
Last active July 19, 2019 08:16
Show Gist options
  • Save ryz310/5300171 to your computer and use it in GitHub Desktop.
Save ryz310/5300171 to your computer and use it in GitHub Desktop.
DataTableの内容をcsvファイルに書き出す拡張メソッドです。 なんか仕事でやたらcsvファイル作るプログラム書く事が多かったので。 拡張メソッドってクラス変数しか持てないのがちょっと残念ですね。
using System;
using System.Data;
using System.IO;
using System.Text;
/// <summary>
/// DataTableクラスにCSV出力機能を追加する拡張メソッド
/// </summary>
public static class ExtensionDataTableToCsv
{
/// <summary>
/// 出力データが無かった場合のアクション
/// </summary>
public enum ActionNoData
{
/// <summary>ファイルを出力しない</summary>
NoOutput,
/// <summary>ゼロバイトのファイルを出力する</summary>
OutputZeroByteFile,
/// <summary>出力ファイルが無い旨を伝えるメッセージファイルを出力する</summary>
OutputMessageFile,
}
/// <summary>
/// 出力データが無かった場合のアクションを設定する。
/// default : ActionNoData.OutputMessageFile
/// </summary>
public static ActionNoData NoDataAction { get; set; }
/// <summary>
/// CSVに出力するデータが無かった場合にファイルに出力するメッセージ。
/// NoDataActionにActionNoData.OutputMessageFileを指定した場合に有効。
/// </summary>
public static string NoDataMessage { get; set; }
/// <summary>
/// CSVデータの区切りにダブルクオーテーションを含めるかどうか。
/// true (default) : "a","b","c"
/// false : a,b,c
/// </summary>
public static bool WithDoubleQuotes { get; set; }
/// <summary>
/// 静的コンストラクタ
/// </summary>
static ExtensionDataTableToCsv()
{
ExtensionDataTableToCsv.WithDoubleQuotes = true;
ExtensionDataTableToCsv.NoDataAction = ActionNoData.OutputMessageFile;
ExtensionDataTableToCsv.NoDataMessage = "出力データ無し";
}
/// <summary>
/// データテーブルの内容をCSVファイルに出力する
/// </summary>
/// <param name="self">DataTableインスタンス</param>
/// <param name="filePath">出力ファイルパス</param>
/// <param name="encoding">出力エンコーディング</param>
/// <param name="withColumnHeader">True: カラムヘッダを付与</param>
public static void ToCsv(this DataTable self, string filePath, Encoding encoding, bool withColumnHeader)
{
self.ToCsv(filePath, encoding, withColumnHeader, "");
}
/// <summary>
/// データテーブルの内容をCSVファイルに出力する
/// </summary>
/// <param name="self">DataTableインスタンス</param>
/// <param name="filePath">出力ファイルパス</param>
/// <param name="encoding">出力エンコーディング</param>
/// <param name="withColumnHeader">True: カラムヘッダを付与</param>
/// <param name="filter">データ抽出用where句</param>
public static void ToCsv(this DataTable self, string filePath, Encoding encoding, bool withColumnHeader, string filter)
{
if (self.Select(filter).Length > 0)
{
WriteCsvFile(filePath, encoding, sw =>
{
sw.Write(CreateCsvData(self, withColumnHeader, filter));
});
}
else
{
switch (ExtensionDataTableToCsv.NoDataAction)
{
case ActionNoData.NoOutput:
break;
case ActionNoData.OutputMessageFile:
WriteCsvFile(filePath, encoding, sw =>
{
sw.Write(FormatItem(ExtensionDataTableToCsv.NoDataMessage));
sw.WriteLine();
});
break;
case ActionNoData.OutputZeroByteFile:
WriteCsvFile(filePath, encoding, sw =>
{
return;
});
break;
default:
break;
}
}
}
/// <summary>
/// CSVファイル書き込み処理
/// </summary>
/// <param name="filePath">出力ファイルパス</param>
/// <param name="encoding">出力エンコーディング</param>
/// <param name="WriteMethod">書き込み内容デリゲート</param>
private static void WriteCsvFile(string filePath, Encoding encoding, Action<StreamWriter> WriteMethod)
{
using (var sw = new StreamWriter(filePath, false, encoding))
{
WriteMethod(sw);
}
}
/// <summary>
/// DataTableの状態からCSVデータを作成する
/// </summary>
/// <param name="table">出力対象</param>
/// <param name="withColumnHeader">True: カラムヘッダを付与</param>
/// <param name="filter">データ抽出用where句</param>
/// <returns>CSVデータ</returns>
private static string CreateCsvData(DataTable table, bool withColumnHeader, string filter)
{
var sb = new StringBuilder();
if (withColumnHeader)
{
PutCsvRow(table, sb, i => table.Columns[i].ToString());
}
foreach (DataRow row in table.Select(filter))
{
PutCsvRow(table, sb, i => row[i].ToString());
}
return sb.ToString();
}
/// <summary>
/// CSV1行分のデータを出力する
/// </summary>
/// <param name="table">出力対象</param>
/// <param name="sb">出力先</param>
/// <param name="CsvItem">データの出力方法</param>
private static void PutCsvRow(DataTable table, StringBuilder sb, Func<int, string> CsvItem)
{
for (int i = 0; i < table.Columns.Count; ++i)
{
if (i > 0) { sb.Append(","); }
sb.Append(FormatItem(CsvItem(i)));
}
sb.AppendLine();
}
/// <summary>
/// csvデータのフォーマットを行う。
/// CsvWithDoubleQuotesがTrueの場合はダブルクオーテーションを付与。
/// また、スペースが含まれる場合はトリムする。
/// </summary>
/// <param name="item">csvデータ</param>
/// <returns>整形済みcsvデータ</returns>
private static string FormatItem(string item)
{
if (ExtensionDataTableToCsv.WithDoubleQuotes)
{
return string.Format("\"{0}\"", item.Trim());
}
else
{
return item.Trim();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment