C# 动态设置string.Format格式化长度实现DataGrid通用ASCII导出
问题描述
现有一段从DataGrid读取数据并导出为ASCII文件的代码,运行正常,代码如下:
FileInfo info = new FileInfo(@"C:\SqlExports\"); info.Directory.Create(); string fileName = condition + " " + date + ".txt"; FileStream stream = new FileStream(@"C:\SqlExports\" + fileName, FileMode.OpenOrCreate); StreamWriter sw = new StreamWriter(stream, Encoding.Default); for (int i = 0; i < Grid.Rows.Count; i++) { List<string> rowprint = new List<string>(); for (int f = 0; f < Grid.Columns.Count; f++) { if (Grid.Rows[i].Cells[f].Value != DBNull.Value) { rowprint.Add(Grid.Rows[i].Cells[f].Value.ToString()); } else { rowprint.Add(" "); } } sw.Write(string.Format("{0,-19}", rowprint[0]) + String.Format("{0,10}", rowprint[1]) + sw.NewLine, Encoding.Default); } sw.Close();
需要将该代码改造为可复用逻辑,适配DataGrid绑定不同数据源的导出需求,支持2列、3列及更多列的动态列数场景。
曾尝试如下写法实现字段长度加2个空格的格式化效果,但无法正常运行:
sw.Write(string.Format("0, -(rowprint[0].length + 2)", rowprint[0]) + string.Format("{"0,rowprint[1].Length + 2"} + sw.Newlinn, Encoding.Default);
需要找到正确的实现方式,在格式化时基于字段值对应长度增加2个空格完成对齐输出,适配动态列数场景。
错误原因
之前的写法无法运行有三个核心问题:
- 把变量计算逻辑直接写在字符串字面量内部,C#不会解析引号包裹的普通字符串中的变量取值,
"0, -(rowprint[0].length + 2)"是非法的string.Format格式串 - 格式串的大括号没有正确拼接,存在语法错误
- 逐单元格用当前内容长度+2作为占位宽度,会因为同一列不同行内容长度不一致,导致最终输出列错位
可复用实现方案
实现逻辑分三步:
- 预计算每一列的最大显示宽度:遍历所有行的单元格内容,取每列最长内容的长度加2个空格作为该列统一的对齐宽度,同时兼容列头长度,避免列头长于内容时错位
- 动态生成格式化模板:根据实际列数拼接占位符,不需要硬编码列索引和固定宽度,可适配任意列数
- 统一写入文件:用
using语句自动释放文件资源,自动跳过DataGrid自带的新增空行,支持自定义导出路径、文件名、编码
完整可复用代码如下:
/// <summary> /// 将DataGrid内容导出为对齐的ASCII文本文件 /// </summary> /// <param name="grid">要导出的DataGrid控件</param> /// <param name="saveDir">导出文件保存目录</param> /// <param name="fileName">导出文件名</param> /// <param name="encoding">文件编码,默认使用系统默认编码</param> public void ExportDataGridToAscii(DataGridView grid, string saveDir, string fileName, Encoding encoding = null) { encoding ??= Encoding.Default; // 自动创建不存在的目录 Directory.CreateDirectory(saveDir); string fullSavePath = Path.Combine(saveDir, fileName); int colCount = grid.Columns.Count; int[] colWidths = new int[colCount]; // 初始化列宽为列头长度+2个空格 for (int i = 0; i < colCount; i++) { colWidths[i] = (grid.Columns[i].HeaderText?.Length ?? 0) + 2; } // 遍历所有行,计算每列的最大内容宽度+2个空格 foreach (DataGridViewRow row in grid.Rows) { // 跳过DataGrid的新增占位空行 if (row.IsNewRow) continue; for (int i = 0; i < colCount; i++) { string cellVal = row.Cells[i].Value == DBNull.Value ? " " : row.Cells[i].Value.ToString(); int currentWidth = cellVal.Length + 2; if (currentWidth > colWidths[i]) { colWidths[i] = currentWidth; } } } // 动态拼接行格式化模板:保持原逻辑第一列左对齐,其余列右对齐 List<string> formatSegments = new List<string>(); for (int i = 0; i < colCount; i++) { // 负宽度代表左对齐,正宽度代表右对齐,需要全列左对齐就统一加负号 string alignFlag = i == 0 ? "-" : ""; formatSegments.Add($"{{{i},{alignFlag}{colWidths[i]}}}"); } string lineFormat = string.Concat(formatSegments) + Environment.NewLine; // 写入文件 using (FileStream fs = new FileStream(fullSavePath, FileMode.OpenOrCreate, FileAccess.Write)) using (StreamWriter sw = new StreamWriter(fs, encoding)) { // 写入列头(不需要可以注释掉这部分) List<string> headerVals = new List<string>(); for (int i = 0; i < colCount; i++) { headerVals.Add(grid.Columns[i].HeaderText ?? string.Empty); } sw.Write(lineFormat, headerVals.ToArray()); // 逐行写入数据 foreach (DataGridViewRow row in grid.Rows) { if (row.IsNewRow) continue; List<string> rowVals = new List<string>(); for (int i = 0; i < colCount; i++) { string val = row.Cells[i].Value == DBNull.Value ? " " : row.Cells[i].Value.ToString(); rowVals.Add(val); } sw.Write(lineFormat, rowVals.ToArray()); } } }
调用示例:
// 调用时只需要传入对应参数即可,不管DataGrid绑定的数据源是2列还是更多列都能自动适配 ExportDataGridToAscii(Grid, @"C:\SqlExports\", $"{condition} {date}.txt");
如果需要所有列都左对齐,只需要把生成alignFlag的判断去掉,统一赋值为"-"即可。
内容的提问来源于stack exchange,提问作者John Karagiannis
相关产品推荐
相关产品推荐

