Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include more rows in Pivot

Tags:

c#

lambda

linq

I am using the extension method in below link to pivot my data: https://techbrij.com/pivot-c-array-datatable-convert-column-to-row-linq

I am including the code from the link just in case somebody finds this question in the future and the link is dead:

public static DataTable ToPivotTable<T, TColumn, TRow, TData>(
    this IEnumerable<T> source,
    Func<T, TColumn> columnSelector,
    Expression<Func<T, TRow>> rowSelector,
    Func<IEnumerable<T>, TData> dataSelector)
        {
            DataTable table = new DataTable();
            var rowName = ((MemberExpression)rowSelector.Body).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);
            }

            return table;
        }

Referring to the example in the link, you get the pivoted data like;

var pivotTable = data.ToPivotTable(
              item => item.Year, 
              item => item.Product,  
              items => items.Any() ? items.Sum(x=>x.Sales) : 0);

My question is, how can I include more rows into this query to return for example, ProductCode as well.. item => new {item.Product, item.ProductCode} does not work..


============== EDIT / 23 OCT 2018 ==============


Assuming my data is this;

enter image description here

With the help of the above mentioned code, I can manage to do this; enter image description here

What I want to achieve is this (extra col: STOCKID or any other cols as well); enter image description here

like image 523
Subliminal Hash Avatar asked Oct 22 '18 12:10

Subliminal Hash


1 Answers

Anonymous types cannot be passed as generic parameters. Try defining your pivot key as a struct:

public struct PivotKey
{
    public string Product;
    public int ProductCode; // assuming your product codes are integers
}

This way you can take advantage of struct's default Equals and GetHashCode methods implementation in terms of the equality and hash code of all the fields.

Then, define the rowSelector as below:

item => new PivotKey { Product = item.Product, ProductCode = item.ProductCode}
like image 156
Thomas C. G. de Vilhena Avatar answered Oct 27 '22 01:10

Thomas C. G. de Vilhena