SVN r901
SVN-Revision: r901
This commit is contained in:
@@ -7123,6 +7123,7 @@ namespace Lskj.Control
|
|||||||
|
|
||||||
// 创建正常列的Band
|
// 创建正常列的Band
|
||||||
GridBand normalBand = new GridBand() { Caption = "基本信息" };
|
GridBand normalBand = new GridBand() { Caption = "基本信息" };
|
||||||
|
normalBand.Fixed = FixedStyle.Left;
|
||||||
bandedGridControlEx.BandedView.Bands.Add(normalBand);
|
bandedGridControlEx.BandedView.Bands.Add(normalBand);
|
||||||
|
|
||||||
// 添加正常列到Band中
|
// 添加正常列到Band中
|
||||||
@@ -7156,11 +7157,15 @@ namespace Lskj.Control
|
|||||||
bandedGridControlEx.BandedView.Columns.Add(col);
|
bandedGridControlEx.BandedView.Columns.Add(col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 取得动态列名(自动处理 DateTime、string 及其它类型,不会抛转换异常)
|
||||||
// 动态获取需要聚合的列
|
|
||||||
var dynamicHeaders = originalDataSource.AsEnumerable()
|
var dynamicHeaders = originalDataSource.AsEnumerable()
|
||||||
.Select(r => r.Field<string>(GroupFieldprimary.FieldName))
|
.Select(r => r[GroupFieldprimary.FieldName]) // 先拿 object
|
||||||
.Distinct().Where(x => !string.IsNullOrEmpty(x)).ToList();
|
.Where(v => v != null && v != DBNull.Value) // 过滤空值
|
||||||
|
.Select(v => v is DateTime dt // ↙︎ DateTime 转指定格式
|
||||||
|
? dt.ToString("yyyy-MM-dd")
|
||||||
|
: v.ToString()) // 其它类型直接 ToString()
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
// 为每个动态表头生成GridBand,并添加子列
|
// 为每个动态表头生成GridBand,并添加子列
|
||||||
foreach (string headerName in dynamicHeaders)
|
foreach (string headerName in dynamicHeaders)
|
||||||
@@ -7217,36 +7222,64 @@ namespace Lskj.Control
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 把行转列、动态列拼接,并对指定列做求和
|
/// 把行转列、动态列拼接,并对指定列做求和
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <summary>
|
||||||
|
/// 把行转列、动态列拼接,并对指定列做求和(兼容 DateTime 作为 Header 列)
|
||||||
|
/// </summary>
|
||||||
private DataTable BuildDynamicDataSource(
|
private DataTable BuildDynamicDataSource(
|
||||||
DataTable original, // 原始数据
|
DataTable original, // 原始数据
|
||||||
GridColumnModel keyCol, // 分组主键
|
GridColumnModel keyCol, // 分组主键
|
||||||
GridColumnModel headerCol, // 动态列的“Header”列
|
GridColumnModel headerCol, // 动态列的“Header”列(可能是 DateTime)
|
||||||
List<GridColumnModel> subCols, // Header 后要展开的子列
|
List<GridColumnModel> subCols, // Header 后要展开的子列
|
||||||
List<GridColumnModel> normalCols, // 普通列(取首行值)
|
List<GridColumnModel> normalCols, // 普通列(取首行值)
|
||||||
List<GridColumnModel> sumColumns, // 需要求和的列
|
List<GridColumnModel> sumColumns, // 需要求和的列
|
||||||
List<string> headers) // Header 值集合
|
List<string> headers) // Header 值集合(建议已格式化为 yyyy-MM-dd 等字符串)
|
||||||
{
|
{
|
||||||
|
// 统一把 Header 的原始值转成用于匹配/建列的键(string)
|
||||||
|
string formatKey(object v)
|
||||||
|
{
|
||||||
|
if (v == null || v == DBNull.Value) return null;
|
||||||
|
if (v is DateTime) return ((DateTime)v).ToString("yyyy-MM-dd"); // 如需其它格式,修改此处
|
||||||
|
return v.ToString();
|
||||||
|
}
|
||||||
|
string keyOf(object v) => formatKey(v) ?? string.Empty; // 避免 null 键
|
||||||
|
|
||||||
var dt = new DataTable();
|
var dt = new DataTable();
|
||||||
|
|
||||||
/* ============ 1. 建列 ============ */
|
/* ============ 1. 建列 ============ */
|
||||||
|
// 主键列
|
||||||
dt.Columns.Add(keyCol.FieldName, original.Columns[keyCol.FieldName].DataType);
|
dt.Columns.Add(keyCol.FieldName, original.Columns[keyCol.FieldName].DataType);
|
||||||
|
|
||||||
// 普通列
|
// 辅助:原表已有列名
|
||||||
var exist = new HashSet<string>(original.Columns.Cast<DataColumn>()
|
var exist = new HashSet<string>(original.Columns.Cast<DataColumn>().Select(c => c.ColumnName));
|
||||||
.Select(c => c.ColumnName));
|
|
||||||
foreach (var col in normalCols.Where(c => exist.Contains(c.FieldName)
|
|
||||||
&& c.FieldName != keyCol.FieldName))
|
|
||||||
dt.Columns.Add(col.FieldName, original.Columns[col.FieldName].DataType);
|
|
||||||
|
|
||||||
// 求和列
|
// 普通列:不重复、不覆盖主键
|
||||||
foreach (var col in sumColumns.Where(c => exist.Contains(c.FieldName)))
|
foreach (var col in normalCols)
|
||||||
|
{
|
||||||
|
if (col.FieldName == keyCol.FieldName) continue;
|
||||||
|
if (!exist.Contains(col.FieldName)) continue;
|
||||||
if (!dt.Columns.Contains(col.FieldName))
|
if (!dt.Columns.Contains(col.FieldName))
|
||||||
dt.Columns.Add(col.FieldName, original.Columns[col.FieldName].DataType);
|
dt.Columns.Add(col.FieldName, original.Columns[col.FieldName].DataType);
|
||||||
|
}
|
||||||
|
|
||||||
// 动态列:统一 string
|
// 求和列:类型沿用原列
|
||||||
foreach (string h in headers)
|
foreach (var col in sumColumns)
|
||||||
|
{
|
||||||
|
if (!exist.Contains(col.FieldName)) continue;
|
||||||
|
if (!dt.Columns.Contains(col.FieldName))
|
||||||
|
dt.Columns.Add(col.FieldName, original.Columns[col.FieldName].DataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态列:以 headers × subCols 展开;类型沿用子列类型
|
||||||
|
foreach (var h in headers)
|
||||||
|
{
|
||||||
foreach (var s in subCols)
|
foreach (var s in subCols)
|
||||||
dt.Columns.Add($"{h}_{s.FieldName}", original.Columns[s.FieldName].DataType);
|
{
|
||||||
|
if (!exist.Contains(s.FieldName)) continue;
|
||||||
|
string dyn = $"{h}_{s.FieldName}";
|
||||||
|
if (!dt.Columns.Contains(dyn))
|
||||||
|
dt.Columns.Add(dyn, original.Columns[s.FieldName].DataType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ============ 2. 分组聚合 ============ */
|
/* ============ 2. 分组聚合 ============ */
|
||||||
foreach (var grp in original.AsEnumerable().GroupBy(r => r[keyCol.FieldName]))
|
foreach (var grp in original.AsEnumerable().GroupBy(r => r[keyCol.FieldName]))
|
||||||
@@ -7254,39 +7287,60 @@ namespace Lskj.Control
|
|||||||
var newRow = dt.NewRow();
|
var newRow = dt.NewRow();
|
||||||
var first = grp.First();
|
var first = grp.First();
|
||||||
|
|
||||||
|
// 主键值
|
||||||
newRow[keyCol.FieldName] = first[keyCol.FieldName];
|
newRow[keyCol.FieldName] = first[keyCol.FieldName];
|
||||||
|
|
||||||
// 普通列:取首行
|
// 普通列:取首行
|
||||||
foreach (var col in normalCols.Where(c => exist.Contains(c.FieldName)))
|
foreach (var col in normalCols)
|
||||||
newRow[col.FieldName] = first[col.FieldName];
|
|
||||||
|
|
||||||
// ─── 求和列:只用第 1 个 Header 小组的行来累加 ───
|
|
||||||
foreach (var col in sumColumns.Where(c => exist.Contains(c.FieldName)))
|
|
||||||
{
|
{
|
||||||
// ① 取当前分组里第一个 Header 值
|
if (!exist.Contains(col.FieldName)) continue;
|
||||||
var firstHeader = grp
|
if (!dt.Columns.Contains(col.FieldName)) continue;
|
||||||
.Select(r => r[headerCol.FieldName])
|
newRow[col.FieldName] = first[col.FieldName];
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
// ② 过滤到只剩这个 Header 的行后求和
|
|
||||||
decimal sum = grp
|
|
||||||
.Where(r => Equals(r[headerCol.FieldName], firstHeader)
|
|
||||||
&& r[col.FieldName] != DBNull.Value)
|
|
||||||
.Sum(r => Convert.ToDecimal(r[col.FieldName]));
|
|
||||||
|
|
||||||
// ③ 写入结果行
|
|
||||||
newRow[col.FieldName] = sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 求和列:以“当前分组中的第一个 Header 键”为准,仅汇总这一组
|
||||||
|
string firstHeader = grp.Select(r => keyOf(r[headerCol.FieldName])).FirstOrDefault();
|
||||||
|
|
||||||
// 动态列
|
foreach (var col in sumColumns)
|
||||||
var lookup = grp.ToLookup(r => r[headerCol.FieldName]?.ToString());
|
{
|
||||||
foreach (string h in headers)
|
if (!exist.Contains(col.FieldName)) continue;
|
||||||
|
if (!dt.Columns.Contains(col.FieldName)) continue;
|
||||||
|
|
||||||
|
decimal sum = 0m;
|
||||||
|
foreach (var r in grp)
|
||||||
|
{
|
||||||
|
if (keyOf(r[headerCol.FieldName]) != firstHeader) continue;
|
||||||
|
var v = r[col.FieldName];
|
||||||
|
if (v == null || v == DBNull.Value) continue;
|
||||||
|
sum += Convert.ToDecimal(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 把 decimal 结果转换成目标列的数据类型再写入
|
||||||
|
var targetType = dt.Columns[col.FieldName].DataType;
|
||||||
|
object sumValue;
|
||||||
|
if (targetType == typeof(decimal)) sumValue = sum;
|
||||||
|
else if (targetType == typeof(int)) sumValue = Convert.ToInt32(sum);
|
||||||
|
else if (targetType == typeof(long)) sumValue = Convert.ToInt64(sum);
|
||||||
|
else if (targetType == typeof(double)) sumValue = Convert.ToDouble(sum);
|
||||||
|
else if (targetType == typeof(float)) sumValue = Convert.ToSingle(sum);
|
||||||
|
else sumValue = sum; // 兜底:直接写 decimal
|
||||||
|
|
||||||
|
newRow[col.FieldName] = sumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态列:用统一的键做命中
|
||||||
|
var lookup = grp.ToLookup(r => keyOf(r[headerCol.FieldName]));
|
||||||
|
foreach (var h in headers)
|
||||||
|
{
|
||||||
foreach (var s in subCols)
|
foreach (var s in subCols)
|
||||||
{
|
{
|
||||||
|
if (!exist.Contains(s.FieldName)) continue;
|
||||||
string dyn = $"{h}_{s.FieldName}";
|
string dyn = $"{h}_{s.FieldName}";
|
||||||
var hit = lookup[h].FirstOrDefault();
|
if (!dt.Columns.Contains(dyn)) continue;
|
||||||
newRow[dyn] = hit?[s.FieldName]?.ToString();
|
|
||||||
|
var hit = lookup[keyOf(h)].FirstOrDefault(); // headers 已是 string
|
||||||
|
newRow[dyn] = hit == null ? DBNull.Value : hit[s.FieldName];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dt.Rows.Add(newRow);
|
dt.Rows.Add(newRow);
|
||||||
@@ -7294,8 +7348,6 @@ namespace Lskj.Control
|
|||||||
|
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 绑定表格树结构弹出框
|
#region 绑定表格树结构弹出框
|
||||||
|
|||||||
@@ -377,6 +377,7 @@ namespace Lskj.Control
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(this.ModuleGridObj.GridControlObj.CustomGroupBandEx!=null) this.ModuleGridObj.GridControlObj.CustomGroupBandEx.GridView.FocusedRowObjectChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventHandler(OnGridViewFocusedRowObjectChanged);
|
||||||
this.ModuleGridObj.GridControlObj.GridView.FocusedRowObjectChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventHandler(OnGridViewFocusedRowObjectChanged);
|
this.ModuleGridObj.GridControlObj.GridView.FocusedRowObjectChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventHandler(OnGridViewFocusedRowObjectChanged);
|
||||||
//this.ModuleGridObj.GridControlObj.GridView.RowCellClick += new RowCellClickEventHandler(GridView_RowCellClick);
|
//this.ModuleGridObj.GridControlObj.GridView.RowCellClick += new RowCellClickEventHandler(GridView_RowCellClick);
|
||||||
this.ModuleGridObj.GridControlObj.GridView.MouseDown += new MouseEventHandler(GridView_MouseDown);
|
this.ModuleGridObj.GridControlObj.GridView.MouseDown += new MouseEventHandler(GridView_MouseDown);
|
||||||
@@ -443,6 +444,10 @@ namespace Lskj.Control
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DataRow rowItem = this.ModuleGridObj.GridControlObj.GetViewFocusedDataRow();
|
DataRow rowItem = this.ModuleGridObj.GridControlObj.GetViewFocusedDataRow();
|
||||||
|
if (this.ModuleGridObj.GridControlObj.CustomGroupBandEx != null)
|
||||||
|
{
|
||||||
|
rowItem = this.ModuleGridObj.GridControlObj.CustomGroupBandEx.GetViewFocusedDataRow();
|
||||||
|
}
|
||||||
if (RefreshDetail)
|
if (RefreshDetail)
|
||||||
{
|
{
|
||||||
XtraTabPage RefreshPage = this.TabObj.SelectedTabPage;
|
XtraTabPage RefreshPage = this.TabObj.SelectedTabPage;
|
||||||
@@ -648,6 +653,10 @@ namespace Lskj.Control
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataRow rowItem = this.ModuleGridObj.GridControlObj.GetViewFocusedDataRow();
|
DataRow rowItem = this.ModuleGridObj.GridControlObj.GetViewFocusedDataRow();
|
||||||
|
if (this.ModuleGridObj.GridControlObj.CustomGroupBandEx != null)
|
||||||
|
{
|
||||||
|
rowItem = this.ModuleGridObj.GridControlObj.CustomGroupBandEx.GetViewFocusedDataRow();
|
||||||
|
}
|
||||||
if (!string.IsNullOrEmpty(SysModel.PageVisbleCond))
|
if (!string.IsNullOrEmpty(SysModel.PageVisbleCond))
|
||||||
{
|
{
|
||||||
string condSql = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(SysModel.PageVisbleCond));
|
string condSql = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(SysModel.PageVisbleCond));
|
||||||
|
|||||||
Reference in New Issue
Block a user