如何使用WriteAllText将DataTable列名写入CSV文件表头?
解决DataTable写入CSV时添加表头的问题
嘿,我来帮你搞定这个CSV表头的问题!你的代码现在有几个小问题导致表头没正确生成,我一步步给你梳理并修正:
首先,你当前代码里的sb.AppendLine(string.Join(",", columnNames));其实是把分组后的匿名对象直接拼接了,这根本不是DataTable的列名;而且你把StringBuilder放在了内层循环里,每次循环都会新建一个,最后每个CSV文件只会保留最后一行数据;还有文件名里的row直接转字符串会输出类似<>f__AnonymousType0的内容,不是你想要的RE名称。
下面是修正后的完整代码,我加了注释说明关键改动:
private void GenerateRETest() { DataTable rI = new DataTable(); rI.Columns.Add("sID", typeof(int)); rI.Columns.Add("sn", typeof(string)); rI.Columns.Add("RE", typeof(string)); rI.Rows.Add(25, "Apex 1", "RE 1"); rI.Rows.Add(50, "Apex 2", "RE 1"); rI.Rows.Add(10, "Apex 3", "RE 1"); rI.Rows.Add(21, "Apex 4", "RE 1"); rI.Rows.Add(251, "Apex 11", "RE 11"); rI.Rows.Add(501, "Apex 21", "RE 11"); rI.Rows.Add(101, "Apex 31", "RE 11"); rI.Rows.Add(211, "Apex 41", "RE 11"); rI.Rows.Add(215, "Apex 12", "RE 12"); rI.Rows.Add(510, "Apex 22", "RE 12"); rI.Rows.Add(110, "Apex 32", "RE 12"); rI.Rows.Add(211, "Apex 42", "RE 12"); // 按RE分组,修正原代码里的变量名错误(dt改成rI) var groupedData = rI.AsEnumerable() .GroupBy(row => row.Field<string>("RE")) .Select(group => new { RE = group.Key, Rows = group.OrderBy(row => row.Field<string>("sn")).ToList() }) .OrderBy(x => x.RE) .ToList(); // 获取DataTable的列名,处理引号转义,和数据字段保持一致格式 var headerFields = rI.Columns.Cast<DataColumn>() .Select(col => $"\"{col.ColumnName.Replace("\"", "\"\"")}\""); string headerLine = string.Join(",", headerFields); foreach (var group in groupedData) { // 把StringBuilder放在分组循环外面,收集该分组的所有行 StringBuilder sb = new StringBuilder(); // 先写入表头 sb.AppendLine(headerLine); foreach (var dataRow in group.Rows) { // 处理数据字段,转义引号并包裹双引号 IEnumerable<string> dataFields = dataRow.ItemArray .Select(field => $"\"{field.ToString().Replace("\"", "\"\"")}\""); sb.AppendLine(string.Join(",", dataFields)); } // 用分组的RE值作为文件名的一部分,避免无效文件名 string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); string fileName = Path.Combine(desktopPath, $"{group.RE}_display.csv"); // 写入整个分组的内容到CSV File.WriteAllText(fileName, sb.ToString()); } }
关键改动点说明:
- 修正了原代码里的变量名错误(
dt改成rI) - 提前生成表头行,用
DataColumn.ColumnName获取真正的列名,同时处理引号转义 - 将
StringBuilder移到分组循环外层,确保每个CSV文件包含表头+所有对应行 - 文件名使用
group.RE来命名,避免生成奇怪的类名格式文件名 - 统一表头和数据字段的格式(都用双引号包裹,转义内部的双引号)
这样每个生成的CSV文件都会以sID,sn,RE作为第一行表头,后面跟着对应分组的数据行啦!
内容的提问来源于stack exchange,提问作者JamesL




