はじめに
ASP.NET CoreのMVCのアプリケーションでCSV出力機能を実装する機会があったため、メモとして使用したものを残しておきたいと思います。
CsvHelper
CSV出力で使用する専用のクラスとマッピングするためのクラスを用意。
CSV用クラス
public class StudentInfo
{
public long ID { get; set; }
public int Japanese { get; set; }
public int Mathematics { get; set; }
public int Science { get; set; }
public int SocialStudies { get; set; }
public int English { get; set; }
}
マッピング用クラス
public class StudentInfoMap : CsvHelper.Configuration.ClassMap<StudentInfo>
{
public StudentInfoMap()
{
Map(result => result.ID).Index(0);
Map(result => result.Japanese).Index(1);
Map(result => result.Mathematics).Index(2);
Map(result => result.Science).Index(3);
Map(result => result.SocialStudies).Index(4);
Map(result => result.English).Index(5);
}
}
ASP.NET MVC
View用Model
public class StudentSearchModel
{
public long ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public int Grade { get; set; }
public string Class { get; set; }
}
Controller
CSVを出力するためのAction(ExportCsv)を用意。
CsvHelperの仕様が一部変わった箇所がある模様。※ここの調査に時間がかかってしまった。。。
この時のCSVは普通のものとは少し違い、区切り線も出力する必要があった。
public IActionResult ExportCsv([FromForm] StudentSearchModel model)
{
//_repositoryはDB操作をするための自作クラスの変数
//GetStudentInfoでDBから情報を取得してくる ※情報取得部分は割愛
var results = _repository.GetStudentInfo(model).ToList());
var bytes_separate = Encoding.GetEncoding("Shift-JIS").GetBytes("-----成績一覧-----\r\n");
var bytes_results = GetCsvData<StudentInfo, StudentInfoMap>(results);
return File(
//byte配列をつなぐ
bytes_separate
.Concat(bytes_results)
.ToArray(),
"text/csv",
"sample.csv");
}
private static byte[] GetCsvData<T, TMap>(List<StudentInfo> list) where TMap : ClassMap
{
var ms = new MemoryStream();
var sw = new StreamWriter(ms, Encoding.GetEncoding("Shift-JIS"));
var cw = new CsvWriter(sw, CultureInfo.CurrentCulture);
//ここの仕様が変わった? 以前は "cw.Configuration.RegisterClassMap" のようにしていたと思う
cw.Context.RegisterClassMap<TMap>();
cw.WriteRecords(list);
sw.Flush();
return ms.ToArray();
}
おわりに
CsvHelperの仕様が変わったところでだいぶ時間がかかってしまいましたが、当時は何とか実装できたのでホッとしました。
今後もこのようなメモは残していきたいと思います。