能否根据条件修改DataGrid列数据类型?Excel数据导入场景
处理Excel Width列不规则值的DataTable适配方案
问题背景
Excel的Width列存在两种数据格式:
- 常规数值:
59cm、18.50cm,可移除单位后转为double类型 - 不规则字符串:
"H:15 ,T:5, W:8.5",包含多维度参数
当前DataTable中Width列被设为double类型,无法直接存入不规则字符串,且DataTable的列类型一旦创建(尤其是已添加行数据后)无法修改,即使未添加行,单列也只能固定一种数据类型,无法兼容两种格式,所以动态改列类型的思路不可行。
可行解决方案
方案1:将Width列设为object类型
直接兼容字符串和数值类型,修改DataTable初始化代码:
bomTable = new DataTable("BomTable"); bomTable.Columns.Add("Description", typeof(string)); bomTable.Columns.Add("Vendor", typeof(string)); bomTable.Columns.Add("PartName", typeof(string)); bomTable.Columns.Add("Weight", typeof(double)); bomTable.Columns.Add("WeightUnit", typeof(string)); bomTable.Columns.Add("Width", typeof(object)); // 改为object类型兼容两种数据 bomTable.Columns.Add("Width Unit", typeof(string));
注意:后续处理DataGridView数据或进行数值计算时,需要额外判断单元格值的类型,避免类型转换错误。
方案2:拆分多维度参数,新增对应列
针对H:xx,T:xx,W:xx这类字符串,拆分出Height、Thickness、Width三个数值列,保持数据结构的规范性:
- 修改DataTable结构:
bomTable = new DataTable("BomTable"); bomTable.Columns.Add("Description", typeof(string)); bomTable.Columns.Add("Vendor", typeof(string)); bomTable.Columns.Add("PartName", typeof(string)); bomTable.Columns.Add("Weight", typeof(double)); bomTable.Columns.Add("WeightUnit", typeof(string)); bomTable.Columns.Add("Width", typeof(double)); bomTable.Columns.Add("Height", typeof(double)); bomTable.Columns.Add("Thickness", typeof(double)); bomTable.Columns.Add("Width Unit", typeof(string));
- 处理单元格值的逻辑:
var cellValue = excelRange.Cells[fabricHeaderRow + 1, j].Value2.ToString().Trim(); if (cellValue.Contains("H") || cellValue.Contains("T") || cellValue.Contains("W")) { // 拆分字符串提取各维度数值 var parts = cellValue.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (var part in parts) { var keyValue = part.Split(':'); if (keyValue.Length != 2) continue; var key = keyValue[0].Trim(); if (double.TryParse(keyValue[1].Trim(), out double num)) { switch(key) { case "W": bomTable.Rows[rowIndex]["Width"] = num; break; case "H": bomTable.Rows[rowIndex]["Height"] = num; break; case "T": bomTable.Rows[rowIndex]["Thickness"] = num; break; } } } } else if (cellValue.EndsWith("cm")) { // 处理常规带单位的数值 if (double.TryParse(cellValue.Replace("cm", "").Trim(), out double widthNum)) { bomTable.Rows[rowIndex]["Width"] = widthNum; bomTable.Rows[rowIndex]["Width Unit"] = "cm"; } }
方案3:双列分离显示与计算需求
保留原始字符串用于显示,新增隐藏的数值列用于计算:
- 修改DataTable结构:
bomTable = new DataTable("BomTable"); bomTable.Columns.Add("Description", typeof(string)); bomTable.Columns.Add("Vendor", typeof(string)); bomTable.Columns.Add("PartName", typeof(string)); bomTable.Columns.Add("Weight", typeof(double)); bomTable.Columns.Add("WeightUnit", typeof(string)); bomTable.Columns.Add("Width", typeof(string)); // 显示原始值 bomTable.Columns.Add("WidthNumeric", typeof(double)); // 存储可计算的数值 bomTable.Columns.Add("Width Unit", typeof(string));
- 隐藏数值列(在DataGridView中):
dataGridView1.Columns["WidthNumeric"].Visible = false;
- 处理单元格值的逻辑:
var cellValue = excelRange.Cells[fabricHeaderRow + 1, j].Value2.ToString().Trim(); bomTable.Rows[rowIndex]["Width"] = cellValue; if (cellValue.Contains("H") || cellValue.Contains("T") || cellValue.Contains("W")) { // 提取W对应的数值存入计算列 var wPart = cellValue.Split(',').FirstOrDefault(p => p.Trim().StartsWith("W:")); if (wPart != null && double.TryParse(wPart.Split(':')[1].Trim(), out double wNum)) { bomTable.Rows[rowIndex]["WidthNumeric"] = wNum; } } else if (cellValue.EndsWith("cm")) { if (double.TryParse(cellValue.Replace("cm", "").Trim(), out double widthNum)) { bomTable.Rows[rowIndex]["WidthNumeric"] = widthNum; bomTable.Rows[rowIndex]["Width Unit"] = "cm"; } }
内容的提问来源于stack exchange,提问作者Riku_dola
相关产品推荐
相关产品推荐

