using DevExpress.XtraEditors; using DevExpress.XtraGrid; using DevExpress.XtraGrid.Columns; using Lskj.Business; using Lskj.Business.Impl; using Lskj.Control; using Lskj.Control.Model; using Lskj.Core; using Lskj.Data; using Lskj.Model; using Lskj.PubModuleExport.Model; using Lskj.Util; using OfficeOpenXml; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; namespace Lskj.PubModuleExport { public partial class FrmMain : BaseForm { #region 私有变量 /// /// 主键 /// private string ParmaryKey; /// /// 左侧树数据 /// private DataRow LeftRowObj; /// /// 左侧树主键关联右侧数据字段 /// private string ParentUnionField; /// /// 左侧树配置字段 /// private string LeftField; #endregion #region 公有变量 /// /// 共有入口参数 /// public DynamicModuleDetailModel Model; /// /// 主表数据类 /// public ModuleModel SysModel; /// /// 自定义查询条件 /// public MyControl SearchObj { get; private set; } #endregion /// /// 构造方法 /// public FrmMain(DynamicModuleDetailModel model = null) { InitializeComponent(); this.Model = model != null ? model : null; } /// /// 窗体加载时 /// /// /// protected override void OnLoad(EventArgs e) { InitControl(); InitEvent(); } /// /// 初始化事件绑定 /// private void InitEvent() { this.splitMainContainer.SplitterPositionChanged += OnSplitMainContainerPositionChanged; this.splitRightContainer.SplitterPositionChanged += OnSplitMainContainerPositionChanged; } /// /// 设置分割条位置 /// private void InitlizeSpiltLocation() { try { string splitMainWidth = IniHelper.Read(string.Format("PubModuleExport_SplitMain_{0}", this.Model.ModuleCode));//通过Key获取Value值 if (!string.IsNullOrEmpty(splitMainWidth)) { this.splitMainContainer.SplitterPosition = Convert.ToInt32(splitMainWidth); } string splitRightWidth = IniHelper.Read(string.Format("PubModuleExport_SplitRight_{0}", this.Model.ModuleCode));//通过Key获取Value值 if (!string.IsNullOrEmpty(splitRightWidth)) { this.splitRightContainer.SplitterPosition = Convert.ToInt32(splitRightWidth); } } catch (Exception ex) { MessageUtil.Show(ex.Message); } } /// /// 初始化控件 /// private void InitControl() { WaitForm.ShowForm(); try { this.Model.Privilege = this.Model.Privilege.Equals("3") ? "1" : Model.ModuleId > 0 ? BaseImpl.GetUserPurviewsByMenuId(Model.ModuleId + "") + "" : BaseImpl.GetUserPurviewsByMenuCode(Model.ModuleCode) + "";// 权限(1.有操作权限.0.无权限.2.只读权限.3.右键配置权限全部开放) DataRow modelRow = MainImpl.GetSystemdllTab(this.Model.ModuleCode);//获取单个模块信息 if (modelRow == null) { MessageUtil.Show("模块编号[" + this.Model.ModuleCode + "],配置错误!\r\n该模块信息未找到!"); return; } this.ParmaryKey = BaseImpl.GetBasePrimaryKey(this.Model.ModuleCode);//获取主键 this.SysModel = new ModuleModel(modelRow);//系统模块实体对象 switch (this.SysModel.MenuType) { case 1: case 4://左侧为树节点 this.treeLeft.Visible = true; //this.ModuleGridObj.LeftTreeViewEx = this.treeLeft; this.InitlizeSpiltLocation();//设置分割条位置 this.treeLeft.TreeInhibitSort = this.SysModel.TreeInhibitSort; this.SetLeftTreeView();//设置左侧树数据 if (this.SysModel.IsHideTreeViewBoxs) { this.treeLeft.TreeView.CheckBoxes = false; } break; //case 2: //case 5: // 左侧为表格 // this.gridLeft.Visible = true; // this.treeLeft.Visible = false; // this.ModuleGridObj.LeftGridEx = this.gridLeft; // this.SetLeftGridView(); // if (this.SysModel.LeftGridIsCheck == 1 && !this.SysModel.IsTreeTable) // { // GridDragGrid.GridAddCheckBox(this.gridLeft.GridView); // } // break; case 3://左侧为空 default: this.splitMainContainer.PanelVisibility = SplitPanelVisibility.Panel2; break; } //构建右侧表格 DataTable _gridColumns = BaseModuleImpl.GetBaseGridColumns(this.SysModel.ModeCode); this.gcMain.SetReadOnlyColumns(_gridColumns); this.gridBottom.SetReadOnlyColumns(_gridColumns); //设置上方条件 this.pl_top.Controls.Clear(); DataTable queryTable = BaseModuleImpl.GetCustomQueryFields(this.SysModel.CondKey);//加载自定义配置字段 this.SearchObj = new MyControl(this.SysModel.MenuSql, this.gcMain, this.treeLeft); this.SearchObj.ParentUnionField = this.ParentUnionField; this.pl_top.Height = 0; this.pl_top.Height = this.SearchObj.InitSearchControl(queryTable, this.pl_top); //右侧表格双击 this.gcMain.GridView.DoubleClick += GcMain_DoubleClick; this.gridBottom.GridView.DoubleClick += GridBottom_DoubleClick; //下方按钮 this.btnExport.Click += BtnExport_Click; this.btnDelete.Click += BtnDelete_Click; this.InitlizeSpiltLocation();//设置分割条位置 } catch (Exception) { } WaitForm.HideForm(); } private void BtnDelete_Click(object sender, EventArgs e) { DataTable table = this.gridBottom.GridControl.DataSourceTable(); if (table == null) return; int[] rows = this.gridBottom.GridView.GetSelectedRows(); if (rows.Length < 1) { GridBottom_DoubleClick(null,null); return; } ArrayList localDeletes = new ArrayList(); foreach (int rowid in rows) { localDeletes.Add(rowid); } // 删除选中且未保存的数据 for (int i = localDeletes.Count - 1; i >= 0; i--) { this.gridBottom.GridView.DeleteRow((int)localDeletes[i]); } } /// /// 导出 /// /// /// private void BtnExport_Click(object sender, EventArgs e) { DataTable dataTable = this.gridBottom.GridControl.DataSource as DataTable; if (dataTable != null && dataTable.Rows.Count > 0) { if (!dataTable.Columns.Contains("DllFileName")) return; SaveFileDialog dialog = new SaveFileDialog(); dialog.Title = "导出"; String suffix = ".xlsx" ; dialog.FileName = this.SysModel.MenuText + DateTime.Now.ToString(SystemInfo.Instance.ExportFileDateFormat) + suffix; dialog.Filter = "Excel文件(*.xlsx)|*.xlsx|PDF文件|*.PDF|RTF文件|*.RTF|HTML文件|*.html"; DialogResult result = dialog.ShowDialog(); if (result == DialogResult.OK) { //清空临时文件 PubUtil.ClearFilesInDirectory(PubUtil.ExportFilePath); string fileExt = Path.GetExtension(dialog.FileName).ToLower(); int i = 1; List Paths = new List(); foreach (DataRow itemRow in dataTable.Rows) { string Path =PubUtil.ExportFilePath + i + ","; i++; if (string.IsNullOrWhiteSpace(itemRow["DllFileName"] + "") || string.IsNullOrWhiteSpace(itemRow["PurviewId"] + "")) continue; if ((itemRow["DllFileName"] + "").Equals("Lskj.PubBill.dll", StringComparison.OrdinalIgnoreCase)) { //单据 string moduleCode = itemRow["PurviewId"] + ""; DataRow modelRow = BillImpl.GetBillInfo(moduleCode);//获取单个模块信息 if (modelRow != null) { BillModel billModel = new BillModel(modelRow); //主表控件 DataTable controls = BaseModuleImpl.GetControlLocation(billModel.FormKey, moduleCode); GridControlEx gridControlExMain = new GridControlEx(); DataTable MasterData = BaseImpl.GetDataTableResult(billModel.MasterSql);//主表数据源 this.ReplaceAndRemoveUnmatchedColumns(MasterData, controls); gridControlExMain.GridControl.DataSource = MasterData; string sheetName = Path + billModel.TypeName + fileExt; Paths.Add(sheetName); gridControlExMain.GridControl.ExportGridToExcel(sheetName, gridControlExMain.GridView.OptionsView.AllowCellMerge); //主表明细 DataTable detailColumns = BillImpl.GetDetailColumns(moduleCode);//初始化单据明细列 GridControlEx controlEx = new GridControlEx(); controlEx.SetReadOnlyColumns(detailColumns); controlEx.GridControl.DataSource = BaseImpl.GetDataTableResult(billModel.DetailSql); string DataSheetName = Path + billModel.TypeName + "-明细" + fileExt; Paths.Add(DataSheetName); controlEx.GridControl.ExportGridToExcel(DataSheetName, controlEx.GridView.OptionsView.AllowCellMerge); } } else { //单表 string moduleCode = itemRow["PurviewId"] + ""; DataRow modelRow = MainImpl.GetSystemdllTab(moduleCode);//获取单个模块信息 if (modelRow != null) { ModuleModel module= new ModuleModel(modelRow);//系统模块实体对象 DataTable gridColumns = BaseModuleImpl.GetBaseGridColumns(moduleCode);//主表列 GridControlEx gridControlExMain = new GridControlEx(); gridControlExMain.SetReadOnlyColumns(gridColumns); gridControlExMain.GridControl.DataSource = BaseImpl.GetDataTableResult(module.MenuSql); string sheetName = Path + module.MenuText+ fileExt; Paths.Add(sheetName); gridControlExMain.GridControl.ExportGridToExcel(sheetName, gridControlExMain.GridView.OptionsView.AllowCellMerge);//GridCustomColumnStruct.BaseMainGridView + this.SysModel.FormKey List details = this.GetDetails(moduleCode);//明细 int j = 1; foreach (GridDetailModel item in details) { string number = "(" + j + ")"; j++; if (item.IsReadOnly&&!string.IsNullOrWhiteSpace(item.DetailSql)) { //明细为动态sql GridControlEx controlEx = new GridControlEx(); controlEx.GridControl.DataSource = BaseImpl.GetDataTableResult(item.DetailSql); string DataSheetName = Path + module.MenuText + "-" + item.DetailName+ number + fileExt; Paths.Add(DataSheetName); controlEx.GridControl.ExportGridToExcel(DataSheetName, controlEx.GridView.OptionsView.AllowCellMerge); } else { //明细为模块 if (string.IsNullOrWhiteSpace(item.UnionModule)) continue; DataRow detaModuleRow = MainImpl.GetSystemdllTab(item.UnionModule);//获取单个模块信息 if (detaModuleRow != null) { ModuleModel detaModule = new ModuleModel(detaModuleRow);//系统模块实体对象 GridControlEx controlEx = new GridControlEx(); DataTable detaGridColumns = BaseModuleImpl.GetBaseGridColumns(item.UnionModule);//主表列 controlEx.SetReadOnlyColumns(detaGridColumns); controlEx.GridControl.DataSource = BaseImpl.GetDataTableResult(detaModule.MenuSql); string DataSheetName = Path + module.MenuText + "-" + item.DetailName+ number + fileExt; Paths.Add(DataSheetName); controlEx.GridControl.ExportGridToExcel(DataSheetName, controlEx.GridView.OptionsView.AllowCellMerge); } } } } } } //把文件夹中多个文件合并 this.MergeExcel_EPPlus(Paths.ToArray(), dialog.FileName); } } } /// /// 合并多XLSX文件(最终稳定版:仅复制数据+解决枚举异常) /// /// 待合并文件路径列表 /// 合并后输出路径 public void MergeExcel_EPPlus(string[] sourceFilePaths, string outputFilePath) { // 基础参数校验 if (sourceFilePaths == null || sourceFilePaths.Length == 0) throw new ArgumentNullException(nameof(sourceFilePaths), "待合并文件列表不能为空"); if (string.IsNullOrEmpty(outputFilePath)) throw new ArgumentNullException(nameof(outputFilePath), "输出文件路径不能为空"); // 创建目标Excel包 using (ExcelPackage targetPackage = new ExcelPackage()) { try { // 删除EPPlus默认创建的空工作表 if (targetPackage.Workbook.Worksheets.Count > 0) { targetPackage.Workbook.Worksheets.Delete(0); } // 遍历所有待合并的源文件 foreach (var filePath in sourceFilePaths) { // 跳过无效文件(不存在/非xlsx) if (!File.Exists(filePath) || Path.GetExtension(filePath).ToLower() != ".xlsx") { XtraMessageBox.Show($"跳过无效文件:{filePath}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); continue; } // 读取源Excel文件(使用FileStream避免文件占用) using (var sourceStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (ExcelPackage sourcePackage = new ExcelPackage(sourceStream)) { // ========== 核心修复:先将工作表名称存入列表,避免枚举时修改集合 ========== // 步骤1:提取所有源工作表名称到临时列表 List sourceSheetNames = new List(); foreach (ExcelWorksheet sheet in sourcePackage.Workbook.Worksheets) { sourceSheetNames.Add(sheet.Name); } // 步骤2:遍历名称列表(而非直接遍历工作表集合) foreach (string sheetName in sourceSheetNames) { // 获取源工作表(通过名称,而非枚举) ExcelWorksheet sourceSheet = sourcePackage.Workbook.Worksheets[sheetName]; // 跳过空工作表(无数据维度) if (sourceSheet == null || sourceSheet.Dimension == null) { continue; } //过滤隐藏 if (sourceSheet.Hidden != eWorkSheetHidden.Visible) { continue; } // 步骤3:源工作簿内复制临时表(2参数Copy方法) string tempSheetName = $"Temp_{Guid.NewGuid().ToString("N").Substring(0, 8)}"; // 先检查临时表名是否重复(防呆) if (sourcePackage.Workbook.Worksheets[tempSheetName] != null) { tempSheetName += $"_{DateTime.Now.Ticks}"; } ExcelWorksheet tempSheet = sourcePackage.Workbook.Worksheets.Copy(sheetName, tempSheetName); // 步骤4:创建目标工作表(处理名称重复) string baseTargetName = Path.GetFileNameWithoutExtension(filePath); string targetSheetName = baseTargetName; int index = 1; // 检查目标工作簿是否已有同名工作表 while (targetPackage.Workbook.Worksheets.Any(ws => ws.Name == targetSheetName)) { targetSheetName = $"{baseTargetName}_{index++}"; } ExcelWorksheet targetSheet = targetPackage.Workbook.Worksheets.Add(targetSheetName); // 步骤5:安全复制数据(仅复制值+列宽+行高,无样式) SafeCopyWorksheetContent(tempSheet, targetSheet); // 步骤6:删除源工作簿内的临时表(此时已不在枚举过程中,无异常) if (sourcePackage.Workbook.Worksheets[tempSheetName] != null) { sourcePackage.Workbook.Worksheets.Delete(tempSheetName); } } } // 每处理一个文件清理一次内存,避免堆积 GC.Collect(); GC.WaitForPendingFinalizers(); } // 保存合并后的文件(覆盖已存在的文件) FileInfo outputFileInfo = new FileInfo(outputFilePath); if (outputFileInfo.Exists) { outputFileInfo.Delete(); // 删除已存在的文件,避免保存失败 } targetPackage.SaveAs(outputFileInfo); XtraMessageBox.Show($"Excel文件合并完成!\n输出路径:{outputFilePath}", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { throw new Exception($"合并Excel失败:{ex.Message}", ex); } } } /// /// 安全复制工作表内容(仅复制数据+列宽+行高,无样式,无越界异常) /// /// 源工作表 /// 目标工作表 private void SafeCopyWorksheetContent(ExcelWorksheet sourceSheet, ExcelWorksheet targetSheet) { // 获取源工作表的有效数据范围 int startRow = sourceSheet.Dimension.Start.Row; int startCol = sourceSheet.Dimension.Start.Column; int endRow = sourceSheet.Dimension.End.Row; int endCol = sourceSheet.Dimension.End.Column; // 1. 批量复制单元格值(核心:仅复制数据,无样式操作) targetSheet.Cells[startRow, startCol, endRow, endCol].Value = sourceSheet.Cells[startRow, startCol, endRow, endCol].Value; // 2. 复制列宽(仅复制有有效值的列) for (int col = startCol; col <= endCol; col++) { if (sourceSheet.Column(col).Width > 0) { targetSheet.Column(col).Width = sourceSheet.Column(col).Width; } } // 3. 复制行高(仅复制有有效值的行) for (int row = startRow; row <= endRow; row++) { if (sourceSheet.Row(row).Height > 0) { targetSheet.Row(row).Height = sourceSheet.Row(row).Height; } } // 4. 自动调整列宽(优化显示效果) targetSheet.Cells[startRow, startCol, endRow, endCol].AutoFitColumns(); } /// /// 顶部表格双击,添加到下方 /// /// /// private void GcMain_DoubleClick(object sender, EventArgs e) { DataRow rowItem = this.gcMain.GridView.GetFocusedDataRow(); if (rowItem != null) { DataTable dataTable = this.gridBottom.GridControl.DataSource as DataTable; if (dataTable == null) { dataTable = rowItem.Table.Clone(); this.gridBottom.GridControl.DataSource = dataTable; } DataRow Item = dataTable.Rows.Cast().FirstOrDefault(x => x[this.ParmaryKey] + "" == rowItem[this.ParmaryKey] + ""); if (Item == null) { dataTable.Rows.Add(rowItem.ItemArray); //gridBottom.GridView.ClearSelection(); //gridBottom.GridView.FocusedRowHandle = dataTable.Rows.Count - 1; //gridBottom.GridView.SelectRow(dataTable.Rows.Count - 1); } rowItem.AcceptChanges(); } } /// /// 取消选中 /// /// /// private void GridBottom_DoubleClick(object sender, EventArgs e) { if (this.gridBottom.GridView.RowCount == 0) return; DataRow rowItem = this.gridBottom.GridView.GetFocusedDataRow(); (this.gridBottom.GridControl.DataSource as DataTable).Rows.Remove(rowItem); } /// /// 说明:树节点点击后刷新数据 /// 创建人:龚宇超 /// 创建日期:2017-10-26 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The source of the event. /// The instance containing the event data. protected void OnTreeLeftTreeNodeSelected(object sender, TreeViewEventArgs e) { try { string where = null; if (string.IsNullOrWhiteSpace(this.ParentUnionField)) { where = string.Format(this.SysModel.TreeExactQuery ? " and {0} = '{1}' " : " and {0} like '{1}%' ", this.treeLeft.TreeNodeKeyField, e.Node.Name); } else { where = string.Format(this.SysModel.TreeExactQuery ? " and {0} = '{1}' " : " and {0} like '{1}%' ", this.ParentUnionField, e.Node.Name); } this.SetMainGridView(where); } catch (Exception ex) { string Message = ErrorMessage.PromptErrorMessage(ex); MessageUtil.Show(Message, ex.Message); } } /// /// 分隔条位置改变时 /// /// /// private void OnSplitMainContainerPositionChanged(object sender, EventArgs e) { try { if (this.Model != null) { IniHelper.Write(string.Format("PubModuleExport_SplitMain_{0}", this.Model.ModuleCode), this.splitMainContainer.SplitterPosition + ""); IniHelper.Write(string.Format("PubModuleExport_SplitRight_{0}", this.Model.ModuleCode), this.splitRightContainer.SplitterPosition + ""); } } catch (Exception ex) { MessageUtil.Show(ex.Message); } } /// /// 说明:设置左侧树数据 /// 创建人:龚宇超 /// 创建日期:2017-10-25 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// private void SetLeftTreeView() { this.LeftRowObj = BaseModuleImpl.GetBaseLeftTreeField(this.Model.ModuleCode);//获取表格左侧树字段 if (this.LeftRowObj != null) { this.ParentUnionField = this.LeftRowObj["fieldname"] + ""; string parentKeyField = this.LeftRowObj["fieldsqlid"] + ""; this.treeLeft.TreeNodeKeyField = parentKeyField; this.treeLeft.TreeNodeTextField = this.LeftRowObj["fieldsqlname"] + ""; this.treeLeft.TreeNodeSelectAfter += new TreeViewEventHandler(OnTreeLeftTreeNodeSelected); this.treeLeft.TreeNodeLength = this.LeftRowObj.Table.Columns.Contains("TreeNodeLength") ? this.LeftRowObj["TreeNodeLength"] + "" : ""; this.treeLeft.BindTreeView(BaseImpl.GetDataTableResult(this.LeftRowObj["fieldsql"] + "")); if (this.LeftRowObj.Table.Columns.Contains("TreeNodeSearch") && "1".Equals(this.LeftRowObj["TreeNodeSearch"] + "")) this.treeLeft.pl_top.Visible = true; } else { // 根据模块上配置的sql加载树 if (this.SysModel != null && !string.IsNullOrEmpty(this.SysModel.TreeSQL)) { this.ParentUnionField = "SpeciesNo"; string parentKeyField = "SpeciesNo"; this.treeLeft.TreeNodeKeyField = parentKeyField; this.treeLeft.TreeNodeTextField = "SpeciesName"; this.treeLeft.TreeNodeSelectAfter += new TreeViewEventHandler(OnTreeLeftTreeNodeSelected); this.treeLeft.BindTreeView(BaseImpl.GetDataTableResult(this.SysModel.TreeSQL)); } else if (this.SysModel.DefaultTreeSql) { this.ParentUnionField = "SpeciesNo"; string parentKeyField = "SpeciesNo"; this.treeLeft.TreeNodeKeyField = parentKeyField; this.treeLeft.TreeNodeTextField = "SpeciesName"; this.treeLeft.TreeNodeSelectAfter += new TreeViewEventHandler(OnTreeLeftTreeNodeSelected); this.treeLeft.BindTreeView(BaseImpl.GetDataTableResult("select a.SpeciesNo,a.SpeciesName from p_productspeciestab a where a.ban=0")); } } } /// /// 说明:加载主表格数据 /// 创建人:龚宇超 /// 创建日期:2018-01-31 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The where key. protected void SetMainGridView(string where = "") { string sqlValue = this.SysModel.MenuSql; //判断是否是select开头,上方的判断可能出现开头是空格或者注释的情况 sqlValue = IsSelectAtStart(sqlValue) ? sqlValue + where : sqlValue; this.SearchObj.SearchGrid(sqlValue); } /// /// 说明:检查可用条件 /// 创建人:龚宇超 /// 创建日期:2017-11-09 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// The cond. /// The data row. /// true if XXXX, false otherwise. private bool ValidateCond(string cond, DataRow dataRow) { bool result = false; cond = ReplaceHelper.ReplaceRowParam(dataRow, cond); if (cond.StartsWith("@") || cond.StartsWith("!")) { result = "1".Equals(BaseImpl.GetDefaultValue(cond)); } else if (dataRow == null) { result = ReplaceHelper.EvalCond(cond); } else { result = ReplaceHelper.ReplaceRowParamCond(dataRow, cond); } return result; } /// /// 判断是否是selete开头(可以处理sql前方有注释和空格的情况) /// /// /// public static bool IsSelectAtStart(string sqlText) { string cleanedText = Regex.Replace(sqlText, @"^(\s*--.*?(\r\n|\n)|\s*)*", ""); return cleanedText.StartsWith("select", StringComparison.OrdinalIgnoreCase); } /// /// 说明:拿到底部表格数据 /// 创建人:龚宇超 /// 创建日期:2017-11-21 /// 修改人: /// 修改日期: /// 修改备注: /// 版本:1.0 /// /// List<GridDetailModel>. private List GetDetails(string ModuleCode) { List details = new List();//表格明细对象的集合 DataTable table = BaseModuleImpl.GetBaseDetailPages(ModuleCode);// 根据传入的模块编号获得基础档案底部标签的数据 foreach (DataRow item in table.Rows) { DataTable gridColumns = ReportImpl.GetReportDetailColumns(ModuleCode, item["id"] + "");//获取报表明细列 details.Add(new GridDetailModel(item, gridColumns, GridCustomColumnStruct.BaseDetailGridView)); } return details; } /// /// 替换DataTable列名并删除无匹配的列: /// 1. 将MasterData匹配FieldName的列名替换为对应的userName; /// 2. 删除MasterData中在controls无匹配FieldName的列 /// /// 数据源表(需要替换列名+删除列) /// 控件信息表(FieldName=字段名,userName=中文列名) public void ReplaceAndRemoveUnmatchedColumns(DataTable MasterData, DataTable controls) { // 前置校验:避免空表/空引用导致异常 if (MasterData == null || controls == null || MasterData.Columns.Count == 0 || controls.Rows.Count == 0) { Console.WriteLine("数据表为空,无需处理"); return; } // 第一步:提取controls中的FieldName(去重),作为保留列名单 // 同时构建FieldName → userName的映射字典 HashSet keepFieldNames = new HashSet(StringComparer.OrdinalIgnoreCase); // 不区分大小写 Dictionary fieldNameToUserNameDict = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (DataRow row in controls.Rows) { string fieldName = row["FieldName"]?.ToString()?.Trim(); string userName = row["userName"]?.ToString()?.Trim(); // 过滤空值,避免无效数据 if (string.IsNullOrEmpty(fieldName) || string.IsNullOrEmpty(userName)) { continue; } // 去重:只保留第一个匹配的FieldName→userName if (!fieldNameToUserNameDict.ContainsKey(fieldName)) { keepFieldNames.Add(fieldName); fieldNameToUserNameDict.Add(fieldName, userName); } } // 第二步:遍历MasterData的列(注意:删除列需用倒序遍历,避免索引错乱) // 先收集需要删除的列,再批量删除(比遍历中直接删除更安全) List columnsToRemove = new List(); foreach (DataColumn column in MasterData.Columns) { string originalColumnName = column.ColumnName.Trim(); // 情况1:列名在保留名单中 → 替换为对应的userName if (keepFieldNames.Contains(originalColumnName)) { string newColumnName = fieldNameToUserNameDict[originalColumnName]; // 避免重复列名(极端情况:不同FieldName对应相同userName) if (!MasterData.Columns.Contains(newColumnName)) { column.ColumnName = newColumnName; Console.WriteLine($"列名替换成功:{originalColumnName} → {newColumnName}"); } else { Console.WriteLine($"警告:替换后的列名[{newColumnName}]已存在,保留原列名[{originalColumnName}]"); } } // 情况2:列名不在保留名单中 → 标记为待删除 else { columnsToRemove.Add(column); Console.WriteLine($"列[{originalColumnName}]无匹配的FieldName,标记为待删除"); } } // 第三步:批量删除无匹配的列 foreach (DataColumn col in columnsToRemove) { MasterData.Columns.Remove(col); Console.WriteLine($"已删除列:{col.ColumnName}"); } } } }