using DevExpress.Data; using DevExpress.Utils; using DevExpress.XtraGrid; using DevExpress.XtraGrid.Columns; using DevExpress.XtraGrid.Views.BandedGrid; using DevExpress.XtraGrid.Views.Base; using DevExpress.XtraGrid.Views.Grid; using Lskj.Business.Impl; using Lskj.Control; using Lskj.Control.Model; using Lskj.Data; using Lskj.Model; using Lskj.ProductSched; using Lskj.Util; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Drawing; using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; namespace Lskj.ProductiSched { public partial class FrmProductSched : UserControl { public ProductDataModel DataModel; public FrmProductSched() { InitializeComponent(); } /// /// 界面加载时 /// public void OnLoad(DynamicProductSchedModel mainModel) { GetControlData(mainModel); InitSpiltLocation(); InitControlView(); InitControlEvents(); SetControlData(); } /// /// 获取数据 /// public void GetControlData(DynamicProductSchedModel mainModel) { DataModel = new ProductDataModel(); DataModel.TopSysModel = mainModel; DataRow topSysRow = MainImpl.GetSystemdllTab(DataModel.TopSysModel.ModuleCode); DataModel.TopModuleModel = new ModuleModel(topSysRow); DataModel.TopModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.TopSysModel.ModuleCode); DataModel.TopGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.TopSysModel.ModuleCode); DataModel.TopRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); DataModel.TopRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); DataModel.TopSearchTab = BaseModuleImpl.GetCustomQueryFields(DataModel.TopModuleModel.CondKey); DataModel.TopSchemesTable = BaseModuleImpl.GetSchemesList(DataModel.TopSysModel.ModuleId); DataModel.TopSearchObj = new MyControl(DataModel.TopModuleModel.MenuSql, bandGcTop); DataModel.TopSearchObj.Model = DataModel.TopSysModel; DataTable detailsTab = BaseModuleImpl.GetBaseDetailPages(DataModel.TopSysModel.ModuleCode); if (detailsTab != null) { if (detailsTab.Rows.Count > 1) { string moduleCode = detailsTab.Rows[0]["unionModule"] + ""; DataModel.BottomDetailModel = new GridDetailModel(detailsTab.Rows[0], null, GridCustomColumnStruct.BaseDetailGridView); DataModel.BottomSysModel = new DynamicModel(new string[] { DataModel.TopSysModel.FormText, DataModel.TopSysModel.UserId, DataModel.TopSysModel.UserName, DataModel.TopSysModel.Privilege, moduleCode }); DataRow sysRow = MainImpl.GetSystemdllTab(DataModel.BottomSysModel.ModuleCode); DataModel.BottomModuleModel = new ModuleModel(sysRow); DataModel.BottomModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.BottomSysModel.ModuleCode); DataModel.BottomGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.BottomSysModel.ModuleCode); DataModel.BottomRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); DataModel.BottomRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); } if (detailsTab.Rows.Count > 1) { string moduleCode = detailsTab.Rows[1]["unionModule"] + ""; DataModel.RightDetailModel = new GridDetailModel(detailsTab.Rows[1], null, GridCustomColumnStruct.BaseDetailGridView); DataModel.RightSysModel = new DynamicModel(new string[] { DataModel.TopSysModel.FormText, DataModel.TopSysModel.UserId, DataModel.TopSysModel.UserName, DataModel.TopSysModel.Privilege, moduleCode }); DataRow sysRow = MainImpl.GetSystemdllTab(DataModel.RightSysModel.ModuleCode); DataModel.RightModuleModel = new ModuleModel(sysRow); DataModel.RightModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.RightSysModel.ModuleCode); DataModel.RightGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.RightSysModel.ModuleCode); DataModel.RightRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); DataModel.RightRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); } else { string moduleCode = detailsTab.Rows[0]["unionModule"] + ""; DataModel.RightDetailModel = new GridDetailModel(detailsTab.Rows[0], null, GridCustomColumnStruct.BaseDetailGridView); DataModel.RightSysModel = new DynamicModel(new string[] { DataModel.TopSysModel.FormText, DataModel.TopSysModel.UserId, DataModel.TopSysModel.UserName, DataModel.TopSysModel.Privilege, moduleCode }); DataRow sysRow = MainImpl.GetSystemdllTab(DataModel.RightSysModel.ModuleCode); DataModel.RightModuleModel = new ModuleModel(sysRow); DataModel.RightModuleModel.ParmaryKey = BaseImpl.GetBasePrimaryKey(DataModel.RightSysModel.ModuleCode); DataModel.RightGridColumns = BaseModuleImpl.GetBaseGridColumns(DataModel.RightSysModel.ModuleCode); DataModel.RightRightMenus = BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey); DataModel.RightRowColors = BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey); } } } /// /// 设置数据 /// public void SetControlData() { } /// /// 初始化控件 /// public void InitControlView() { //搜索控件 bool fixedQuery = DataModel.TopSearchTab == null || DataModel.TopSearchTab.Rows.Count == 0; if (!fixedQuery) { this.pl_mainSearch.Height = DataModel.TopSearchObj.InitSearchControl(DataModel.TopSearchTab, this.pl_search, true, DataModel.TopSchemesTable, DataModel.TopSysModel); this.pl_search.Width = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Max(n => n.Location.X + n.Width) + 5; } //上方表格 bandGcTop.Model = DataModel.TopSysModel; bandGcTop.SetEditColumns(DataModel.TopGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.TopModuleModel.FormKey); bandGcTop.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.FormKey), DataModel.TopSysModel); bandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.FormKey)); AddDataColumns(bandGcTop); if (DataModel.TopModuleModel.HasReport) { flowLayoutPanel.Visible = false; } //下方表格 if (DataModel.BottomSysModel != null && !string.IsNullOrEmpty(DataModel.BottomSysModel.ModuleCode)) { bandGcBottom.Model = DataModel.BottomSysModel; bandGcBottom.SetEditColumns(DataModel.BottomGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.BottomModuleModel.FormKey); bandGcBottom.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.BottomModuleModel.FormKey), DataModel.BottomSysModel); bandGcBottom.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.BottomModuleModel.FormKey)); AddDataColumns(bandGcBottom); foreach (GridBand gridBand in bandGcBottom.BandedView.Bands) { gridBand.OptionsBand.AllowSize = false; foreach (BandedGridColumn bandedGridColumn in gridBand.Columns) { bandedGridColumn.OptionsColumn.AllowSize = false; } } bandGcBottom.BandedView.OptionsBehavior.Editable = false; OnBandedViewColumnWidthChanged(bandGcTop.BandedView, null); } else { splitLeftControl.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Panel1; } //右侧表格 if (!string.IsNullOrEmpty(DataModel.RightSysModel.ModuleCode)) { gcRight.Model = DataModel.RightSysModel; gcRight.SetEditColumns(DataModel.RightGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.RightModuleModel.FormKey); gcRight.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.RightModuleModel.FormKey), DataModel.RightSysModel); gcRight.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.RightModuleModel.FormKey)); } } /// /// 绑定控件事件 /// public void InitControlEvents() { splitLeftControl.SplitterPositionChanged += OnSplitContainerPositionChanged; splitMainControl.SplitterPositionChanged += OnSplitContainerPositionChanged; DataModel.TopSearchObj.OnDataSourceBindCallBack += OnDataSourceBindCallBack; DataModel.TopSearchObj.OnSearchAfterCallBack += OnSearchAfterCallBack; bandGcTop.BandedView.BandWidthChanged += OnBandedViewColumnWidthChanged; bandGcTop.BandedView.ColumnWidthChanged += OnBandedViewColumnWidthChanged; bandGcTop.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged; bandGcBottom.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged; bandGcTop.BandedView.RowCellClick += OnBandedViewRowCellClick; bandGcTop.BandedView.KeyDown += OnBandedViewKeyDown; bandGcTop.BandedView.CustomDrawFooterCell += OnCustomDrawFooterCell; bandGcTop.BandedView.CustomDrawColumnHeader += OnCustomDrawColumnHeader; bandGcBottom.BandedView.CustomDrawColumnHeader += OnCustomDrawColumnHeader; btnSave.Click += OnBtnSaveClick; } /// /// 保存按钮点击时 /// /// /// private void OnBtnSaveClick(object sender, EventArgs e) { if (SaveGridRecord()) { if (SaveDatePlanRecord()) { DataModel.TopSearchObj.ButtonObj.PerformClick(); } } } /// /// 保存主表数据 /// /// public bool SaveGridRecord() { string tableName = DataModel.TopModuleModel.MenuTable; string Autogrowcolumn = BaseImpl.GetResult(string.Format("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.columns WHERE TABLE_NAME='{0}' AND COLUMNPROPERTY(OBJECT_ID('{0}'),COLUMN_NAME,'IsIdentity')=1", tableName)) + ""; DataTable DatabasePropertySheet = BaseImpl.GetDataTableResult(string.Format("select COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH from information_schema.columns where table_name = '{0}'", tableName));//数据库属性表 string SaveErrorMessage = "失败列表:\r\n"; if (string.IsNullOrEmpty(tableName)) { MessageUtil.Show(ResourceKeys.MenuTableNameIsNull); return false; } List mList = new List(); DataRow[] modifiedRows = (bandGcTop.BandedView.GridControl.DataSource as DataTable) .Rows .Cast() .Where(x => x.RowState == DataRowState.Modified || x.RowState == DataRowState.Added) .ToArray(); if (modifiedRows == null || modifiedRows.Length == 0) { MessageUtil.Show(ResourceKeys.UnUpdateData); return false; } else { DataColumnCollection columns = BaseImpl.GetTableColumns(tableName).Columns; foreach (DataRow row in modifiedRows) { string updateSql = "update {0} set {1} where {2}='{3}';"; string insertSql = "insert into {0}({1}) values({2});"; string updateFields = string.Empty; string insertFields = string.Empty; string insertValues = string.Empty; BaseSaveModel model = new BaseSaveModel() { MenuCode = DataModel.TopSysModel.ModuleCode, TableName = tableName, KeyField = DataModel.TopModuleModel.ParmaryKey, NewVer = DataModel.TopModuleModel.NewVer }; foreach (DataColumn col in columns) { // 区分大小写匹配列 DataRow hasContainRow = DataModel.TopGridColumns.Rows.Cast().FirstOrDefault(x => (x["fieldname"] + "").ToLower() == col.ColumnName.ToLower()); if (hasContainRow != null && col.ColumnName != DataModel.TopModuleModel.ParmaryKey && !col.ColumnName.Equals("id") && Autogrowcolumn.ToLower() != col.ColumnName.ToLower()) { if (row.RowState == DataRowState.Modified && string.IsNullOrEmpty(DataModel.TopModuleModel.CustomColumnSQL)) { string newValue = row[col.ColumnName, DataRowVersion.Current] + ""; string oldValue = row[col.ColumnName, DataRowVersion.Original] + ""; //如果是修改状态,没有改变的值就不拼接,以免造成多人同时修改同一行不同列的值混乱情况 if (oldValue != newValue) { if ((col.DataType == typeof(DateTime)) && (row[col.ColumnName] + "" == "")) { updateFields += string.Format("[{0}]=null,", col.ColumnName); } else { if (col.DataType == typeof(Decimal) && string.IsNullOrWhiteSpace((row[col.ColumnName] + "").Replace("'", "''"))) { updateFields += string.Format("[{0}]='{1}',", col.ColumnName, 0); } else { updateFields += string.Format("[{0}]=N'{1}',", col.ColumnName, (row[col.ColumnName] + "").Replace("'", "''")); } } } } else if (row.RowState == DataRowState.Added || (row.RowState == DataRowState.Modified && !string.IsNullOrEmpty(DataModel.TopModuleModel.CustomColumnSQL))) { // 动态生成列,保存时默认全部为新增 string fieldValue = (row[col.ColumnName] + "").Replace("'", "''"); insertFields += "[" + col.ColumnName + "],"; if (!string.IsNullOrWhiteSpace(fieldValue)) { insertValues += col.DataType == typeof(DateTime) ? "'" + Convert.ToDateTime(fieldValue).ToString("yyyy-MM-dd HH:mm:ss") + "'," : "N'" + fieldValue + "',"; } else { if (col.DataType == typeof(Decimal) || col.DataType == typeof(Int32)) insertValues += "0,"; else if (col.DataType == typeof(DateTime)) insertValues += "NULL,"; else insertValues += "'',"; } } SaveErrorMessage = SaveErrorMessage + DatabaseFormatJudgment.SaveOrModifyBalidation(DataModel.TopGridColumns, DatabasePropertySheet, row, col, (row[col.ColumnName] + "").Replace("'", "''")); } } // 检查是否保存主键字段 if (row.RowState == DataRowState.Added && !insertFields.Contains(DataModel.TopModuleModel.ParmaryKey) && !"ID".Equals(DataModel.TopModuleModel.ParmaryKey, StringComparison.OrdinalIgnoreCase)) { // 跳过自动增长列处理 if (Autogrowcolumn.ToLower() != DataModel.TopModuleModel.ParmaryKey.ToLower()) { insertFields += DataModel.TopModuleModel.ParmaryKey + ","; insertValues += "N'" + row[DataModel.TopModuleModel.ParmaryKey] + "',"; } } updateFields = updateFields.TrimEnd(','); insertFields = insertFields.TrimEnd(','); insertValues = insertValues.TrimEnd(','); if (!string.IsNullOrEmpty(updateFields)) { model.FieldValue = row[DataModel.TopModuleModel.ParmaryKey] + ""; model.BaseSaveType = SaveType.Update; model.BaseSql = string.Format(updateSql, tableName, updateFields, DataModel.TopModuleModel.ParmaryKey, row[DataModel.TopModuleModel.ParmaryKey]); } if (!string.IsNullOrEmpty(insertFields)) { model.BaseSaveType = SaveType.Add; model.FieldValue = row[DataModel.TopModuleModel.ParmaryKey] + ""; model.BaseSql = string.Format(insertSql, tableName, insertFields, insertValues); } if (!string.IsNullOrWhiteSpace(model.BaseSql)) mList.Add(model); } try { if (mList.Count == 0) { return true; } string retuenMsg = ""; string apiRetMsg = ""; // 批量保存数据 if (BaseModuleImpl.SaveBaseGridData(mList, out retuenMsg, out apiRetMsg)) { return true; } else { StringBuilder builder = new StringBuilder(); builder.Append("失败列表\r\n"); foreach (BaseSaveModel item in mList) { if (!string.IsNullOrEmpty(item.FaultMsg)) SaveErrorMessage += item.FaultMsg + "\r\n"; } LogHelper.Instance.WriteLog(builder.ToString()); MessageUtil.Show(SaveErrorMessage); return false; } } catch (Exception ex) { string Message = ErrorMessage.PromptErrorMessage(ex); MessageUtil.Show(Message, ex.Message); return false; } } } /// /// 保存日期数据 /// private bool SaveDatePlanRecord() { // 获取主数据源,假设已绑定到 gridControl1 DataTable mainDataSource = bandGcTop.BandedView.GridControl.DataSourceTable(); if (mainDataSource == null) { return true; } // 当前操作用户(例如从全局获取) string currentUser = ERPInfo.Instance.UserName; DataTable tvp = new DataTable(); tvp.Columns.Add("billdocument_id", typeof(string)); tvp.Columns.Add("showday", typeof(string)); tvp.Columns.Add("amount", typeof(decimal)); tvp.Columns.Add("operatorname", typeof(string)); // 遍历主数据源所有行,仅处理已修改行 foreach (DataRow row in mainDataSource.Rows) { if (row.RowState == DataRowState.Modified) { // 获取关联的 keyvalue(用于匹配 mps_dayplantab.billdocument_id) string key = row["keyvalue"].ToString(); // 遍历每个列,处理虚拟列(列名格式必须为 "yyyy-MM-dd") foreach (DataColumn col in mainDataSource.Columns) { // 忽略固定字段 if (col.ColumnName == "ID" || col.ColumnName == "keyvalue" || col.ColumnName == "Name") continue; // 仅处理列名符合完整日期格式的虚拟列 if (!Regex.IsMatch(col.ColumnName, @"^\d{4}-\d{2}-\d{2}$")) continue; // 比较原始值和当前值 object originalValue = row[col, DataRowVersion.Original]; object currentValue = row[col, DataRowVersion.Current]; if (!object.Equals(originalValue, currentValue)) { decimal newAmount = 0m; if (row[col] != DBNull.Value && !string.IsNullOrWhiteSpace(row[col].ToString())) { decimal.TryParse(row[col].ToString(), out newAmount); } DataRow dr = tvp.NewRow(); dr["billdocument_id"] = key; dr["showday"] = col.ColumnName; // 列名如 "2025-03-06" dr["amount"] = newAmount; dr["operatorname"] = currentUser; tvp.Rows.Add(dr); } } } } if (tvp.Rows.Count == 0) { return true; } // 调用存储过程保存变更数据 string msg; int ret = SaveDayPlanChanges(tvp, out msg); if (ret == 1) { MessageUtil.Show("保存成功:" + msg); return true; } else { MessageUtil.Show("保存失败:" + msg); return false; } } /// /// 保存日计划变更数据(批量保存)。 /// 调用存储过程 usp_MergeDayPlanChanges,将所有变更记录一次性提交到数据库。 /// 通过 TVP 参数传递数据,同时捕获输出参数 @msg 和返回值。 /// /// 包含所有变更记录的 DataTable,必须与 dbo.DayPlanChangeType 定义一致 /// 输出提示信息,存储过程执行后的返回消息 /// 存储过程返回值,成功返回 1,失败返回 0 public int SaveDayPlanChanges(DataTable tvp, out string message) { // 创建输出参数 @msg SqlParameter pMsg = new SqlParameter("@msg", SqlDbType.VarChar, 2000) { Direction = ParameterDirection.Output }; // 创建返回值参数 @return SqlParameter returnValue = new SqlParameter("@return", SqlDbType.Int) { Direction = ParameterDirection.ReturnValue }; // 创建 TVP 参数,名称必须与存储过程参数一致 SqlParameter tvpParam = new SqlParameter("@DayPlanChanges", SqlDbType.Structured) { TypeName = "dbo.DayPlanChangeType", Value = tvp }; // 构造参数数组 SqlParameter[] parameters = new SqlParameter[] { tvpParam, pMsg, returnValue }; // 执行存储过程,此处调用 ExecuteNonQuery 即可,不需要返回数据集 // 请确保 DBUtil.ExecuteNonQuery 方法能够传递参数并执行存储过程 BaseImpl.ExecProcedure("usp_MergeDayPlanChanges", parameters); // 获取输出参数 @msg 中的提示信息 message = pMsg.Value.ToString(); // 获取存储过程的返回值 int result = Convert.ToInt32(returnValue.Value); return result; } /// /// 单元格点击刷新当前行数据 /// /// /// private void OnBandedViewRowCellClick(object sender, RowCellClickEventArgs e) { try { GridDetailModel model = DataModel.RightDetailModel; DataRow rowItem = bandGcTop.BandedView.GetFocusedDataRow(); if (rowItem != null) { string searchSql = this.GetSearchSql(model, rowItem, false); gcRight.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql)); if (e != null) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); if (baseUserControl != null) { LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; DateTime dateTime = labelDateEdit.TextEdit.DateTime; DataRow focusedRow = bandGcTop.BandedView.GetFocusedDataRow(); DataTable dataDayPlan = gcRight.GridControl.DataSourceTable().Copy(); UpdateRowWithDayPlan(focusedRow, dataDayPlan, dateTime); } } } } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 获取查询sql /// /// /// /// /// private string GetSearchSql(GridDetailModel model, DataRow rowItem, bool isLeft = false) { string fieldName = !string.IsNullOrEmpty(model.UnionParentField) && rowItem.Table.Columns.Contains(model.UnionParentField) ? model.UnionParentField : DataModel.TopModuleModel.ParmaryKey; string sqlValue = model.IsReadOnly || model.IsChart ? model.DetailSql : DataModel.RightModuleModel.MenuSql; sqlValue = ReplaceHelper.ReplaceRowParam(rowItem, sqlValue); DataRow row = bandGcTop.GetViewFocusedDataRow(); if (row != null && isLeft) { //先替换左侧选中行,在替换主表 sqlValue = ReplaceHelper.ReplaceRowParam(row, sqlValue); } if (ReplaceHelper.IsSelect(sqlValue) && !string.IsNullOrEmpty(model.UnionValue)) { string Conditions = string.Empty; //是左侧选中行,并且没有替换字段,则使用主表选中行 Conditions = isLeft ? rowItem.Table.Columns.Contains(fieldName) ? rowItem[fieldName] + "" : row[fieldName] + "" : rowItem[fieldName] + ""; sqlValue = ReplaceHelper.ReplaceWhereCond(sqlValue) + string.Format(" and {0}='{1}'", model.UnionValue, Conditions); } if (!string.IsNullOrEmpty(model.UnionCond)) { string UnionCond = ReplaceHelper.ReplaceRowParam(rowItem, model.UnionCond); sqlValue += UnionCond; } return sqlValue; } /// /// 宽度改变时 /// /// /// private void OnBandedViewColumnWidthChanged(object sender, EventArgs e) { if (sender == bandGcTop.BandedView && bandGcBottom.Visible) { int allWidth = 0; foreach (GridBand gridBand in bandGcTop.BandedView.Bands) { if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_")) { break; } else { allWidth += gridBand.Width; } } List bandedColumnList = new List(); foreach (GridBand gridBand in bandGcBottom.BandedView.Bands) { if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_")) { break; } else { bandedColumnList.AddRange(gridBand.Columns.Cast()); } } if (bandedColumnList.Count > 0) { int perWidth = allWidth / bandedColumnList.Count; foreach (BandedGridColumn bandedGridColumn in bandedColumnList) { bandedGridColumn.Width = perWidth; } } } } /// /// 水平滚动条改变时 /// /// /// private void OnBandedViewLeftCoordChanged(object sender, EventArgs e) { if (sender == bandGcTop.BandedView) { bandGcBottom.BandedView.LeftCoord = bandGcTop.BandedView.LeftCoord; } else if (sender == bandGcBottom.BandedView) { bandGcTop.BandedView.LeftCoord = bandGcBottom.BandedView.LeftCoord; } } /// /// 搜索条件绑定完成后 /// /// /// private void OnDataSourceBindCallBack(object sender, EventArgs e) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); if (baseUserControl != null) { LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; DateTime dateTime = labelDateEdit.TextEdit.DateTime; UpdateDynamicColumns(bandGcTop, dateTime); UpdateDynamicColumns(bandGcBottom, dateTime); } } /// /// 搜索后事件 /// /// /// private void OnSearchAfterCallBack(object sender, EventArgs e) { BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast().Where(n => n is LabelDateEdit).FirstOrDefault(); if (baseUserControl != null) { LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit; DateTime dateTime = labelDateEdit.TextEdit.DateTime; UpdateDynamicColumns(bandGcTop, dateTime); UpdateDynamicColumns(bandGcBottom, dateTime); DataTable dataMain = bandGcTop.GridControl.DataSourceTable().Copy(); DataTable dataDetail = bandGcTop.GridControl.DataSourceTable().Copy(); bandGcTop.GridControl.DataSource = null; string sqlValue = DataModel.RightModuleModel.MenuSql; sqlValue = $"{ReplaceHelper.ReplaceWhereCond(sqlValue)} and day >= '{dateTime.ToString("yyyy-MM-dd")}'"; DataTable dataDayPlan = BaseImpl.GetDataTableResult(sqlValue); MergeMainDataWithDayPlan(dataMain, dataDayPlan, dateTime); bandGcTop.BandedView.GridControl.DataSource = dataMain; if (bandGcBottom.Visible) { DataTable bottomTab = BuildCTable(dataDetail, dataDayPlan, dateTime, 93); bandGcBottom.BandedView.GridControl.DataSource = bottomTab; } OnBandedViewRowCellClick(bandGcTop.BandedView, null); } } /// /// 获取数据源缓存 /// /// /// public void GetDataCaches(Dictionary cachesDic) { //获取通用数据 Task sysModelTask = cachesDic.GetTask(this, "SysModel"); Task dynamicModelTask = cachesDic.GetTask(this, "DynamicModel"); Task> detailsTask = cachesDic.GetTask>(this, "Details"); Task getDataCachesTask = cachesDic.AddTask(this, "DataCaches", new Task(() => { ModuleModel sysModel = sysModelTask.Result; DynamicModel dynamicModel = dynamicModelTask.Result; //创建数据 if (sysModel != null && dynamicModel != null) { Task menuConfigTabTask = cachesDic.AddTask(this, "MenuConfigTab", new Task(() => { return BaseImpl.GetMenuConfigTab(dynamicModel.ModuleId); //获取菜单其他配置 })); if (dynamicModel is DynamicExcelModel)//isExcel { Task basePrimaryKeyTask = cachesDic.AddTask(this, "BasePrimaryKey", new Task(() => { return BaseImpl.GetBasePrimaryKey(dynamicModel.ModuleCode); })); Task gridColumnsTask = cachesDic.AddTask(this, "GridColumns", new Task(() => { return BaseModuleImpl.GetBaseGridColumns(dynamicModel.ModuleCode); })); } else { //构建主表数据 } } return true; })); } /// /// 添加虚拟日期列 /// private void AddDataColumns(BandedGridControlEx bandedGridControlEx) { if (bandedGridControlEx == bandGcTop) { bandedGridControlEx.BandedView.OptionsView.ShowFooter = true; } foreach (GridBand gridBand in bandedGridControlEx.BandedView.Bands) { gridBand.Fixed = FixedStyle.Left; } for (int i = 0; i < 93; i++) { GridBand gridBand = new GridBand(); gridBand.Name = $"Day_{i}"; gridBand.Caption = ""; gridBand.OptionsBand.AllowMove = false; gridBand.OptionsBand.AllowSize = false; gridBand.AppearanceHeader.Options.UseFont = true; gridBand.AppearanceHeader.Font = new Font("宋体", 9, FontStyle.Bold); gridBand.AppearanceHeader.Options.UseTextOptions = true; gridBand.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center; bandedGridControlEx.BandedView.Bands.Add(gridBand); BandedGridColumn gridColumn = new BandedGridColumn(); gridColumn.AppearanceCell.Options.UseTextOptions = true; gridColumn.AppearanceCell.TextOptions.HAlignment = HorzAlignment.Center; gridColumn.AppearanceHeader.Options.UseTextOptions = true; gridColumn.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center; gridColumn.OptionsColumn.AllowMove = false; gridColumn.OptionsColumn.AllowSize = false; gridColumn.OptionsFilter.AllowFilter = false; gridColumn.OptionsColumn.AllowMerge = DefaultBoolean.False; gridColumn.OptionsColumn.AllowSort = DefaultBoolean.False; gridColumn.FieldName = $"DDay_{i}"; gridColumn.Width = 70; gridColumn.DisplayFormat.FormatType = FormatType.Numeric; gridColumn.DisplayFormat.FormatString = "{0:#,##0.####}"; gridColumn.Visible = false; if (bandedGridControlEx == bandGcTop) { gridColumn.SummaryItem.SummaryType = SummaryItemType.Sum; gridColumn.SummaryItem.DisplayFormat = "{0:#,##0.####}"; } gridBand.Columns.Add(gridColumn); } } /// /// 根据日期修改列状态 /// /// private void UpdateDynamicColumns(BandedGridControlEx bandedGridControlEx, DateTime currentDate) { // 定义三个月的结束日期:起始日期加3个月减1天 DateTime endDate = currentDate.AddMonths(3).AddDays(-1); bandedGridControlEx.BandedView.BeginUpdate(); try { for (int i = 0; i < 93; i++) { // 以构建列时的命名规则 "Day_{i}" 查找对应的 GridBand string bandTitle = $"Day_{i}"; GridBand gridBand = bandedGridControlEx.BandedView.Bands.Cast().FirstOrDefault(x => x.Name == bandTitle); if (gridBand == null) { continue; } // 假定每个 GridBand 下只有一个子列 BandedGridColumn gridColumn = gridBand.Columns.Count > 0 ? gridBand.Columns[0] : null; if (gridColumn == null) { continue; } // 当前列对应的日期 = 起始日期加 i 天 DateTime dateForColumn = currentDate.AddDays(i); if (dateForColumn <= endDate) { gridBand.Caption = dateForColumn.ToString("MM-dd"); gridBand.Visible = true; gridColumn.FieldName = dateForColumn.ToString("yyyy-MM-dd"); gridColumn.Caption = GetChineseWeekDayNumber(dateForColumn); gridColumn.Tag = dateForColumn; if (bandedGridControlEx == bandGcTop) { if (dateForColumn.Date < DateTime.Now.Date) { gridColumn.OptionsColumn.AllowEdit = false; } else { gridColumn.OptionsColumn.AllowEdit = true; } } gridColumn.Visible = true; } else { gridBand.Visible = false; gridColumn.Visible = false; } } } finally { bandedGridControlEx.BandedView.EndUpdate(); } } /// /// 构建带日期的数据源 /// /// /// /// /// private DataTable MergeMainDataWithDayPlan(DataTable dataMain, DataTable dataDayPlan, DateTime startDate) { string rightPrimaryKey = DataModel.RightModuleModel.ParmaryKey; string topPrimaryKey = DataModel.TopModuleModel.ParmaryKey; DateTime endDate = startDate.AddMonths(3).AddDays(-1); // 计算结束日期 // **1. 预索引 dataDayPlan 数据(billdocument_id -> 该 key 相关的所有行)** Dictionary> dayPlanMap = new Dictionary>(); foreach (DataRow row in dataDayPlan.Rows) { string billId = row[rightPrimaryKey].ToString(); if (!dayPlanMap.ContainsKey(billId)) { dayPlanMap[billId] = new List(); } dayPlanMap[billId].Add(row); } // **2. 预构建主数据的列** for (DateTime dt = startDate; dt <= endDate; dt = dt.AddDays(1)) { string colName = dt.ToString("yyyy-MM-dd"); if (!dataMain.Columns.Contains(colName)) { dataMain.Columns.Add(colName, typeof(decimal)); // 确保列存在 } } // **3. 预构建数据填充映射表** Dictionary> dataMap = new Dictionary>(); foreach (DataRow row in dataMain.Rows) { string key = row[topPrimaryKey].ToString(); if (!dataMap.ContainsKey(key)) { dataMap[key] = new Dictionary(); } // **查找 key 关联的时间数据** if (dayPlanMap.ContainsKey(key)) { foreach (DataRow dayRow in dayPlanMap[key]) { if (dayRow["day"] != DBNull.Value) { DateTime dayValue = Convert.ToDateTime(dayRow["day"]); string colName = dayValue.ToString("yyyy-MM-dd"); if (dayValue >= startDate && dayValue <= endDate && dataMain.Columns.Contains(colName)) { Decimal.TryParse(dayRow["amount"] + "", out decimal amountValue); dataMap[key][colName] = amountValue; } } } } } // **4. 一次性填充 DataTable(避免逐行赋值带来的性能问题)** foreach (DataRow row in dataMain.Rows) { string key = row[topPrimaryKey].ToString(); if (dataMap.ContainsKey(key)) { foreach (var col in dataMap[key]) { row[col.Key] = col.Value; } } } return dataMain; } /// /// 构建带日期的数据源 /// /// /// /// /// private void UpdateRowWithDayPlan(DataRow focusedRow, DataTable dataDayPlan, DateTime startDate) { string rightPrimaryKey = DataModel.RightModuleModel.ParmaryKey; string topPrimaryKey = DataModel.TopModuleModel.ParmaryKey; DateTime endDate = startDate.AddMonths(3).AddDays(-1); // 计算结束日期 // **1. 预索引 dataDayPlan 数据(billdocument_id -> 该 key 相关的所有行)** Dictionary> dayPlanMap = new Dictionary>(); foreach (DataRow row in dataDayPlan.Rows) { string billId = row[rightPrimaryKey].ToString(); if (!dayPlanMap.ContainsKey(billId)) { dayPlanMap[billId] = new List(); } dayPlanMap[billId].Add(row); } // **2. 预构建主数据的列** for (DateTime dt = startDate; dt <= endDate; dt = dt.AddDays(1)) { string colName = dt.ToString("yyyy-MM-dd"); if (!focusedRow.Table.Columns.Contains(colName)) { focusedRow.Table.Columns.Add(colName, typeof(decimal)); // 确保列存在 } } // **3. 预构建数据填充映射表** Dictionary> dataMap = new Dictionary>(); string key = focusedRow[topPrimaryKey].ToString(); if (!dataMap.ContainsKey(key)) { dataMap[key] = new Dictionary(); } // **查找 key 关联的时间数据** if (dayPlanMap.ContainsKey(key)) { foreach (DataRow dayRow in dayPlanMap[key]) { if (dayRow["day"] != DBNull.Value) { DateTime dayValue = Convert.ToDateTime(dayRow["day"]); string colName = dayValue.ToString("yyyy-MM-dd"); if (dayValue >= startDate && dayValue <= endDate && focusedRow.Table.Columns.Contains(colName)) { dataMap[key][colName] = Convert.ToDecimal(dayRow["amount"]); } } } } // **4. 一次性填充 DataTable(避免逐行赋值带来的性能问题)** if (dataMap.ContainsKey(key)) { foreach (var col in dataMap[key]) { focusedRow[col.Key] = col.Value; } } } /// /// 日期对照 /// /// /// private string GetChineseWeekDayNumber(DateTime date) { switch (date.DayOfWeek) { case DayOfWeek.Monday: return "一"; case DayOfWeek.Tuesday: return "二"; case DayOfWeek.Wednesday: return "三"; case DayOfWeek.Thursday: return "四"; case DayOfWeek.Friday: return "五"; case DayOfWeek.Saturday: return "六"; case DayOfWeek.Sunday: return "日"; default: return ""; } } /// /// 初始化位置 /// private void InitSpiltLocation() { try { string splitLeftWidth = IniHelper.Read(string.Format("ProductSched_SplitLeft_{0}", DataModel.TopSysModel.ModuleCode)); if (!string.IsNullOrEmpty(splitLeftWidth)) { splitLeftControl.SplitterPosition = Convert.ToInt32(splitLeftWidth); } string splitMainWidth = IniHelper.Read(string.Format("ProductSched_SplitMain_{0}", DataModel.TopSysModel.ModuleCode)); if (!string.IsNullOrEmpty(splitMainWidth)) { splitMainControl.SplitterPosition = Convert.ToInt32(splitMainWidth); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 分隔条位置改变时 /// /// /// private void OnSplitContainerPositionChanged(object sender, EventArgs e) { try { if (DataModel.TopSysModel != null) { IniHelper.Write(string.Format("ProductSched_SplitLeft_{0}", DataModel.TopSysModel.ModuleCode), splitLeftControl.SplitterPosition + ""); IniHelper.Write(string.Format("ProductSched_SplitMain_{0}", DataModel.TopSysModel.ModuleCode), splitMainControl.SplitterPosition + ""); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 合计显示居中设置 /// /// /// private void OnCustomDrawFooterCell(object sender, FooterCellCustomDrawEventArgs e) { e.Appearance.TextOptions.HAlignment = HorzAlignment.Center; } /// /// 表头颜色设置 /// /// /// private void OnCustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e) { if (e.Column != null && e.Column.Tag != null && e.Column.Tag is DateTime dateTime) { if (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday) { e.Appearance.ForeColor = Color.Red; } } } /// /// 按键点击事件 /// /// /// private void OnBandedViewKeyDown(object sender, KeyEventArgs e) { BandedGridView bandedGridView = (BandedGridView)sender; if (e.KeyCode == Keys.F7) { GridColumn column = bandedGridView.FocusedColumn; GridColumnModel model = column.Tag as GridColumnModel; if (column != null && column.OptionsColumn.AllowEdit && bandedGridView.RowCount > 0 && bandedGridView.OptionsBehavior.Editable) { // 允许操作 GridCell[] SelectCells = bandedGridView.GetSelectedCells(); if (SelectCells.Length > 0) { object obj = bandedGridView.GetRowCellValue(SelectCells[0].RowHandle, SelectCells[0].Column); if (MessageUtil.Show("是否替换所选单元格值?", MessageBoxButtons.YesNo) == DialogResult.Yes) { WaitForm.ShowForm("数据填充中"); if (obj != null) { foreach (GridCell gridCell in SelectCells) { if (gridCell.Column.Tag != null && gridCell.Column.Tag is DateTime dateTime) { if (dateTime.Date >= DateTime.Now.Date) { bandedGridView.SetRowCellValue(gridCell.RowHandle, gridCell.Column, obj); } } } bandedGridView.PostEditor(); e.Handled = true; } WaitForm.HideForm(); } } } } } /// /// 构建下方数据 /// /// /// /// /// /// public DataTable BuildCTable(DataTable dtA, DataTable dtPlan, DateTime startDate, int daysCount) { try { // 1. 按“产地”分组 // key: 产地; value: Tuple(总产能, 系数, keyvalue集合) var groupDict = dtA.AsEnumerable() .GroupBy(r => r.Field("产地")) .ToDictionary( g => g.Key, g => new { TotalCapacity = g.First().Field("总产能"), Coefficient = g.First().Field("系数"), KeyValues = g.Select(r => r.Field("keyvalue")).Distinct().ToList() } ); // 2. 构建 C 表结构:固定字段“产地”、“产能”,以及动态日期列(格式 "yyyy-MM-dd") DataTable dtC = new DataTable(); dtC.Columns.Add("产地", typeof(string)); dtC.Columns.Add("总产能", typeof(decimal)); List dateColumns = new List(); for (int i = 0; i < daysCount; i++) { DateTime d = startDate.AddDays(i); string colName = d.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); dtC.Columns.Add(colName, typeof(decimal)); dateColumns.Add(colName); } // 3. 预处理 dtPlan:转换 day 字段为 "yyyy-MM-dd" 字符串,方便后续匹配 var planRows = dtPlan.AsEnumerable() .Select(r => new { BillId = r.Field("billdocument_id"), ShowDay = r.Field("day").ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), Amount = r.Field("amount") }) .ToList(); // 4. 遍历每个分组,构造 C 表行数据 foreach (var kvp in groupDict) { string origin = kvp.Key; decimal totalCapacity = kvp.Value.TotalCapacity; decimal coefficient = kvp.Value.Coefficient; List keyValues = kvp.Value.KeyValues;