// Report tab methods ------------------------------------------------ private void UpdateReportDataGrid() { if (this.reportSelectedPeriod != null && this.reportSelectedGroupBy != null && this.reportSelectedAggregation != null) { C3PredictedColumn selectedColumn = this.config.columns .Where(col => col.columnName.Equals(this.reportSelectedGroupBy, StringComparison.InvariantCultureIgnoreCase)) .FirstOrDefault(); var periodGrouper = Selectors.periodSpecifiers[this.reportSelectedPeriod]; var aggregation = Selectors.aggreations[this.reportSelectedAggregation]; ReportTabDatagrid.ItemsSource = Transforms.GetPeriodSummary(this.currentDataTable, periodGrouper, selectedColumn, aggregation).AsDataView(); } }
/// <summary> /// Generate the table to populate the Report tab, sort of a pivot table /// </summary> /// <param name="currentDataTable"></param> /// <param name="periodGrouper">Function to group datetimes into time ranges (i.e. generates row headers)</param> /// <param name="predictedColumn">Specifies which predictedColumn to use as the column headers</param> /// <param name="aggregation">Function to aggregate grouped prices (usually with Sum)</param> /// <returns>A DataTable to display in the Report tab</returns> public static DataTable GetPeriodSummary(DataTable currentDataTable, Func <DateTime, DateTime> periodGrouper, C3PredictedColumn predictedColumn, Func <IEnumerable <decimal>, decimal> aggregation) { var sw = System.Diagnostics.Stopwatch.StartNew(); var groups = currentDataTable.AsEnumerable() .GroupBy(row => new { category = row.Field <string>(predictedColumn.columnName), period = periodGrouper(row.Field <DateTime>(Consts.TRANSACTIONTIME)) }) .Select(rec => new { k = rec.Key, s = aggregation(rec.Select(row => row.Field <decimal>(Consts.AMOUNT))) }) .ToDictionary(rec => rec.k, rec => rec.s); DataTable dt = new DataTable(); dt.Columns.Add(Consts.PERIOD_START, typeof(DateTime)); foreach (string c in predictedColumn.validValues) { dt.Columns.Add(c.ToString(), typeof(decimal)); } dt.Columns.Add(Consts.PERIOD_TOTAL, typeof(decimal)); var groupQuery = groups.Keys.Select(g => g.period).Distinct().OrderBy(g => g); foreach (DateTime period in groupQuery) { decimal periodTotal = 0M; DataRow dr = dt.NewRow(); dr[0] = period; int i = 1; foreach (string category in predictedColumn.validValues) { groups.TryGetValue(new { category, period }, out decimal total); periodTotal += total; dr[i++] = total; } dr[i] = periodTotal; dt.Rows.Add(dr); } System.Diagnostics.Debug.WriteLine($"{sw.ElapsedMilliseconds} ms elapsed in {nameof(GetPeriodSummary)}()"); return(dt); }