Update ToPivotTable

This commit is contained in:
sunkaixuan 2024-01-06 23:19:02 +08:00
parent 6ee18ff5f1
commit 932dd36ab6
3 changed files with 139 additions and 0 deletions

View File

@ -460,6 +460,7 @@
<Compile Include="Utilities\CallContext.cs" /> <Compile Include="Utilities\CallContext.cs" />
<Compile Include="Utilities\CallContextAsync.cs" /> <Compile Include="Utilities\CallContextAsync.cs" />
<Compile Include="Abstract\DynamicBuilder\DynamicBuilderHelper.cs" /> <Compile Include="Abstract\DynamicBuilder\DynamicBuilderHelper.cs" />
<Compile Include="Utilities\PivotHelper.cs" />
<Compile Include="Utilities\FastCopy.cs" /> <Compile Include="Utilities\FastCopy.cs" />
<Compile Include="Utilities\ExpressionBuilderHelper.cs" /> <Compile Include="Utilities\ExpressionBuilderHelper.cs" />
<Compile Include="Utilities\CommonExtensions.cs" /> <Compile Include="Utilities\CommonExtensions.cs" />

View File

@ -18,6 +18,11 @@ namespace SqlSugar
Expression<Func<T, TRow>> rowSelector, Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector) Func<IEnumerable<T>, TData> dataSelector)
{ {
if (rowSelector.Body is MemberExpression)
return PivotHelper.ToPivotTable(source, columnSelector, rowSelector, dataSelector);
DataTable table = new DataTable(); DataTable table = new DataTable();
var rowName = new List<string>(); var rowName = new List<string>();
@ -64,6 +69,10 @@ namespace SqlSugar
Func<IEnumerable<T>, TData> dataSelector) Func<IEnumerable<T>, TData> dataSelector)
{ {
if (rowSelector.Body is MemberExpression)
return PivotHelper.ToPivotList(source, columnSelector, rowSelector, dataSelector);
var rowName = new List<string>(); var rowName = new List<string>();
if (rowSelector.Body is MemberExpression) if (rowSelector.Body is MemberExpression)
rowName.Add(((MemberExpression)rowSelector.Body).Member.Name); rowName.Add(((MemberExpression)rowSelector.Body).Member.Name);

View File

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SqlSugar
{
internal static class PivotHelper
{
public static DataTable ToPivotTable<T, TColumn, TRow, TData>(
IEnumerable<T> source,
Func<T, TColumn> columnSelector,
Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector)
{
DataTable table = new DataTable();
var rowName = "";
if (rowSelector.Body is MemberExpression)
rowName = ((MemberExpression)rowSelector.Body).Member.Name;
else
rowName = string.Join(UtilConstants.ReplaceKey, ((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name));
table.Columns.Add(new DataColumn(rowName));
var columns = source.Select(columnSelector).Distinct();
foreach (var column in columns)
table.Columns.Add(new DataColumn(column?.ToString()));
var rows = source.GroupBy(rowSelector.Compile())
.Select(rowGroup => new
{
Key = rowGroup.Key,
Values = columns.GroupJoin(
rowGroup,
c => c,
r => columnSelector(r),
(c, columnGroup) => dataSelector(columnGroup))
});
foreach (var row in rows)
{
var dataRow = table.NewRow();
var items = row.Values.Cast<object>().ToList();
items.Insert(0, row.Key);
dataRow.ItemArray = items.ToArray();
table.Rows.Add(dataRow);
}
var firstName = table.Columns[0]?.ColumnName;
if (firstName.ObjToString().Contains(UtilConstants.ReplaceKey))
{
int i = 0;
foreach (var item in Regex.Split(firstName, UtilConstants.ReplaceKey))
{
i++;
table.Columns.Add(item);
table.Columns[item].SetOrdinal(i);
}
foreach (DataRow row in table.Rows)
{
var json = row[firstName];
var list = json.ToString().TrimStart('{', ' ').TrimEnd('}', ' ')
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(it => it.Split(new[] { " = " }, StringSplitOptions.None)).ToList();
foreach (var item in Regex.Split(firstName, UtilConstants.ReplaceKey))
{
var x = list.First(it => it.First().Trim() == item.Trim());
row[item] = x[1];
}
}
table.Columns.Remove(firstName);
}
return table;
}
public static List<dynamic> ToPivotList<T, TColumn, TRow, TData>(
IEnumerable<T> source,
Func<T, TColumn> columnSelector,
Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector)
{
var arr = new List<object>();
var cols = new List<string>();
var rowName = "";
if (rowSelector.Body is MemberExpression)
rowName = ((MemberExpression)rowSelector.Body).Member.Name;
else
rowName = "Group_" + string.Join("_", ((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name));
var columns = source.Select(columnSelector).Distinct();
cols = (new[] { rowName }).Concat(columns.Select(x => x?.ToString())).ToList();
var rows = source.GroupBy(rowSelector.Compile())
.Select(rowGroup => new
{
Key = rowGroup.Key,
Values = columns.GroupJoin(
rowGroup,
c => c,
r => columnSelector(r),
(c, columnGroup) => dataSelector(columnGroup))
}).ToList();
foreach (var row in rows)
{
var items = row.Values.Cast<object>().ToList();
items.Insert(0, row.Key);
var obj = GetAnonymousObject(cols, items);
arr.Add(obj);
}
return arr.ToList();
}
private static dynamic GetAnonymousObject(IEnumerable<string> columns, IEnumerable<object> values)
{
IDictionary<string, object> eo = new ExpandoObject() as IDictionary<string, object>;
int i;
for (i = 0; i < columns.Count(); i++)
{
eo.Add(columns.ElementAt<string>(i), values.ElementAt<object>(i));
}
return eo;
}
}
}