SVN-Revision: r808
This commit is contained in:
tdx
2025-06-27 10:25:34 +00:00
parent 0da4640550
commit 23e797a3f3
+89 -86
View File
@@ -7021,7 +7021,7 @@ namespace Lskj.Control
GridColumnModel GroupPrimary = ColumnList.FirstOrDefault(o => o.IsCustomGroupPrimary);
GridColumnModel GroupFieldprimary = ColumnList.FirstOrDefault(o => o.IsCustomGroupField == 1);
List<GridColumnModel> GroupField = ColumnList.Where(o => o.IsCustomGroupField == 2).ToList();
List<GridColumnModel> sumField = ColumnList.Where(o => o.IsCustomGroupField == 3).ToList();
if (GroupPrimary == null || GroupFieldprimary == null || !GroupField.Any())
return; // 数据不足直接退出
@@ -7072,7 +7072,7 @@ namespace Lskj.Control
var dynamicHeaders = originalDataSource.AsEnumerable()
.Select(r => r.Field<string>(GroupFieldprimary.FieldName))
.Distinct().Where(x => !string.IsNullOrEmpty(x)).ToList();
// 为每个动态表头生成GridBand,并添加子列
foreach (string headerName in dynamicHeaders)
{
@@ -7111,7 +7111,7 @@ namespace Lskj.Control
}
bandedGridControlEx.BandedView.EndUpdate();
// 构建最终动态数据源
DataTable dynamicDataTable = BuildDynamicDataSource(originalDataSource, GroupPrimary, GroupFieldprimary, GroupField, normalColumns, dynamicHeaders);
DataTable dynamicDataTable = BuildDynamicDataSource(originalDataSource, GroupPrimary, GroupFieldprimary, GroupField, normalColumns, sumField, dynamicHeaders);
bandedGridControlEx.gridControl.DataSource = dynamicDataTable;
}
@@ -7125,98 +7125,75 @@ namespace Lskj.Control
/// <param name="normalColumns"></param>
/// <param name="dynamicHeaders"></param>
/// <returns></returns>
private DataTable BuildDynamicDataSource(DataTable originalDataSource,
GridColumnModel GroupPrimary,
GridColumnModel GroupFieldprimary,
List<GridColumnModel> GroupField,
List<GridColumnModel> normalColumns,
List<string> dynamicHeaders)
/// <summary>
/// 把行转列、动态列拼接,并对指定列做求和
/// </summary>
private DataTable BuildDynamicDataSource(
DataTable original, // 原始数据
GridColumnModel keyCol, // 分组主键
GridColumnModel headerCol, // 动态列的“Header”列
List<GridColumnModel> subCols, // Header 后要展开的子列
List<GridColumnModel> normalCols, // 普通列(取首行值)
List<GridColumnModel> sumColumns, // 需要求和的列
List<string> headers) // Header 值集合
{
try
var dt = new DataTable();
/* ============ 1. 建列 ============ */
dt.Columns.Add(keyCol.FieldName, original.Columns[keyCol.FieldName].DataType);
// 普通列
var exist = new HashSet<string>(original.Columns.Cast<DataColumn>()
.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)))
if (!dt.Columns.Contains(col.FieldName))
dt.Columns.Add(col.FieldName, original.Columns[col.FieldName].DataType);
// 动态列:统一 string
foreach (string h in headers)
foreach (var s in subCols)
dt.Columns.Add($"{h}_{s.FieldName}", typeof(string));
/* ============ 2. 分组聚合 ============ */
foreach (var grp in original.AsEnumerable().GroupBy(r => r[keyCol.FieldName]))
{
DataTable dtResult = new DataTable();
var newRow = dt.NewRow();
var first = grp.First();
// 添加主键列
if (!dtResult.Columns.Contains(GroupPrimary.FieldName))
newRow[keyCol.FieldName] = first[keyCol.FieldName];
// 普通列:取首行
foreach (var col in normalCols.Where(c => exist.Contains(c.FieldName)))
newRow[col.FieldName] = first[col.FieldName];
// 求和列
foreach (var col in sumColumns.Where(c => exist.Contains(c.FieldName)))
{
Type dataType = originalDataSource.Columns[GroupPrimary.FieldName].DataType;
dtResult.Columns.Add(GroupPrimary.FieldName, dataType);
var sum = grp
.Where(r => r[col.FieldName] != DBNull.Value)
.Sum(r => Convert.ToDecimal(r[col.FieldName]));
newRow[col.FieldName] = sum;
}
// 添加普通列,仅当原数据源存在时才添加
foreach (var col in normalColumns)
{
if (originalDataSource.Columns.Contains(col.FieldName) && col.FieldName != GroupPrimary.FieldName)
// 动态列
var lookup = grp.ToLookup(r => r[headerCol.FieldName]?.ToString());
foreach (string h in headers)
foreach (var s in subCols)
{
Type dataType = originalDataSource.Columns[col.FieldName].DataType;
dtResult.Columns.Add(col.FieldName, dataType);
}
}
// 添加动态列 (改为string类型避免异常)
foreach (string header in dynamicHeaders)
{
foreach (var subField in GroupField)
{
string dynamicFieldName = $"{header}_{subField.FieldName}";
if (!dtResult.Columns.Contains(dynamicFieldName))
{
Type dataType = originalDataSource.Columns[subField.FieldName].DataType;
dtResult.Columns.Add(dynamicFieldName, dataType); // <-- 此处已修改为string
}
}
}
// 根据主键聚合数据
var groupedData = originalDataSource.AsEnumerable()
.GroupBy(row => row.Field<string>(GroupPrimary.FieldName));
foreach (var group in groupedData)
{
DataRow newRow = dtResult.NewRow();
// 主键列赋值
DataRow firstRow = group.First();
newRow[GroupPrimary.FieldName] = firstRow[GroupPrimary.FieldName];
// 普通列赋值(需判断原数据源中存在)
foreach (var col in normalColumns)
{
if (originalDataSource.Columns.Contains(col.FieldName))
newRow[col.FieldName] = firstRow[col.FieldName];
string dyn = $"{h}_{s.FieldName}";
var hit = lookup[h].FirstOrDefault();
newRow[dyn] = hit?[s.FieldName]?.ToString();
}
// 动态聚合列赋值
foreach (var header in dynamicHeaders)
{
var matchedRow = group.FirstOrDefault(r => r.Field<string>(GroupFieldprimary.FieldName) == header);
foreach (var subField in GroupField)
{
string dynamicFieldName = $"{header}_{subField.FieldName}";
object value = DBNull.Value;
if (matchedRow != null && originalDataSource.Columns.Contains(subField.FieldName))
{
value = matchedRow[subField.FieldName];
}
newRow[dynamicFieldName] = value;
}
}
dtResult.Rows.Add(newRow);
}
return dtResult;
}
catch (Exception ex)
{
// 最好将异常记录下来
Console.WriteLine(ex.Message);
return null;
dt.Rows.Add(newRow);
}
return dt;
}
@@ -8739,4 +8716,30 @@ namespace Lskj.Control
{
// 只处理列名可解析成日期的列
if (!DateTime.TryParse(col.FieldName, out _))
continue;
// 取 “Sum” 合计
var sumItem = col.Summary
.OfType<GridColumnSummaryItem>()
.FirstOrDefault(s => s.SummaryType == SummaryItemType.Sum);
bool needRed = false;
if (sumItem?.SummaryValue != null &&
decimal.TryParse(sumItem.SummaryValue.ToString(), out var colSum) &&
jhrowitem.Table.Columns.Contains(col.FieldName) &&
decimal.TryParse(jhrowitem[col.FieldName].ToString(), out var planVal))
{
needRed = (colSum != planVal);
}
// 只改表头文字颜色
col.AppearanceHeader.ForeColor = needRed ? Color.Red : Color.Black;
col.AppearanceHeader.Options.UseForeColor = true;
}
// 立刻刷新表头
gridView.Invalidate();
}
}
}