Files
lserp_cs_6.0/插件库/Lskj.ProductSched/FrmProductSched.cs
T
wyf 443703f29c SVN r879
SVN-Revision: r879
2025-07-21 12:50:36 +00:00

2595 lines
122 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using DevExpress.Data;
using DevExpress.Utils;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.BandedGrid;
using DevExpress.XtraGrid.Views.BandedGrid.ViewInfo;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using DevExpress.XtraTab;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Columns;
using DevExpress.XtraTreeList.Nodes;
using Lskj.Business;
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 bool TreeMultiHeader;
public bool isAddBottom;
public Control.BandedGridControlEx bandGcBottom;
public ProductDataModel DataModel;
public FrmProductSched()
{
InitializeComponent();
}
/// <summary>
/// 界面加载时
/// </summary>
public void OnLoad(DynamicProductSchedModel mainModel)
{
GetControlData(mainModel);
InitSpiltLocation();
InitControlView();
InitControlEvents();
SetControlData();
}
/// <summary>
/// 获取数据
/// </summary>
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);
if (DataModel.TopModuleModel.TreeAutoMultiHeader == 1)
{
DataModel.TopSearchObj = new MyControl(DataModel.TopModuleModel.MenuSql, treebandGcTop);
}
else
{
DataModel.TopSearchObj = new MyControl(DataModel.TopModuleModel.MenuSql, bandGcTop);
}
DataModel.TopSearchObj.Model = DataModel.TopSysModel;
DataTable detailsTab = BaseModuleImpl.GetBaseDetailPages(DataModel.TopSysModel.ModuleCode);//明细数据
List<GridDetailModel> detailsTablist = new List<GridDetailModel>();
if (detailsTab != null)
{
foreach (DataRow item in detailsTab.Rows)
{
GridDetailModel detailModel = new GridDetailModel(item, null, GridCustomColumnStruct.BaseDetailGridView);
DataTable gridColumns = ReportImpl.GetReportDetailColumns(DataModel.TopSysModel.ModuleCode, item["id"] + "");//获取报表明细列
detailModel.GridColumns = gridColumns;
if (detailModel.Orderid == -1)//序号为-1固定配置右键
{
string moduleCode = detailModel.UnionModule;
DataModel.RightDetailModel = detailModel;
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
{
detailsTablist.Add(detailModel);
}
}
tabBottom.Model = DataModel.TopSysModel;
tabBottom.InitTabPages(detailsTablist);
this.isAddBottom = detailsTablist.Where(o => o.displayMode != 1 && o.rightVisible != 1 && o.Orderid == -2).ToList().Count > 0;
//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);
//}
}
}
/// <summary>
/// 设置数据
/// </summary>
public void SetControlData()
{
}
/// <summary>
/// 初始化控件
/// </summary>
public void InitControlView()
{
//搜索控件
bool fixedQuery = DataModel.TopSearchTab == null || DataModel.TopSearchTab.Rows.Count == 0;
TreeMultiHeader = DataModel.TopModuleModel.TreeAutoMultiHeader == 1;
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<System.Windows.Forms.Control>().Max(n => n.Location.X + n.Width) + 5;
}
//构建树表格
if (TreeMultiHeader)//若为多表头树表格模式
{
treebandGcTop.Expansion = "3";
treebandGcTop.Model = DataModel.TopSysModel;
treebandGcTop.moduleModel = DataModel.TopModuleModel;
treebandGcTop.SetEditColumns(DataModel.TopGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.TopModuleModel.FormKey);
treebandGcTop.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.ModeCode), DataModel.TopSysModel, this.OnGridViewRightCallBack);
treebandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.ModeCode));
bandGcTop.Visible = false;
}
else
{
//上方表格
bandGcTop.Model = DataModel.TopSysModel;
bandGcTop.SetEditColumns(DataModel.TopGridColumns, GridCustomColumnStruct.BaseMainGridView + DataModel.TopModuleModel.FormKey);
bandGcTop.SetGridRightMenus(BaseModuleImpl.GetBaseGridRightMenus(DataModel.TopModuleModel.ModeCode), DataModel.TopSysModel, this.OnGridViewRightCallBack);
bandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.ModeCode));
bandGcTop.SetGridRowColors(BaseModuleImpl.GetBaseGridRowColors(DataModel.TopModuleModel.ModeCode));
treebandGcTop.Visible = false;
}
if (TreeMultiHeader)
{
AddDataColumns(treebandGcTop);
}
else
{
AddDataColumns(bandGcTop);
}
if (DataModel.TopModuleModel.HasReport)
{
flowLayoutPanel.Visible = false;
}
if (isAddBottom)
{
GridControlEx gridControl = tabBottom.TabControlObj.TabPages[0].Tag as GridControlEx;
bandGcBottom = gridControl as BandedGridControlEx;
AddDataColumns(bandGcBottom);
foreach (GridBand gridBand in bandGcBottom.BandedView.Bands)
{
gridBand.OptionsBand.AllowSize = false;
foreach (BandedGridColumn bandedGridColumn in gridBand.Columns)
{
bandedGridColumn.OptionsColumn.AllowSize = false;
}
}
if (TreeMultiHeader)
{
OnBandedViewColumnWidthChanged(treebandGcTop.TreeListObj, null);
}
else
{
OnBandedViewColumnWidthChanged(bandGcTop.BandedView, null);
}
}
if (tabBottom.TabControlObj.TabPages.Count == 0)
{
splitLeftControl.PanelVisibility = DevExpress.XtraEditors.SplitPanelVisibility.Panel1;
}
//右侧表格
if (!string.IsNullOrEmpty(DataModel.RightSysModel.ModuleCode))
{
DataRow moduleInformation = MainImpl.GetSystemdllTab(DataModel.RightSysModel.ModuleCode);
if (moduleInformation == null)
{
MessageUtil.Show("没有找到编号为" + DataModel.RightSysModel.ModuleCode + "的模块信息");
return;
}
DataModel.RightDetailModel.SystemModel = new ModuleModel(moduleInformation);
gcRight.OnSaveGridCallBack += OnDetailSaveGridCallBack;
gcRight.Name = "gridEx";
gcRight.IsDetail = true;
gcRight.Dock = DockStyle.Fill;
gcRight.OperShortMode = false; // 不显示简短模式
gcRight.VisibleSearchPanel = false;
DataTable rightDt = BaseModuleImpl.GetBaseGridRightMenus(DataModel.RightSysModel.ModuleCode, ModuleType.MrpClickBtn);
gcRight.VisibleOperPanel = !DataModel.RightDetailModel.IsReadOnly;
gcRight.InitializeControl(DataModel.RightDetailModel.SystemModel, DataModel.RightSysModel);
gcRight.GridControlObj.Tag = DataModel.RightDetailModel;
if (DataModel.RightDetailModel.IsCheck == 1)//加载复选框
{
GridDragGrid.GridAddCheckBox(gcRight.GridControlObj.GridView);
}
}
}
/// <summary>
/// 右侧表格保存回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDetailSaveGridCallBack(object sender, EventArgs e)
{
DataModel.TopSearchObj.ButtonObj.PerformClick();
}
/// <summary>
/// 绑定控件事件
/// </summary>
public void InitControlEvents()
{
splitLeftControl.SplitterPositionChanged += OnSplitContainerPositionChanged;
splitMainControl.SplitterPositionChanged += OnSplitContainerPositionChanged;
DataModel.TopSearchObj.OnDataSourceBindCallBack += OnDataSourceBindCallBack;
DataModel.TopSearchObj.OnSearchBeforeCallBack += OnSearchBeforeCallBack; ;
DataModel.TopSearchObj.OnSearchAfterCallBack += OnSearchAfterCallBack;
if (bandGcBottom != null)
{
bandGcBottom.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged;
bandGcBottom.BandedView.CustomDrawColumnHeader += OnCustomDrawColumnHeader;
}
if (TreeMultiHeader)
{
// 改为TreeList的事件绑定
treebandGcTop.TreeListObj.BandWidthChanged += OnBandedViewColumnWidthChanged;
treebandGcTop.TreeListObj.ColumnWidthChanged += OnBandedViewColumnWidthChanged; // 宽度改变事件
treebandGcTop.TreeListObj.LeftCoordChanged += OnBandedViewLeftCoordChanged; // 水平滚动事件
treebandGcTop.TreeListObj.FocusedNodeChanged += OnFocusedNodeChanged; // 单元格点击事件
treebandGcTop.TreeListObj.KeyDown += OnTreeListKeyDown; // 键盘事件
treebandGcTop.TreeListObj.CustomDrawFooterCell += OnTreeListCustomDrawFooterCell; // 自定义绘制Footer事件
treebandGcTop.TreeListObj.CustomDrawColumnHeader += OnTreeListCustomDrawColumnHeader; // 自定义绘制列头事件
treebandGcTop.TreeListObj.ShowingEditor += OnTreeListShowingEditor; // 编辑器显示前事件
treebandGcTop.TreeListObj.InvalidValueException += OnInvalidValueException; ;
}
else
{
bandGcTop.BandedView.BandWidthChanged += OnBandedViewColumnWidthChanged;
bandGcTop.BandedView.ColumnWidthChanged += OnBandedViewColumnWidthChanged;
bandGcTop.BandedView.LeftCoordChanged += OnBandedViewLeftCoordChanged;
bandGcTop.BandedView.RowCellClick += OnBandedViewRowCellClick;
bandGcTop.BandedView.KeyDown += OnBandedViewKeyDown;
bandGcTop.BandedView.CustomDrawFooterCell += OnCustomDrawFooterCell;
bandGcTop.BandedView.CustomDrawColumnHeader += OnCustomDrawColumnHeader;
bandGcTop.BandedView.ShowingEditor += OnShowingEditor;
bandGcTop.BandedView.InvalidValueException += OnInvalidValueException;
}
btnSave.Click += OnBtnSaveClick;
}
/// <summary>
/// 判断单元格是否可以编辑
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnRightShowingEditor(object sender, CancelEventArgs e)
{
var view = sender as GridView;
if (view == null) return;
DataRow row = gcRight.GridControlObj.GetViewFocusedDataRow();
if (row == null) { e.Cancel = true; return; } // 没有行也不让编辑
// —— 1. 解析 day 字段 ——
if (!DateTime.TryParse(row["day"]?.ToString(), out DateTime dayDate))
{
e.Cancel = true; // 无法解析日期 → 禁止编辑
return;
}
// —— 2. 超过 7 天的行不可编辑 ——
if (dayDate.AddDays(7) <= DateTime.Today)
{
e.Cancel = true;
return;
}
}
/// <summary>
/// 判断单元格是否可以编辑
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnShowingEditor(object sender, CancelEventArgs e)
{
BandedGridView view = sender as BandedGridView;
if (view == null) return;
if (DataModel.TopModuleModel.HasReport)//报表所有的都不能编辑
{
e.Cancel = true; // 取消编辑,单元格变灰
}
DataRow dataRow = view.GetFocusedDataRow();
if (dataRow == null) return;
string bj_tig = dataRow["bj_tig"]?.ToString() ?? "";
if (bj_tig == "0")
{
e.Cancel = true; // 取消编辑,单元格变灰
}
else
{
string billDocumentId = view.GetRowCellValue(view.FocusedRowHandle, DataModel.TopModuleModel.ParmaryKey) + "";
// 新方式 (精准替代原有取值方式)
DateTime date;
if (DataModel.columnDateMapping.TryGetValue(view.FocusedColumn, out date))
{
string columnName = date.ToString("yyyy-MM-dd");
// 检查该行的 billdocument_id 是否在字典中
if (DataModel.nonEditableCells.ContainsKey(billDocumentId))
{
HashSet<string> showDays = DataModel.nonEditableCells[billDocumentId];
// 如果列名(日期)在 showday_list 里,则禁用编辑
if (showDays.Contains(columnName))
{
e.Cancel = true; // 取消编辑,单元格变灰
}
}
}
}
}
/// <summary>
/// 判断TreeList单元格是否可以编辑(精准适配原BandedGridView逻辑)
/// </summary>
private void OnTreeListShowingEditor(object sender, CancelEventArgs e)
{
if (DataModel.TopModuleModel.HasReport)//报表所有的都不能编辑
{
e.Cancel = true; // 取消编辑,单元格变灰
}
TreeList treeList = sender as TreeList;
string bj_tig = treeList.FocusedNode.GetValue("bj_tig")?.ToString() ?? "";
if (treeList == null || treeList.FocusedNode == null) return;
if (bj_tig == "0")
{
e.Cancel = true; // 取消编辑,单元格变灰
}
else
{
string billDocumentId = treeList.FocusedNode.GetValue(DataModel.TopModuleModel.ParmaryKey)?.ToString() ?? "";
DateTime date;
if (DataModel.columnDateMapping.TryGetValue(treeList.FocusedColumn, out date))
{
string columnName = date.ToString("yyyy-MM-dd");
// 检查该行的 billdocument_id 是否在字典中
if (DataModel.nonEditableCells.ContainsKey(billDocumentId))
{
HashSet<string> showDays = DataModel.nonEditableCells[billDocumentId];
// 如果列名(日期)在 showday_list 里,则禁用编辑
if (showDays.Contains(columnName))
{
e.Cancel = true; // 取消编辑,单元格变灰
}
}
}
}
}
/// <summary>
/// 保存按钮点击时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBtnSaveClick(object sender, EventArgs e)
{
if (TreeMultiHeader)
{
treebandGcTop.GridView.PostEditor();
}
else
{
bandGcTop.BandedView.PostEditor();
}
if (!string.IsNullOrEmpty(DataModel.TopModuleModel.MenuTable))
{
SaveGridRecord();
}
if (SaveDatePlanRecord())
{
DataModel.TopSearchObj.ButtonObj.PerformClick();
}
}
/// <summary>
/// 保存主表数据
/// </summary>
/// <param name="isErrorTips"></param>
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<BaseSaveModel> mList = new List<BaseSaveModel>();
DataTable dataTable = TreeMultiHeader ? treebandGcTop.GetGridViewDataSource() : bandGcTop.BandedView.GridControl.DataSource as DataTable;
DataRow[] modifiedRows = dataTable
.Rows
.Cast<DataRow>()
.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<DataRow>().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;
}
}
}
/// <summary>
/// 保存日期数据
/// </summary>
private bool SaveDatePlanRecord()
{
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().FirstOrDefault(); // 获取第一个符合条件的控件
string typeDate = "0";
if (dataTypeControl != null)
{
LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit;
typeDate = labelAutoTextEdit.EditValue;
}
// 获取主数据源,假设已绑定到 gridControl1
DataTable mainDataSource = TreeMultiHeader ? treebandGcTop.GetGridViewDataSource() : 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, typeDate, out msg);
if (ret == 1)
{
MessageUtil.Show("保存成功:" + msg);
return true;
}
else
{
MessageUtil.Show("保存失败:" + msg);
return false;
}
}
/// <summary>
/// 保存日计划变更数据(批量保存)。
/// 调用存储过程 usp_MergeDayPlanChanges,将所有变更记录一次性提交到数据库。
/// 通过 TVP 参数传递数据,同时捕获输出参数 @msg 和返回值。
/// </summary>
/// <param name="tvp">包含所有变更记录的 DataTable,必须与 dbo.DayPlanChangeType 定义一致</param>
/// <param name="message">输出提示信息,存储过程执行后的返回消息</param>
/// <returns>存储过程返回值,成功返回 1,失败返回 0</returns>
public int SaveDayPlanChanges(DataTable tvp, string typeDate, 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
};
// 创建 typeDate 参数并传入存储过程
SqlParameter typeDateParam = new SqlParameter("@TypeDate", SqlDbType.VarChar, 10)
{
Value = typeDate
};
// 构造参数数组
SqlParameter[] parameters = new SqlParameter[] { tvpParam, typeDateParam, pMsg, returnValue };
// 执行存储过程,此处调用 ExecuteNonQuery 即可,不需要返回数据集
// 请确保 BaseImpl.ExecProcedure 方法能够传递参数并执行存储过程
BaseImpl.ExecProcedure("usp_MergeDayPlanChanges", parameters);
// 获取输出参数 @msg 中的提示信息
message = pMsg.Value.ToString();
// 获取存储过程的返回值
int result = Convert.ToInt32(returnValue.Value);
return result;
}
/// <summary>
/// 单元格点击刷新当前行数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBandedViewRowCellClick(object sender, RowCellClickEventArgs e)
{
try
{
GridDetailModel model = DataModel.RightDetailModel;
DataRow rowItem = bandGcTop.BandedView.GetFocusedDataRow();
if (rowItem != null)
{
BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<BaseUserControl>().Where(n => n is LabelDateEdit).FirstOrDefault();
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().FirstOrDefault(); // 获取第一个符合条件的控件
string typeDate = "0";
LabelDateEdit labelDateEdit = null;
if (baseUserControl != null)
{
labelDateEdit = baseUserControl as LabelDateEdit;
}
if (dataTypeControl != null)
{
LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit;
typeDate = labelAutoTextEdit.EditValue;
}
string searchSql = this.GetSearchSql(model, rowItem, false);
string isweekcond = DataModel.TopModuleModel.HasReport ? "" : $"and isWeek='{typeDate}'";
searchSql = $"{ReplaceHelper.ReplaceWhereCond(searchSql)} and day >= '{labelDateEdit.TextEdit.DateTime.ToString("yyyy-MM-dd")}' {isweekcond}";
gcRight.GridControlObj.LastSearchSql = searchSql;
// 4) 让 Grid 用这张表,并把 adapter 存起来
gcRight.GridControlObj.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql));
if (e != null)
{
if (labelDateEdit != null)
{
DateTime dateTime = labelDateEdit.TextEdit.DateTime;
DataRow focusedRow = bandGcTop.BandedView.GetFocusedDataRow();
DataTable dataDayPlan = gcRight.GridControlObj.GridControl.DataSourceTable().Copy();
if (DataModel.TopModuleModel.HasReport) UpdateRowWithDayPlan(focusedRow, dataDayPlan, dateTime);
}
}
this.SetDetailGridDataSource(rowItem);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// TreeList聚焦节点改变刷新当前行数据(精确移植原点击事件逻辑)
/// </summary>
private void OnFocusedNodeChanged(object sender, FocusedNodeChangedEventArgs e)
{
try
{
GridDetailModel model = DataModel.RightDetailModel;
if (e.Node != null)
{
DataRow rowItem = (treebandGcTop.TreeListObj.GetDataRecordByNode(e.Node) as DataRowView)?.Row;
if (rowItem != null)
{
BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls
.Cast<BaseUserControl>()
.FirstOrDefault(n => n is LabelDateEdit);
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls
.Cast<System.Windows.Forms.Control>()
.FirstOrDefault(n => n is LabelComboxEdit) as BaseUserControl;
string typeDate = "0";
LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit;
if (dataTypeControl != null && dataTypeControl is LabelComboxEdit labelAutoTextEdit)
{
typeDate = labelAutoTextEdit.EditValue;
}
if (labelDateEdit == null) return;
string searchSql = this.GetSearchSql(model, rowItem, false);
string isweekcond = DataModel.TopModuleModel.HasReport ? "" : $"and isWeek='{typeDate}'";
searchSql = $"{ReplaceHelper.ReplaceWhereCond(searchSql)} and day >= '{labelDateEdit.TextEdit.DateTime:yyyy-MM-dd}' {isweekcond}";
gcRight.GridControlObj.SetGridViewDataSource(BaseImpl.GetDataTableResult(searchSql));
// 更新行数据逻辑
DateTime dateTime = labelDateEdit.TextEdit.DateTime;
DataTable dataDayPlan = gcRight.GridControlObj.GridControl.DataSourceTable().Copy();
if (DataModel.TopModuleModel.HasReport) UpdateRowWithDayPlan(rowItem, dataDayPlan, dateTime);
this.SetDetailGridDataSource(rowItem);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// <para>说明:下面多数据源刷新</para>
/// <para>创建人:王一帆</para>
/// <para>创建日期:2017-12-19 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
public void SetDetailGridDataSource(DataRow rowItem, XtraTabPage tabPage = null)
{
if (tabPage != null)
{
this.SetTabPageDataSource(tabPage, rowItem);
}
else
{
foreach (XtraTabPage page in this.tabBottom.TabControlObj.TabPages)
{
if (rowItem != null && page != null)
{
this.SetTabPageDataSource(page, rowItem);
}
}
}
}
protected void SetTabPageDataSource(XtraTabPage tabPage, DataRow rowItem)
{
GridDetailModel model = this.tabBottom.GetGridDetailModel(tabPage);
if (model.Orderid == -2) return;
Object moduleObject = tabPage.Controls.Cast<Object>().FirstOrDefault();
ModuleGridEx moduleGridEx = null;
if (moduleObject is ModuleGridEx)
{
moduleGridEx = moduleObject as ModuleGridEx;
}
if (rowItem != null && model != null)
{
if (!string.IsNullOrEmpty(model.UnionModule) && (string.IsNullOrEmpty(model.UnionValue) && string.IsNullOrEmpty(model.UnionCond))) return;
if (tabPage.Tag is FrmWebBrowser)
{
// 加载网页
FrmWebBrowser webView = tabPage.Tag as FrmWebBrowser;
string url = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(model.DetailSql));
url = url.StartsWith("http") ? url : SystemInfo.Instance.OAUrl + url;
//webView.FrmLoad(url);
webView.LoadUrl(url);
webView.Dock = DockStyle.Fill;
webView.Tag = model;
}
else if (tabPage.Tag is FrmWebBrowser2)
{
// 加载网页
FrmWebBrowser2 webView = tabPage.Tag as FrmWebBrowser2;
string url = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(model.DetailSql));
url = url.StartsWith("http") ? url : SystemInfo.Instance.OAUrl + url;
webView.LoadUrl(url);
webView.Dock = DockStyle.Fill;
webView.Tag = model;
}
else if (tabPage.Tag is FrmMiniBlink)
{
// 加载网页
FrmMiniBlink webView = tabPage.Tag as FrmMiniBlink;
string url = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(model.DetailSql));
url = url.StartsWith("http") ? url : SystemInfo.Instance.OAUrl + url;
webView.LoadUrl(url);
webView.Dock = DockStyle.Fill;
webView.Tag = model;
}
else if (tabPage.Tag is TabMultipledetails)
{
TabMultipledetails tabMultipledetails = tabPage.Tag as TabMultipledetails;
tabMultipledetails.SetConditionValues(rowItem);
GridControlEx grdExMain = (tabMultipledetails.SplitMain.Panel1.Tag as GridControlEx);
GridDetailModel MainModel = grdExMain.Tag as GridDetailModel;
string searchMainSql = this.GetSearchSql(MainModel, rowItem);
DataTable firstTable = MainImpl.GetDataTableResult(searchMainSql);
grdExMain.LastSearchSql = searchMainSql;
grdExMain.SetGridViewDataSource(firstTable);
if (tabMultipledetails.SplitMain.Panel2.Tag is GridControlEx)
{
GridControlEx grdExAdditional = (tabMultipledetails.SplitMain.Panel2.Tag as GridControlEx);
GridDetailModel AdditionalModel = grdExAdditional.Tag as GridDetailModel;
string searchAddSql = this.GetSearchSql(AdditionalModel, rowItem);
if (!MainModel.IsUnioDetail)
{
grdExAdditional.LastSearchSql = searchAddSql;
grdExAdditional.SetGridViewDataSource(MainImpl.GetDataTableResult(searchAddSql));
}
//右侧是左侧的明细,左侧没有数据时。右侧赋空值(因为无法触发左侧行改变事件)
if (MainModel.IsUnioDetail && firstTable.Rows.Count == 0)
{
grdExAdditional.LastSearchSql = "";
grdExAdditional.SetGridViewDataSource(new DataTable());
}
}
else if (tabMultipledetails.SplitMain.Panel2.Tag is ChartControlEx)
{
ChartControlEx grdExAdditional = (tabMultipledetails.SplitMain.Panel2.Tag as ChartControlEx);
GridDetailModel AdditionalModel = grdExAdditional.Tag as GridDetailModel;
string searchAddSql = this.GetSearchSql(AdditionalModel, rowItem);
DataTable table = MainImpl.GetDataTableResult(searchAddSql);
grdExAdditional.CreateChart(table);
}
tabPage.Text = MainModel.DetailName + "(" + firstTable.Rows.Count + "条)";
tabPage.Appearance.Header.ForeColor = firstTable.Rows.Count > 0 ? Color.Red : Color.FromArgb(0, 0, 0);
}
else
{
if (model.IsDrag)
{
return;
}
string searchSql = this.GetSearchSql(model, rowItem);
if (tabPage.Tag is GridControlEx)
{
(tabPage.Tag as GridControlEx).LastSearchSql = searchSql;
}
//DataTable dataTable = MainImpl.GetDataTableResult(searchSql);//明细数据源
if (model.DynamicDetails && rowItem.Table.Columns.Contains("DisplayColumns")) //
{
this.tabBottom.SetGridDisplayColumns(tabPage, rowItem["DisplayColumns"] + "");
}
this.tabBottom.SetGridDataSource(tabPage, MainImpl.GetDataTableResult(searchSql));
if (tabPage.Tag is GridControlEx && (tabPage.Tag as GridControlEx).ParentControl != null)
(tabPage.Tag as GridControlEx).ParentControl.SetAllControlValue(rowItem);
//配置明细直接根据条件加载
if (model.SystemModel != null && 1 == model.SystemModel.isFirstLoad)
{
(tabPage.Tag as GridControlEx).ParentControl.SearchGrid();
tabPage.Text = model.DetailName + "(" + (tabPage.Tag as GridControlEx).ParentControl.GridRowCount + "条)";
}
}
if (moduleGridEx != null) moduleGridEx.ParentButtonState(rowItem);
}
}
/// <summary>
/// 获取查询sql
/// </summary>
/// <param name="model"></param>
/// <param name="rowItem"></param>
/// <param name="isLeft"></param>
/// <returns></returns>
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.Orderid == -1 ? DataModel.RightModuleModel.MenuSql : model.IsReadOnly || model.IsChart ? model.DetailSql : model.SystemModel.MenuSql;
sqlValue = ReplaceHelper.ReplaceRowParam(rowItem, sqlValue);
DataRow row = TreeMultiHeader ? treebandGcTop.GetViewFocusedDataRow() : 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;
}
/// <summary>
/// 宽度改变事件处理,兼容BandedGridView和TreeList
/// </summary>
private void OnBandedViewColumnWidthChanged(object sender, EventArgs e)
{
if (bandGcBottom != null)
{
int allWidth = 0;
// 如果sender为原有的BandedView类型
if (sender == bandGcTop.BandedView)
{
foreach (GridBand gridBand in bandGcTop.BandedView.Bands)
{
if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_"))
{
break;
}
else
{
allWidth += gridBand.Width;
}
}
}
// 如果sender为TreeList类型
else if (sender is TreeList treeListSender)
{
foreach (TreeListBand band in treeListSender.Bands)
{
if (band.Columns.Count == 1 && band.Columns[0].Name.Contains("DDay_"))
{
break;
}
else
{
foreach (TreeListColumn treeListColumn in band.Columns)
{
if (treeListColumn.Visible) allWidth += treeListColumn.Width;
}
}
}
}
else
{
return; // 非预期sender类型时直接退出
}
// 调整底部bandGcBottom的列宽(始终为BandedGridView类型)
List<BandedGridColumn> bottomColumnList = new List<BandedGridColumn>();
foreach (GridBand gridBand in bandGcBottom.BandedView.Bands)
{
if (gridBand.Columns.Count == 1 && gridBand.Columns[0].Name.Contains("DDay_"))
{
break;
}
else
{
bottomColumnList.AddRange(gridBand.Columns.Cast<BandedGridColumn>());
}
}
// 按计算好的宽度均分调整
if (bottomColumnList.Count > 0)
{
int perWidth = allWidth / bottomColumnList.Count;
foreach (BandedGridColumn bandedGridColumn in bottomColumnList)
{
bandedGridColumn.Width = perWidth;
}
}
}
}
/// <summary>
/// 水平滚动条改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBandedViewLeftCoordChanged(object sender, EventArgs e)
{
if (!isAddBottom) return;
if (sender == bandGcTop.BandedView)
{
bandGcBottom.BandedView.LeftCoord = bandGcTop.BandedView.LeftCoord;
}
else if (sender is TreeList treeListSender)
{
// 使用TreeList的LeftCoord属性同步BandedView的LeftCoord
bandGcBottom.BandedView.LeftCoord = treeListSender.LeftCoord;
}
else if (sender == bandGcBottom.BandedView)
{
if (TreeMultiHeader)
{
treebandGcTop.TreeListObj.LeftCoord = bandGcBottom.BandedView.LeftCoord;
}
else
{
bandGcTop.BandedView.LeftCoord = bandGcBottom.BandedView.LeftCoord;
}
}
}
/// <summary>
/// 记录展开的节点
/// </summary>
public void GetTreeExpanded()
{
DataModel.treeListNodes.Clear();
foreach (TreeListNode n in this.treebandGcTop.TreeListObj.Nodes)
{
setRecursive(n);
}
}
/// <summary>
/// 递归进行遍历节点
/// </summary>
/// <param name="treeNode"></param>
public void setRecursive(TreeListNode treeNode)
{
if (treeNode.Expanded) DataModel.treeListNodes.Add(treeNode);
// Visit each node recursively.
foreach (TreeListNode tn in treeNode.Nodes)
{
setRecursive(tn);
}
}
/// <summary>
/// 搜索条件绑定完成后
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDataSourceBindCallBack(object sender, EventArgs e)
{
BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<BaseUserControl>().Where(n => n is LabelDateEdit).FirstOrDefault();
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().FirstOrDefault(); // 获取第一个符合条件的控件
string typeDate = "0";
if (dataTypeControl != null)
{
LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit;
typeDate = labelAutoTextEdit.EditValue;
}
if (baseUserControl != null)
{
LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit;
DateTime dateTime = labelDateEdit.TextEdit.DateTime;
if (isAddBottom) UpdateDynamicColumns(bandGcBottom, dateTime, typeDate);
if (TreeMultiHeader)
{
UpdateDynamicColumns(treebandGcTop, dateTime, typeDate);
}
else
{
UpdateDynamicColumns(bandGcTop, dateTime, typeDate);
}
}
}
/// <summary>
/// 搜索前事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSearchBeforeCallBack(object sender, SearchArgs e)
{
if (TreeMultiHeader)
{
DataModel.MainLeftCoord = treebandGcTop.TreeListObj.LeftCoord;
}
else
{
DataModel.MainLeftCoord = bandGcTop.BandedView.LeftCoord;
}
}
/// <summary>
/// 搜索后事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSearchAfterCallBack(object sender, EventArgs e)
{
BaseUserControl baseUserControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<BaseUserControl>().Where(n => n is LabelDateEdit).FirstOrDefault();
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().FirstOrDefault(); // 获取第一个符合条件的控件
string typeDate = "0";
if (dataTypeControl != null)
{
LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit;
typeDate = labelAutoTextEdit.EditValue;
}
if (baseUserControl != null)
{
LabelDateEdit labelDateEdit = baseUserControl as LabelDateEdit;
if (typeDate == "1")
{
DateTime endDate = labelDateEdit.TextEdit.DateTime.AddMonths(3).AddDays(-1); // 计算结束日期
int weekIndex = 0;
DateTime weekStart = GetStartOfWeek(labelDateEdit.TextEdit.DateTime); // 获取本周的周一日期
labelDateEdit.TextEdit.DateTime = weekStart;
}
DateTime dateTime = labelDateEdit.TextEdit.DateTime;
if (TreeMultiHeader)
{
UpdateDynamicColumns(treebandGcTop, dateTime, typeDate);
}
else
{
UpdateDynamicColumns(bandGcTop, dateTime, typeDate);
}
if (isAddBottom) UpdateDynamicColumns(bandGcBottom, dateTime, typeDate);
DataTable dataMain = null;
DataTable dataDetail = null;
int hander = bandGcTop.BandedView.FocusedRowHandle;
if (TreeMultiHeader)
{
dataMain = treebandGcTop.GetGridViewDataSource().Copy();
dataDetail = treebandGcTop.GetGridViewDataSource().Copy();
//treebandGcTop.TreeListObj.DataSource = null;
}
else
{
dataMain = bandGcTop.GridControl.DataSourceTable().Copy();
dataDetail = bandGcTop.GridControl.DataSourceTable().Copy();
bandGcTop.GridControl.DataSource = null;
}
string sqlValue = DataModel.RightModuleModel.MenuSql;
string isweekcond = DataModel.TopModuleModel.HasReport ? "" : $"and isWeek='{typeDate}'";
sqlValue = $"{ReplaceHelper.ReplaceWhereCond(sqlValue)} and day >= '{dateTime.ToString("yyyy-MM-dd")}' {isweekcond}";
DataTable dataDayPlan = BaseImpl.GetDataTableResult(sqlValue);
if (isAddBottom)
{
DataTable bottomTab = BuildCTable(dataDetail, dataDayPlan, dateTime, 93);
bandGcBottom.BandedView.GridControl.DataSource = bottomTab;
}
MergeMainDataWithDayPlan(dataMain, dataDayPlan, dateTime, typeDate);
if (!TreeMultiHeader)
{
bandGcTop.BandedView.GridControl.DataSource = dataMain;
bandGcTop.BandedView.FocusedRowHandle = hander;
OnBandedViewRowCellClick(bandGcTop.BandedView, null);
bandGcTop.BandedView.LeftCoord = DataModel.MainLeftCoord;
}
else
{
treebandGcTop.SetGridViewDataSource(dataMain);
treebandGcTop.TreeListObj.LeftCoord = DataModel.MainLeftCoord;
}
}
string query = @"
SELECT
billdocument_id,
STUFF((SELECT ',' + CAST(showday AS VARCHAR(MAX))
FROM mps_dayplantab AS sub WITH(NOLOCK)
WHERE sub.billdocument_id = main.billdocument_id
AND sub.update_tig = 1
FOR XML PATH('')), 1, 1, '') AS showday_list
FROM mps_dayplantab AS main WITH(NOLOCK)
GROUP BY billdocument_id;";
DataTable dt = BaseImpl.GetDataTableResult(query);
foreach (DataRow row in dt.Rows)
{
string billDocumentId = row["billdocument_id"] + "";
string showDayList = row["showday_list"].ToString();
if (!string.IsNullOrEmpty(showDayList))
{
HashSet<string> daysSet = new HashSet<string>(showDayList.Split(','));
DataModel.nonEditableCells[billDocumentId] = daysSet;
}
}
}
/// <summary>
/// 获取数据源缓存
/// </summary>
/// <param name="cachesDic"></param>
/// <param name="dynamicModel"></param>
public void GetDataCaches(Dictionary<object, Hashtable> cachesDic)
{
//获取通用数据
Task<ModuleModel> sysModelTask = cachesDic.GetTask<ModuleModel>(this, "SysModel");
Task<DynamicModel> dynamicModelTask = cachesDic.GetTask<DynamicModel>(this, "DynamicModel");
Task<List<GridDetailModel>> detailsTask = cachesDic.GetTask<List<GridDetailModel>>(this, "Details");
Task<bool> getDataCachesTask = cachesDic.AddTask(this, "DataCaches", new Task<bool>(() =>
{
ModuleModel sysModel = sysModelTask.Result;
DynamicModel dynamicModel = dynamicModelTask.Result;
//创建数据
if (sysModel != null && dynamicModel != null)
{
Task<DataRow> menuConfigTabTask = cachesDic.AddTask(this, "MenuConfigTab", new Task<DataRow>(() =>
{
return BaseImpl.GetMenuConfigTab(dynamicModel.ModuleId); //获取菜单其他配置
}));
if (dynamicModel is DynamicExcelModel)//isExcel
{
Task<string> basePrimaryKeyTask = cachesDic.AddTask(this, "BasePrimaryKey", new Task<string>(() =>
{
return BaseImpl.GetBasePrimaryKey(dynamicModel.ModuleCode);
}));
Task<DataTable> gridColumnsTask = cachesDic.AddTask(this, "GridColumns", new Task<DataTable>(() =>
{
return BaseModuleImpl.GetBaseGridColumns(dynamicModel.ModuleCode);
}));
}
else
{
//构建主表数据
}
}
return true;
}));
}
/// <summary>
/// 添加虚拟日期列
/// </summary>
private void AddDataColumns(BandedGridControlEx bandedGridControlEx)
{
if (bandedGridControlEx == bandGcTop)
{
bandedGridControlEx.BandedView.OptionsView.ShowFooter = false;
}
foreach (GridBand gridBand in bandedGridControlEx.BandedView.Bands)
{
gridBand.Fixed = DevExpress.XtraGrid.Columns.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;
gridBand.AppearanceHeader.TextOptions.WordWrap = WordWrap.Wrap;
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 = DevExpress.Data.SummaryItemType.Sum;
gridColumn.SummaryItem.DisplayFormat = "{0:#,##0.####}";
}
gridBand.Columns.Add(gridColumn);
}
// 现在添加15个周列
for (int i = 93; i < 108; i++) // 新增15个周列
{
GridBand gridBand = new GridBand();
gridBand.Name = $"Week_{i - 93}";
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;
gridBand.AppearanceHeader.TextOptions.WordWrap = WordWrap.Wrap;
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 = $"WWeek_{i - 93}";
gridColumn.Width = 105;
gridColumn.DisplayFormat.FormatType = FormatType.Numeric;
gridColumn.DisplayFormat.FormatString = "{0:#,##0.####}";
gridColumn.Visible = false;
if (bandedGridControlEx == bandGcTop)
{
gridColumn.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum;
gridColumn.SummaryItem.DisplayFormat = "{0:#,##0.####}";
}
gridBand.Columns.Add(gridColumn);
}
}
/// <summary>
/// 添加多表头树结构模式的虚拟日期列(基于TreeList)
/// </summary>
/// <summary>
/// 添加虚拟日期列(树的多表头模式)
/// </summary>
/// <summary>
/// 添加虚拟日期列(树的多表头模式)
/// </summary>
private void AddDataColumns(TreeBandedGridControlEx bandedGridControlEx)
{
// 核心优化代码:暂停数据源绑定和界面刷新
bandedGridControlEx.TreeListObj.BeginUpdate();
bandedGridControlEx.TreeListObj.LockReloadNodes(); // 阻止节点数据重载(关键优化)
try
{
if (bandedGridControlEx == treebandGcTop)
{
bandedGridControlEx.TreeListObj.OptionsView.ShowSummaryFooter = false;
}
foreach (TreeListBand fixedBand in bandedGridControlEx.TreeListObj.Bands)
{
fixedBand.Fixed = DevExpress.XtraTreeList.Columns.FixedStyle.Left;
}
// 添加93个日列
for (int i = 0; i < 93; i++)
{
TreeListBand dayBand = new TreeListBand
{
Name = $"Day_{i}",
Caption = "",
OptionsBand = { AllowMove = false, AllowSize = false },
AppearanceHeader = {
Options = { UseFont = true, UseTextOptions = true },
Font = new Font("宋体", 9, FontStyle.Bold),
TextOptions = { HAlignment = HorzAlignment.Center }
}
};
bandedGridControlEx.TreeListObj.Bands.Add(dayBand);
TreeListColumn dayColumn = new TreeListColumn
{
FieldName = $"DDay_{i}",
Width = 70,
Visible = false,
OptionsColumn = {
AllowMove = false,
AllowSize = false,
AllowSort = false,
AllowEdit = false
},
AppearanceCell = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } },
AppearanceHeader = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } },
Format = { FormatType = FormatType.Numeric, FormatString = "{0:#,##0.####}" }
};
if (bandedGridControlEx == treebandGcTop)
{
dayColumn.AllNodesSummary = true;
dayColumn.SummaryFooter = DevExpress.XtraTreeList.SummaryItemType.Sum;
dayColumn.SummaryFooterStrFormat = "{0:#,##0.####}";
}
dayBand.Columns.Add(dayColumn);
bandedGridControlEx.TreeListObj.Columns.Add(dayColumn);
}
// 添加15个周列
for (int i = 93; i < 108; i++)
{
TreeListBand weekBand = new TreeListBand
{
Name = $"Week_{i - 93}",
Caption = "",
OptionsBand = { AllowMove = false, AllowSize = false },
AppearanceHeader = {
Options = { UseFont = true, UseTextOptions = true },
Font = new Font("宋体", 9, FontStyle.Bold),
TextOptions = { HAlignment = HorzAlignment.Center }
}
};
bandedGridControlEx.TreeListObj.Bands.Add(weekBand);
TreeListColumn weekColumn = new TreeListColumn
{
FieldName = $"WWeek_{i - 93}",
Width = 105,
Visible = false,
OptionsColumn = {
AllowMove = false,
AllowSize = false,
AllowSort = false,
AllowEdit = false
},
AppearanceCell = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } },
AppearanceHeader = { TextOptions = { HAlignment = HorzAlignment.Center }, Options = { UseTextOptions = true } },
Format = { FormatType = FormatType.Numeric, FormatString = "{0:#,##0.####}" }
};
if (bandedGridControlEx == treebandGcTop)
{
weekColumn.AllNodesSummary = true;
weekColumn.SummaryFooter = DevExpress.XtraTreeList.SummaryItemType.Sum;
weekColumn.SummaryFooterStrFormat = "{0:#,##0.####}";
}
weekBand.Columns.Add(weekColumn);
//bandedGridControlEx.TreeListObj.Columns.Add(weekColumn);
}
}
finally
{
bandedGridControlEx.TreeListObj.UnlockReloadNodes(); // 重新允许节点加载数据
bandedGridControlEx.TreeListObj.EndUpdate(); // 一次性完成所有刷新
}
}
/// <summary>
/// 创建TreeList统一的列
/// </summary>
private TreeListColumn CreateTreeListColumn(string fieldName, int width)
{
var column = new TreeListColumn
{
Name = $"col_{fieldName}",
FieldName = fieldName,
Caption = fieldName,
Width = width,
Visible = true,
OptionsColumn =
{
AllowMove = false,
AllowSize = false,
AllowSort = false,
AllowEdit = false
},
AppearanceHeader =
{
TextOptions = { HAlignment = HorzAlignment.Center },
Font = new Font("宋体", 9, FontStyle.Bold)
},
AppearanceCell =
{
TextOptions = { HAlignment = HorzAlignment.Center }
},
Format =
{
FormatType = FormatType.Numeric,
FormatString = "{0:#,##0.####}"
}
};
return column;
}
/// <summary>
/// 配置列的汇总项
/// </summary>
private void SetupColumnSummary(TreeListColumn column)
{
column.SummaryFooter = DevExpress.XtraTreeList.SummaryItemType.Sum;
column.SummaryFooterStrFormat = "{0:#,##0.####}";
}
#region 类型切换日期展示方法
/// <summary>
/// 构建带日期或周期
/// </summary>
/// <param name="bandedGridControlEx"></param>
/// <param name="currentDate"></param>
/// <param name="typeDate"></param>
private void UpdateDynamicColumns(BandedGridControlEx bandedGridControlEx, DateTime currentDate, string typeDate = "0")
{
bandedGridControlEx.BandedView.BeginUpdate();
try
{
if (typeDate == "1")
{
UpdateWeeklyColumns(bandedGridControlEx, currentDate);
}
else
{
UpdateDailyColumns(bandedGridControlEx, currentDate);
}
}
finally
{
bandedGridControlEx.BandedView.EndUpdate();
}
}
/// <summary>
/// 更新TreeList控件的动态列
/// </summary>
private void UpdateDynamicColumns(TreeBandedGridControlEx bandedGridControlEx, DateTime currentDate, string typeDate = "0")
{
try
{
if (typeDate == "1")
{
UpdateWeeklyColumns(bandedGridControlEx, currentDate);
}
else
{
UpdateDailyColumns(bandedGridControlEx, currentDate);
}
}
finally
{
}
}
/// <summary>
/// 按周结构生成列(跨月后从第 1 周重新计)
/// </summary>
private void UpdateWeeklyColumns(BandedGridControlEx grid, DateTime currentDate)
{
grid.BandedView.BandPanelRowHeight = 45;
DateTime endDate = currentDate.AddMonths(3).AddDays(-1); // 3 个月窗口
DateTime weekStart = GetStartOfWeek(currentDate); // 本周周一
int weekIndex = 0; // Week_0 ~ Week_14
while (weekStart <= endDate && weekIndex < 15)
{
DateTime weekEnd = weekStart.AddDays(6); // 本周周日
DateTime pivotDate = weekStart.AddDays(3); // —— 周四 —— 归属月份基准
int monthKey = pivotDate.Month; // 本周归属的「月份」
/* ---------- 计算“几月第几周” ---------- */
DateTime monthFirstDay = new DateTime(pivotDate.Year, pivotDate.Month, 1); // 当月1号
DateTime firstWeekStart = GetStartOfWeek(monthFirstDay); // 先找周一
// 若周四不在同月,则循环向后推 1 周,直到周四落在目标月
while (firstWeekStart.AddDays(3).Month != monthKey)
firstWeekStart = firstWeekStart.AddDays(7);
int weekOfMonth = ((weekStart - firstWeekStart).Days / 7) + 1; // 1 起算
/* ---------- 设置 Week_i Band ---------- */
string bandName = $"Week_{weekIndex}";
GridBand weekBand = grid.BandedView.Bands
.Cast<GridBand>()
.FirstOrDefault(b => b.Name == bandName);
if (weekBand != null && weekBand.Columns.Count > 0)
{
BandedGridColumn weekColumn = weekBand.Columns[0];
weekBand.Visible = true;
weekBand.Caption = $"{weekStart:MM.dd}\r\n|\r\n{weekEnd:MM.dd}"; // 父 Band:日期范围
weekColumn.FieldName = weekStart.ToString("yyyy-MM-dd"); // 字段名:周一
weekColumn.Caption = $"{pivotDate.Month}月第{weekOfMonth}周"; // 列标题:几月第几周
weekColumn.Width = 65;
DataModel.columnDateMapping[weekColumn] = weekStart;
weekColumn.OptionsColumn.AllowEdit = weekEnd >= DateTime.Today; // 仅未来可编辑
weekColumn.Visible = true;
}
/* ---------- 移到下一周 ---------- */
weekStart = weekEnd.AddDays(1); // 下周周一
weekIndex++;
}
/* ---------- 隐藏多余 Week_i BandweekIndex ~ 14 ---------- */
for (int i = weekIndex; i < 15; i++)
{
GridBand band = grid.BandedView.Bands
.Cast<GridBand>()
.FirstOrDefault(b => b.Name == $"Week_{i}");
if (band != null) band.Visible = false;
}
/* ---------- 隐藏所有 Day_* 列 ---------- */
foreach (GridBand band in grid.BandedView.Bands.Cast<GridBand>())
{
if (!band.Name.StartsWith("Day_")) continue;
band.Visible = false;
foreach (BandedGridColumn col in band.Columns)
col.Visible = false;
}
}
/// <summary>
/// 更新TreeList控件的周列
/// </summary>
private void UpdateWeeklyColumns(TreeBandedGridControlEx grid, DateTime currentDate)
{
grid.TreeListObj.BeginInit();
DateTime endDate = currentDate.AddMonths(3).AddDays(-1);
int weekIndex = 0;
DateTime weekStart = GetStartOfWeek(currentDate);
while (weekStart <= endDate && weekIndex < 15)
{
DateTime weekEnd = weekStart.AddDays(6);
string bandTitle = $"Week_{weekIndex}";
TreeListBand weekBand = grid.TreeListObj.Bands.Cast<TreeListBand>()
.FirstOrDefault(b => b.Name == bandTitle);
if (weekBand != null && weekBand.Columns.Count > 0)
{
TreeListColumn weekColumn = weekBand.Columns[0];
weekBand.Visible = true;
weekBand.Caption = $"{weekStart:MM-dd}至{weekEnd:MM-dd}";
weekColumn.FieldName = weekStart.ToString("yyyy-MM-dd");
// 使用修改后的方法设置 Caption
weekColumn.Caption = $"{weekEnd.Month}月第{GetWeekOfMonth(weekEnd)}周";
weekColumn.Width = 105;
// 新优化方式(使用字典存储)
DataModel.columnDateMapping[weekColumn] = weekStart;
weekColumn.OptionsColumn.AllowEdit = weekEnd >= DateTime.Today;
weekColumn.Visible = true;
}
weekStart = weekEnd.AddDays(1);
weekIndex++;
}
foreach (int i in Enumerable.Range(weekIndex, 15 - weekIndex))
{
TreeListBand band = grid.TreeListObj.Bands.Cast<TreeListBand>()
.FirstOrDefault(b => b.Name == $"Week_{i}");
if (band != null) band.Visible = false;
}
foreach (var band in grid.TreeListObj.Bands.Cast<TreeListBand>())
{
if (band.Name.StartsWith("Day_"))
{
band.Visible = false;
foreach (TreeListColumn column in band.Columns)
{
column.Visible = false;
}
}
}
grid.TreeListObj.EndInit();
}
/// <summary>
/// 获取给定日期所在周的开始日期(周一)。
/// </summary>
private DateTime GetStartOfWeek(DateTime date)
{
// 这里假设一周是从周一开始的
int diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7;
DateTime startOfWeek = date.AddDays(-diff);
return startOfWeek.Date; // 返回周一的日期
}
/// <summary>
/// 计算某个日期在该月的第几周
/// </summary>
/// <param name="date">日期</param>
/// <returns>该月的周数</returns>
private int GetWeekOfMonth(DateTime date)
{
var cultureInfo = new CultureInfo("zh-CN");
var calendar = cultureInfo.Calendar;
// 月份的第一天
DateTime firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
// 月份第一天是一年中的第几周
int firstWeekOfYear = calendar.GetWeekOfYear(firstDayOfMonth, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
// 当前日期是一年中的第几周
int currentWeekOfYear = calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
// 计算结果为当前周减去当月第一周,再加1(第一周为第1周)
return currentWeekOfYear - firstWeekOfYear + 1;
}
private void UpdateDailyColumns(BandedGridControlEx grid, DateTime currentDate)
{
grid.BandedView.BandPanelRowHeight = -1;
// 原有的日处理逻辑(保持原代码不变)
DateTime endDate = currentDate.AddMonths(3).AddDays(-1);
grid.BandedView.BeginUpdate();
// 处理每天的列(现有逻辑)
for (int i = 0; i < 93; i++)
{
// 以构建列时的命名规则 "Day_{i}" 查找对应的 GridBand
string bandTitle = $"Day_{i}";
GridBand gridBand = grid.BandedView.Bands.Cast<GridBand>().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.Width = 70;
// 新优化方式(使用字典存储)
DataModel.columnDateMapping[gridColumn] = dateForColumn;
if (grid == 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;
}
}
//隐藏所有包含 week_ 的列
foreach (var band in grid.BandedView.Bands.Cast<GridBand>())
{
if (band.Name.StartsWith("Week_"))
{
band.Visible = false;
foreach (BandedGridColumn column in band.Columns)
{
column.Visible = false;
}
}
}
grid.BandedView.EndUpdate();
}
/// <summary>
/// 更新TreeList控件的日列
/// </summary>
private void UpdateDailyColumns(TreeBandedGridControlEx grid, DateTime currentDate)
{
DateTime endDate = currentDate.AddMonths(3).AddDays(-1);
// 核心优化代码:暂停数据源绑定和界面刷新
grid.TreeListObj.BeginInit();
grid.TreeListObj.BeginUpdate();
grid.TreeListObj.LockReloadNodes(); // 阻止节点数据重载(关键优化)
try
{
for (int i = 0; i < 93; i++)
{
string bandTitle = $"Day_{i}";
TreeListBand treeListBand = grid.TreeListObj.Bands.Cast<TreeListBand>().FirstOrDefault(x => x.Name == bandTitle);
if (treeListBand == null)
continue;
TreeListColumn treeListColumn = treeListBand.Columns.Count > 0 ? treeListBand.Columns[0] : null;
if (treeListColumn == null)
continue;
DateTime dateForColumn = currentDate.AddDays(i);
if (dateForColumn <= endDate)
{
treeListBand.Caption = dateForColumn.ToString("MM-dd");
treeListBand.Visible = true;
treeListColumn.FieldName = dateForColumn.ToString("yyyy-MM-dd"); // 保留原逻辑不变
treeListColumn.Caption = GetChineseWeekDayNumber(dateForColumn);
treeListColumn.Width = 70;
// 关键优化:改为外部字典缓存
DataModel.columnDateMapping[treeListColumn] = dateForColumn;
//treeListColumn.Tag = dateForColumn;
if (grid == treebandGcTop)
{
treeListColumn.OptionsColumn.AllowEdit = dateForColumn.Date >= DateTime.Now.Date;
}
treeListColumn.Visible = true;
}
else
{
treeListBand.Visible = false;
treeListColumn.Visible = false;
}
}
foreach (var band in grid.TreeListObj.Bands.Cast<TreeListBand>())
{
if (band.Name.StartsWith("Week_"))
{
band.Visible = false;
foreach (TreeListColumn column in band.Columns)
{
column.Visible = false;
}
}
}
}
finally
{
grid.TreeListObj.UnlockReloadNodes(); // 重新允许节点加载数据
grid.TreeListObj.EndUpdate(); // 一次性完成所有刷新
grid.TreeListObj.EndInit();
}
}
#endregion
/// <summary>
/// 构建带日期的数据源
/// </summary>
/// <param name="dataMain"></param>
/// <param name="dataDayPlan"></param>
/// <param name="startDate"></param>
/// <returns></returns>
private DataTable MergeMainDataWithDayPlan(
DataTable dataMain,
DataTable dataDayPlan,
DateTime startDate,
string typeDate = "0")
{
string rightPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionValue) ? DataModel.RightDetailModel.UnionValue : "billdocument_id";
string topPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionParentField) ? DataModel.RightDetailModel.UnionParentField : "keyvalue";
// 结束日期 = 开始日期 + 3 个月(不包含该日)
DateTime endDate = startDate.AddMonths(3);
/* ---------- 1. 预索引 dataDayPlan ---------- */
var dayPlanMap = new Dictionary<string, List<DataRow>>();
foreach (DataRow row in dataDayPlan.Rows)
{
string billId = row[rightPrimaryKey].ToString();
if (!dayPlanMap.TryGetValue(billId, out var list))
{
list = new List<DataRow>();
dayPlanMap[billId] = list;
}
list.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. 填充映射表 ---------- */
var dataMap = new Dictionary<string, Dictionary<string, decimal>>();
foreach (DataRow row in dataMain.Rows)
{
string key = row[topPrimaryKey].ToString();
if (!dataMap.ContainsKey(key))
dataMap[key] = new Dictionary<string, decimal>();
if (!dayPlanMap.TryGetValue(key, out var plans)) continue;
foreach (var dayRow in plans)
{
if (dayRow["day"] == DBNull.Value) continue;
var dayValue = Convert.ToDateTime(dayRow["day"]);
if (dayValue < startDate || dayValue >= endDate) continue; // 改成 < endDate
string colName = dayValue.ToString("yyyy-MM-dd");
decimal.TryParse(dayRow["amount"] + "", out var amount);
if (dataMap[key].ContainsKey(colName))
dataMap[key][colName] += amount;
else
dataMap[key][colName] = amount;
}
}
/* ---------- 4. 周报合并(仅当 HasReport && typeDate == "1" ---------- */
if (DataModel.TopModuleModel.HasReport && typeDate == "1")
{
int weekIndex = 0;
DateTime weekStart = startDate;
while (weekStart < endDate && weekIndex < 15)
{
DateTime weekEnd = weekStart.AddDays(6);
var weekSumMap = new Dictionary<string, decimal>();
for (DateTime dt = weekStart; dt <= weekEnd && dt < endDate; dt = dt.AddDays(1))
{
string col = dt.ToString("yyyy-MM-dd");
if (!dataMain.Columns.Contains(col)) continue;
foreach (DataRow row in dataMain.Rows)
{
string key = row[topPrimaryKey].ToString();
if (dataMap.TryGetValue(key, out var map) && map.TryGetValue(col, out var v))
weekSumMap[key] = weekSumMap.TryGetValue(key, out var x) ? x + v : v;
}
}
string firstDayCol = weekStart.ToString("yyyy-MM-dd");
foreach (DataRow row in dataMain.Rows)
{
string key = row[topPrimaryKey].ToString();
if (weekSumMap.TryGetValue(key, out var sum))
row[firstDayCol] = sum;
}
for (DateTime dt = weekStart.AddDays(1); dt <= weekEnd && dt < endDate; dt = dt.AddDays(1))
{
string col = dt.ToString("yyyy-MM-dd");
if (dataMain.Columns.Contains(col))
dataMain.Columns[col].ColumnMapping = MappingType.Hidden;
}
weekStart = weekEnd.AddDays(1);
weekIndex++;
}
}
/* ---------- 5. 一次性写入 DataTable ---------- */
bandGcTop.rowDateValues.Clear();
if (!dataMain.Columns.Contains("PrecomputedMaxDate"))
dataMain.Columns.Add("PrecomputedMaxDate", typeof(string));
for (int i = 0; i < dataMain.Rows.Count; i++)
{
var row = dataMain.Rows[i];
bandGcTop.rowDateValues[i] = new List<DateTime>();
string key = row[topPrimaryKey].ToString();
if (!dataMap.TryGetValue(key, out var map)) continue;
foreach (var kvp in map)
{
row[kvp.Key] = kvp.Value;
if (DateTime.TryParse(kvp.Key, out var d))
bandGcTop.rowDateValues[i].Add(d);
}
row["PrecomputedMaxDate"] = bandGcTop.rowDateValues[i].Any()
? bandGcTop.rowDateValues[i].Max().ToString("yyyy-MM-dd")
: "";
}
dataMain.ColumnChanged += OnDataMainColumnChanged;
dataMain.AcceptChanges();
return dataMain;
}
/// <summary>
/// 数据值改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnDataMainColumnChanged(object sender, DataColumnChangeEventArgs e)
{
DataTable dataMain = (DataTable)sender;
if (e.Column.ColumnName.Equals("PrecomputedMaxDate"))
{
return;
}
if (dataMain != null && dataMain.Columns.Contains("PrecomputedMaxDate"))
{
var value = e.Row[e.Column];
int rowHandle = dataMain.Rows.IndexOf(e.Row);
DateTime? maxDate = null; // 初始化为 null,表示尚未找到有效日期
bool isdatefile = DateTime.TryParse(e.Column.ColumnName, out DateTime tempDate);//获取改变当前列日期
bool isMaxDatefile = bandGcTop.rowDateValues.TryGetValue(rowHandle, out List<DateTime> currentRowDateColumns);//获取记录日期
if (isdatefile)
{
if (isMaxDatefile && currentRowDateColumns.Count > 0)
{
List<DateTime> mvalidDateColumns = bandGcTop.rowDateValues[rowHandle];
if (tempDate > currentRowDateColumns.Max()) // 只有在找到更大的日期时才更新
{
if (decimal.TryParse(value + "", out decimal dValue) && dValue > 0)
{
mvalidDateColumns.Add(tempDate);
e.Row["PrecomputedMaxDate"] = tempDate.ToString("yyyy-MM-dd");
}
}
else if (tempDate == currentRowDateColumns.Max() && string.IsNullOrEmpty(value + ""))
{
bandGcTop.rowDateValues[rowHandle].Remove(tempDate);
e.Row["PrecomputedMaxDate"] = currentRowDateColumns.Count > 0 ? currentRowDateColumns.Max().ToString("yyyy-MM-dd") : "";
}
else
{
if (!mvalidDateColumns.Contains(tempDate))
{
if (decimal.TryParse(value + "", out decimal dValue) && dValue > 0)
{
mvalidDateColumns.Add(tempDate);
e.Row["PrecomputedMaxDate"] = tempDate.ToString("yyyy-MM-dd");
}
}
}
}
else if (decimal.TryParse(value + "", out decimal dValue) && dValue > 0)
{
bandGcTop.rowDateValues[rowHandle].Add(tempDate);
e.Row["PrecomputedMaxDate"] = tempDate.ToString("yyyy-MM-dd");
}
}
}
}
/// <summary>
/// 构建带日期的数据源
/// </summary>
/// <param name="focusedRow"></param>
/// <param name="dataDayPlan"></param>
/// <param name="startDate"></param>
/// <returns></returns>
private void UpdateRowWithDayPlan(DataRow focusedRow, DataTable dataDayPlan, DateTime startDate)
{
string rightPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionValue) ? DataModel.RightDetailModel.UnionValue : "billdocument_id";
string topPrimaryKey = !string.IsNullOrEmpty(DataModel.RightDetailModel.UnionParentField) ? DataModel.RightDetailModel.UnionParentField : "keyvalue";
//string rightPrimaryKey = DataModel.RightModuleModel.ParmaryKey;
//string topPrimaryKey = DataModel.TopModuleModel.ParmaryKey;
DateTime endDate = startDate.AddMonths(3).AddDays(-1); // 计算结束日期
// **1. 预索引 dataDayPlan 数据(billdocument_id -> 该 key 相关的所有行)**
Dictionary<string, List<DataRow>> dayPlanMap = new Dictionary<string, List<DataRow>>();
foreach (DataRow row in dataDayPlan.Rows)
{
string billId = row[rightPrimaryKey].ToString();
if (!dayPlanMap.ContainsKey(billId))
{
dayPlanMap[billId] = new List<DataRow>();
}
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<string, Dictionary<string, decimal>> dataMap = new Dictionary<string, Dictionary<string, decimal>>();
string key = focusedRow[topPrimaryKey].ToString();
if (!dataMap.ContainsKey(key))
{
dataMap[key] = new Dictionary<string, decimal>();
}
// **查找 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))
{
decimal.TryParse(dayRow["amount"] + "", out decimal amountValue);
// 如果日期已存在,则累加金额;否则直接赋值
if (dataMap[key].ContainsKey(colName))
{
dataMap[key][colName] += amountValue; // 累加金额
}
else
{
dataMap[key][colName] = amountValue; // 直接赋值
}
}
}
}
}
// **4. 一次性填充 DataTable(避免逐行赋值带来的性能问题)**
if (dataMap.ContainsKey(key))
{
foreach (var col in dataMap[key])
{
focusedRow[col.Key] = col.Value;
}
}
}
/// <summary>
/// 日期对照
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
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 "";
}
}
/// <summary>
/// 初始化位置
/// </summary>
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);
}
}
/// <summary>
/// 分隔条位置改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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 + "");
}
bandGcTop.gridControl.Refresh();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 合计显示居中设置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnCustomDrawFooterCell(object sender, FooterCellCustomDrawEventArgs e)
{
e.Appearance.TextOptions.HAlignment = HorzAlignment.Center;
}
/// <summary>
/// TreeList合计行单元格居中显示
/// </summary>
private void OnTreeListCustomDrawFooterCell(object sender, DevExpress.XtraTreeList.CustomDrawFooterCellEventArgs e)
{
e.Appearance.TextOptions.HAlignment = HorzAlignment.Center;
}
/// <summary>
/// 表头颜色设置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnCustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e)
{
// 判断列的Tag是否为 DateTime
if (e.Column != null)
{
if (e.Column.Caption.StartsWith("第"))
{
return; // 跳过周列
}
DateTime dateTime;
if (DataModel.columnDateMapping.TryGetValue(e.Column, out dateTime))
{
// 判断日期是否为周末(星期六或星期日)
if (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday)
{
// 设置表头文字颜色为红色
e.Appearance.ForeColor = Color.Red;
}
}
}
}
/// <summary>
/// TreeList表头颜色自定义绘制(精准适配原BandedGridView逻辑)
/// </summary>
private void OnTreeListCustomDrawColumnHeader(object sender, DevExpress.XtraTreeList.CustomDrawColumnHeaderEventArgs e)
{
// 判断列的Tag是否为 DateTime
if (e.Column != null)
{
if (e.Column.Caption.StartsWith("第"))
{
return; // 跳过周列
}
DateTime dateTime;
if (DataModel.columnDateMapping.TryGetValue(e.Column, out dateTime))
{
// 判断日期是否为周末(星期六或星期日)
if (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday)
{
// 设置表头文字颜色为红色
e.Appearance.ForeColor = Color.Red;
}
}
}
}
/// <summary>
/// 按键点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnBandedViewKeyDown(object sender, KeyEventArgs e)
{
BaseUserControl dataTypeControl = DataModel.TopSearchObj.ParentPanel.Controls.Cast<System.Windows.Forms.Control>().Where(n => n is LabelComboxEdit).Cast<BaseUserControl>().FirstOrDefault(); // 获取第一个符合条件的控件
string typeDate = "0";
if (dataTypeControl != null)
{
LabelComboxEdit labelAutoTextEdit = dataTypeControl as LabelComboxEdit;
typeDate = labelAutoTextEdit.EditValue;
}
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 > 1)
{
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)
{
// 判断列的Tag是否为 DateTime
if (gridCell.Column != null)
{
DateTime dateTime;
if (DataModel.columnDateMapping.TryGetValue(gridCell.Column, out dateTime))
{
if (typeDate.Equals("1"))
{
dateTime = dateTime.AddDays(7);
}
string bj_tig = bandedGridView.GetRowCellValue(gridCell.RowHandle, "bj_tig")?.ToString() ?? "";
if (!DataModel.TopModuleModel.HasReport && bj_tig != "0" && dateTime.Date >= DateTime.Now.Date)
{
bandedGridView.SetRowCellValue(gridCell.RowHandle, gridCell.Column, obj);
}
}
}
}
bandedGridView.PostEditor();
e.Handled = true;
}
WaitForm.HideForm();
}
}
}
}
}
/// <summary>
/// TreeList按键事件处理,精准移植原BandedGridView的F7快速填充逻辑
/// </summary>
private void OnTreeListKeyDown(object sender, KeyEventArgs e)
{
TreeList treeList = sender as TreeList;
if (treeList == null || !treeList.OptionsBehavior.Editable) return;
if (e.KeyCode == Keys.F7)
{
// 使用你框架中定义的精准方法来获取选中的单元格集合
List<TreeListCell> selectedCells = treeList.GetSelectedCells();
if (selectedCells != null && selectedCells.Count > 0)
{
// 以第一个选中单元格作为赋值基准值
TreeListCell firstCell = selectedCells[0];
object valueToSet = firstCell.Node.GetValue(firstCell.Column);
if (valueToSet != null && MessageUtil.Show("是否替换所选单元格值?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
WaitForm.ShowForm("数据填充中");
foreach (TreeListCell cell in selectedCells)
{
if (cell.Column.OptionsColumn.AllowEdit)
{
if (DataModel.columnDateMapping.TryGetValue(cell.Column, out DateTime dateTime))
{
// 日期必须大于等于今天才允许赋值
string bj_tig = cell.Node.GetValue("bj_tig")?.ToString() ?? "";
if (!DataModel.TopModuleModel.HasReport && bj_tig != "0" && dateTime.Date >= DateTime.Now.Date)
{
treeList.SetFocusedNode(treebandGcTop.TreeListObj.Nodes[0]);
cell.Node.SetValue(cell.Column, valueToSet);
}
}
}
}
e.Handled = true;
WaitForm.HideForm();
}
}
}
}
/// <summary>
/// 构建下方数据
/// </summary>
/// <param name="dtA"></param>
/// <param name="dtPlan"></param>
/// <param name="startDate"></param>
/// <param name="daysCount"></param>
/// <returns></returns>
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<string>("产地"))
.ToDictionary(
g => g.Key,
g => new
{
TotalCapacity = g.First().Field<decimal>("总产能"),
Coefficient = g.First().Field<decimal>("系数"),
KeyValues = g.Select(r => r.Field<string>("keyvalue")).Distinct().ToList()
}
);
// 2. 构建 C 表结构:固定字段“产地”、“产能”,以及动态日期列(格式 "yyyy-MM-dd"
DataTable dtC = new DataTable();
dtC.Columns.Add("产地", typeof(string));
dtC.Columns.Add("总产能", typeof(decimal));
List<string> dateColumns = new List<string>();
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<string>("billdocument_id"),
ShowDay = r.Field<DateTime>("day").ToString("yyyy-MM-dd", CultureInfo.InvariantCulture),
Amount = r.Field<decimal>("amount")
})
.ToList();
// 4. 遍历每个分组,构造 C 表行数据
foreach (var kvp in groupDict)
{
string origin = kvp.Key;
decimal totalCapacity = kvp.Value.TotalCapacity;
decimal coefficient = kvp.Value.Coefficient;
List<string> keyValues = kvp.Value.KeyValues;
DataRow newRow = dtC.NewRow();
newRow["产地"] = origin;
newRow["总产能"] = totalCapacity;
// 对每个动态日期列,从 dtPlan 中查找 billdocument_id 在 keyValues 内,
// 且 ShowDay 等于当前列名的记录,将 amount 累加后再乘以系数
foreach (string dateCol in dateColumns)
{
decimal sumAmount = planRows
.Where(pr => keyValues.Contains(pr.BillId) && pr.ShowDay == dateCol)
.Sum(pr => pr.Amount);
// 乘以系数得到实际值
newRow[dateCol] = sumAmount * coefficient;
}
dtC.Rows.Add(newRow);
}
return dtC;
}
catch (Exception)
{
return default;
}
}
/// <summary>
/// 纠正输入异常
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnInvalidValueException(object sender, InvalidValueExceptionEventArgs e)
{
if (e.Value.Equals(""))
{
e.ExceptionMode = ExceptionMode.Ignore;
}
}
/// <summary>
/// <para>说明:右键菜单执行后刷新数据,刷新规则按照上一次查询条件刷新</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-11-02 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
protected void OnGridViewRightCallBack(object sender, EventArgs e)
{
try
{
if (TreeMultiHeader)
{
DataTable dt = this.treebandGcTop.GetGridViewDataSource();
if (dt == null || dt.Rows.Count == 0) return;
DataRow SelectTheLine = this.treebandGcTop.GetViewFocusedDataRow();
this.DataModel.TopSearchObj.RememberRow = (this.DataModel.TopModuleModel.AccordingNameSelected == 0);
this.DataModel.TopSearchObj.ButtonObj.PerformClick();
if (this.DataModel.TopModuleModel.AccordingNameSelected != 0)//根据主键刷新目标选中行
{
DataRow items = dt.Rows.Cast<DataRow>().FirstOrDefault(x => x[this.DataModel.TopModuleModel.ParmaryKey].Equals(SelectTheLine[this.DataModel.TopModuleModel.ParmaryKey]));
dt = this.treebandGcTop.GridView.GetGridViewFilteredAndSortedDataToDataTable();
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = dt;
int numberOfRows = bindingSource.Find(this.DataModel.TopModuleModel.ParmaryKey, SelectTheLine[this.DataModel.TopModuleModel.ParmaryKey].ToString());
this.treebandGcTop.GridView.ClearSelection();
this.treebandGcTop.GridView.FocusedRowHandle = numberOfRows;
this.treebandGcTop.GridView.SelectRow(numberOfRows);
}
//this.OnSearchAfterCallBack(null,null);
}
else
{
int oldRowHandle = bandGcTop.GridView.FocusedRowHandle;
DataTable dt = this.bandGcTop.GridView.GetGridViewFilteredAndSortedDataToDataTable();
if (dt == null || dt.Rows.Count == 0) return;
DataRow SelectTheLine = dt.Rows[oldRowHandle];
this.DataModel.TopSearchObj.RememberRow = (this.DataModel.TopModuleModel.AccordingNameSelected == 0);
this.DataModel.TopSearchObj.ButtonObj.PerformClick();
bandGcTop.GridView.SelectRowHandler(oldRowHandle);
if (this.DataModel.TopModuleModel.AccordingNameSelected != 0)//根据主键刷新目标选中行
{
DataRow items = dt.Rows.Cast<DataRow>().FirstOrDefault(x => x[this.DataModel.TopModuleModel.ParmaryKey].Equals(SelectTheLine[this.DataModel.TopModuleModel.ParmaryKey]));
dt = this.bandGcTop.GridView.GetGridViewFilteredAndSortedDataToDataTable();
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = dt;
int numb