SVN r901
SVN-Revision: r901
This commit is contained in:
@@ -7123,6 +7123,7 @@ namespace Lskj.Control
|
||||
|
||||
// 创建正常列的Band
|
||||
GridBand normalBand = new GridBand() { Caption = "基本信息" };
|
||||
normalBand.Fixed = FixedStyle.Left;
|
||||
bandedGridControlEx.BandedView.Bands.Add(normalBand);
|
||||
|
||||
// 添加正常列到Band中
|
||||
@@ -7156,11 +7157,15 @@ namespace Lskj.Control
|
||||
bandedGridControlEx.BandedView.Columns.Add(col);
|
||||
}
|
||||
}
|
||||
|
||||
// 动态获取需要聚合的列
|
||||
// 取得动态列名(自动处理 DateTime、string 及其它类型,不会抛转换异常)
|
||||
var dynamicHeaders = originalDataSource.AsEnumerable()
|
||||
.Select(r => r.Field<string>(GroupFieldprimary.FieldName))
|
||||
.Distinct().Where(x => !string.IsNullOrEmpty(x)).ToList();
|
||||
.Select(r => r[GroupFieldprimary.FieldName]) // 先拿 object
|
||||
.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,并添加子列
|
||||
foreach (string headerName in dynamicHeaders)
|
||||
@@ -7217,36 +7222,64 @@ namespace Lskj.Control
|
||||
/// <summary>
|
||||
/// 把行转列、动态列拼接,并对指定列做求和
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// 把行转列、动态列拼接,并对指定列做求和(兼容 DateTime 作为 Header 列)
|
||||
/// </summary>
|
||||
private DataTable BuildDynamicDataSource(
|
||||
DataTable original, // 原始数据
|
||||
GridColumnModel keyCol, // 分组主键
|
||||
GridColumnModel headerCol, // 动态列的“Header”列
|
||||
GridColumnModel headerCol, // 动态列的“Header”列(可能是 DateTime)
|
||||
List<GridColumnModel> subCols, // Header 后要展开的子列
|
||||
List<GridColumnModel> normalCols, // 普通列(取首行值)
|
||||
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();
|
||||
|
||||
/* ============ 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);
|
||||
// 辅助:原表已有列名
|
||||
var exist = new HashSet<string>(original.Columns.Cast<DataColumn>().Select(c => c.ColumnName));
|
||||
|
||||
// 求和列
|
||||
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))
|
||||
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)
|
||||
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. 分组聚合 ============ */
|
||||
foreach (var grp in original.AsEnumerable().GroupBy(r => r[keyCol.FieldName]))
|
||||
@@ -7254,48 +7287,67 @@ namespace Lskj.Control
|
||||
var newRow = dt.NewRow();
|
||||
var first = grp.First();
|
||||
|
||||
// 主键值
|
||||
newRow[keyCol.FieldName] = first[keyCol.FieldName];
|
||||
|
||||
// 普通列:取首行
|
||||
foreach (var col in normalCols.Where(c => exist.Contains(c.FieldName)))
|
||||
newRow[col.FieldName] = first[col.FieldName];
|
||||
|
||||
// ─── 求和列:只用第 1 个 Header 小组的行来累加 ───
|
||||
foreach (var col in sumColumns.Where(c => exist.Contains(c.FieldName)))
|
||||
foreach (var col in normalCols)
|
||||
{
|
||||
// ① 取当前分组里第一个 Header 值
|
||||
var firstHeader = grp
|
||||
.Select(r => r[headerCol.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;
|
||||
if (!exist.Contains(col.FieldName)) continue;
|
||||
if (!dt.Columns.Contains(col.FieldName)) continue;
|
||||
newRow[col.FieldName] = first[col.FieldName];
|
||||
}
|
||||
|
||||
// 求和列:以“当前分组中的第一个 Header 键”为准,仅汇总这一组
|
||||
string firstHeader = grp.Select(r => keyOf(r[headerCol.FieldName])).FirstOrDefault();
|
||||
|
||||
// 动态列
|
||||
var lookup = grp.ToLookup(r => r[headerCol.FieldName]?.ToString());
|
||||
foreach (string h in headers)
|
||||
foreach (var col in sumColumns)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!exist.Contains(s.FieldName)) continue;
|
||||
string dyn = $"{h}_{s.FieldName}";
|
||||
var hit = lookup[h].FirstOrDefault();
|
||||
newRow[dyn] = hit?[s.FieldName]?.ToString();
|
||||
if (!dt.Columns.Contains(dyn)) continue;
|
||||
|
||||
var hit = lookup[keyOf(h)].FirstOrDefault(); // headers 已是 string
|
||||
newRow[dyn] = hit == null ? DBNull.Value : hit[s.FieldName];
|
||||
}
|
||||
}
|
||||
|
||||
dt.Rows.Add(newRow);
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 绑定表格树结构弹出框
|
||||
|
||||
@@ -377,6 +377,7 @@ namespace Lskj.Control
|
||||
}
|
||||
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.RowCellClick += new RowCellClickEventHandler(GridView_RowCellClick);
|
||||
this.ModuleGridObj.GridControlObj.GridView.MouseDown += new MouseEventHandler(GridView_MouseDown);
|
||||
@@ -443,6 +444,10 @@ namespace Lskj.Control
|
||||
else
|
||||
{
|
||||
DataRow rowItem = this.ModuleGridObj.GridControlObj.GetViewFocusedDataRow();
|
||||
if (this.ModuleGridObj.GridControlObj.CustomGroupBandEx != null)
|
||||
{
|
||||
rowItem = this.ModuleGridObj.GridControlObj.CustomGroupBandEx.GetViewFocusedDataRow();
|
||||
}
|
||||
if (RefreshDetail)
|
||||
{
|
||||
XtraTabPage RefreshPage = this.TabObj.SelectedTabPage;
|
||||
@@ -648,6 +653,10 @@ namespace Lskj.Control
|
||||
}
|
||||
|
||||
DataRow rowItem = this.ModuleGridObj.GridControlObj.GetViewFocusedDataRow();
|
||||
if (this.ModuleGridObj.GridControlObj.CustomGroupBandEx != null)
|
||||
{
|
||||
rowItem = this.ModuleGridObj.GridControlObj.CustomGroupBandEx.GetViewFocusedDataRow();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(SysModel.PageVisbleCond))
|
||||
{
|
||||
string condSql = ReplaceHelper.ReplaceRowParam(rowItem, ReplaceHelper.ReplaceUserInfo(SysModel.PageVisbleCond));
|
||||
|
||||
Reference in New Issue
Block a user