public Pivoter(PivotReport pivotReport, ResultSet plainResultSet) { _plainResultSet = plainResultSet; _normalColumns = new List <ColumnInfo>(); _pivotColumns = new List <ColumnInfo>(); IList <ReportColumn> groupByColumns = pivotReport.GroupByColumns; IList <ReportColumn> crosstabColumns = pivotReport.CrossTabHeaders; foreach (ReportColumn reportColumn in pivotReport.Columns) { _normalColumns.Add(plainResultSet.GetColumnInfo(reportColumn)); } foreach (ReportColumn reportColumn in pivotReport.CrossTabValues) { _pivotColumns.Add(plainResultSet.GetColumnInfo(reportColumn)); } Dictionary <RowKey, Dictionary <RowKey, int> > rowsById = new Dictionary <RowKey, Dictionary <RowKey, int> >(); ICollection <RowKey> pivotNameSet = new HashSet <RowKey>(); for (int i = 0; i < plainResultSet.RowCount; i++) { RowKey unqualifiedGroupByKey = new RowKey(); foreach (var reportColumn in groupByColumns) { unqualifiedGroupByKey.Add(plainResultSet.GetValue(i, reportColumn)); } RowKey crossTabKey = new RowKey(); foreach (var reportColumn in crosstabColumns) { crossTabKey.Add(plainResultSet.GetValue(i, reportColumn)); } // Add the data from the row into the spot for the GroupByKey and CrossTabKey. // In case that spot is already taken, an integer is appended to the GroupByKey // until a vacant spot to hold the data is found. Dictionary <RowKey, int> pivotNameDict; for (int iQualifier = 0; ; iQualifier++) { var qualifiedGroupByKey = new RowKey(); qualifiedGroupByKey.AddRange(unqualifiedGroupByKey); qualifiedGroupByKey.Add(iQualifier); if (!rowsById.TryGetValue(qualifiedGroupByKey, out pivotNameDict)) { pivotNameDict = new Dictionary <RowKey, int>(); rowsById.Add(qualifiedGroupByKey, pivotNameDict); } if (!pivotNameDict.ContainsKey(crossTabKey)) { break; } } pivotNameDict.Add(crossTabKey, i); pivotNameSet.Add(crossTabKey); } _pivotNames = new List <RowKey>(pivotNameSet); _pivotNames.Sort(); List <Object[]> rows = new List <object[]>(); foreach (Dictionary <RowKey, int> dict in rowsById.Values) { rows.Add(PivotRow(dict)); } _pivotedResultSet = new ResultSet(GetPivotedColumnInfos(), rows); }