private string GetFormattedValue(DataContext dataContext) { if (Format == null) { return(null); } String f; String[] pn; StringFormatHelper.PrepareFormatWithNames(Format, out f, out pn); if (pn == null) { return(f); } object[] pv = pn.Select(a => dataContext.GetParameterValue(a)).ToArray(); return(String.Format(f, pv)); }
public override void Render(Report report, Flow fm, DataContext dataContext) { HashSet <String> fieldNames = new HashSet <string>(); foreach (var c in Columns) { if (c.DataField != "#") { fieldNames.Add(c.DataField); } if (c.AggregateWeightDataField != null) { fieldNames.Add(c.AggregateWeightDataField); } } foreach (var g in Groups) { foreach (var sc in g.GroupByColumns) { fieldNames.Add(sc.DataField); } } var data = dataContext.CreateTable(DataTable, fieldNames.ToArray()); for (int i = 0; i < Columns.Length; i++) { Columns[i]._Index = i; Columns[i]._DataFieldIndex = data.GetColumnIndex(Columns[i].DataField); if (Columns[i].AggregateWeightDataField != null) { Columns[i]._AggregateWeightDataFieldIndex = data.GetColumnIndex(Columns[i].AggregateWeightDataField); if (Columns[i]._AggregateWeightDataFieldIndex == -1) { throw new InvalidOperationException(String.Format("Weight column '{0}' not found.", Columns[i].AggregateWeightDataField)); } } } List <SortColumn> sort = new List <SortColumn>(); List <GroupData> groupData = new List <GroupData>(); int gi = 0; if (Groups != null) { foreach (var g in Groups) { var gd = new GroupData(); var gc = new List <SortColumn>(); if (g.GroupByColumns != null) { foreach (var c in g.GroupByColumns) { var ci = data.GetColumnIndex(c.DataField); if (ci != -1) { gc.Add(new SortColumn { ColumnIndex = ci, SortDirection = c.SortDirection == SortDirection.None ? SortDirection.Ascending : c.SortDirection }); } } } gd.Columns = gc.ToArray(); sort.AddRange(gd.Columns); gd.GroupIndex = gi++; gd.Group = g; if (g.CaptionFormat != null) { String[] names; String format; StringFormatHelper.PrepareFormatWithNames(g.CaptionFormat, out format, out names); gd.PreparedCaptionFormat = format; gd.PreparedCaptionColumns = names != null?names.Select(a => data.GetColumnIndex(a)).ToArray() : null; } if (g.FooterFormat != null) { String[] names; String format; StringFormatHelper.PrepareFormatWithNames(g.FooterFormat, out format, out names); gd.PreparedFooterFormat = format; gd.PreparedFooterColumns = names != null?names.Select(a => data.GetColumnIndex(a)).ToArray() : null; } gd.GroupLevel = Groups.Length - gd.GroupIndex - 1; gd.GroupOpen = false; groupData.Add(gd); } } sort.AddRange(from c in Columns where c.SortDirection != SortDirection.None orderby c.SortIndex select new SortColumn { ColumnIndex = c._DataFieldIndex, SortDirection = c.SortDirection }); if (sort.Count != 0) { data.Sort(sort.ToArray()); } var rows = data.Rows; var rect = fm.GetRect(Position, Columns.Length, 0); var pos = new RowCol { Col = rect.Col1, Row = rect.Row1 }; var startRow = pos.Row; List <Cell> cells = new List <Cell>(); object[] accumulator = new object[Columns.Length]; decimal[] count = new decimal[Columns.Length]; CellAlignment[] align = new CellAlignment[Columns.Length]; for (int c = 0; c < Columns.Length; c++) { var th = Columns[c]._DataFieldIndex >= 0 ? data.TypeHelper[Columns[c]._DataFieldIndex] : null; if (th != null) { switch (Columns[c].AggregateFunction) { case AggregateFunction.Sum: accumulator[c] = th.Math.Zero; break; case AggregateFunction.Count: accumulator[c] = 0; break; case AggregateFunction.Avg: if (Columns[c].AggregateWeightDataField != null) { count[c] = 0; accumulator[c] = 0m; } else { accumulator[c] = th.Math.Zero; count[c] = 0; } break; case AggregateFunction.Product: accumulator[c] = th.Math.One; break; } } align[c] = th != null?CalcAlignment(Columns[c].CellAlignment, th) : CellAlignment.Right; } Data.Row prevRow = null; for (int r = 0, rowIndex = 0; r <= rows.Length; r++, rowIndex++) { var row = r < rows.Length ? rows[r] : null; var closeToGroupLevel = row != null ? groupData.Count : 0; if (prevRow != null && row != null) { for (int g = 0; g < groupData.Count; g++) { if (RowComparer.Compare(row, prevRow, groupData[g].Columns) != 0) { closeToGroupLevel = g; break; } } } //close higher groups first for (int g = groupData.Count - 1; g >= closeToGroupLevel; g--) { var gd = groupData[g]; if (gd.GroupOpen) { gd.GroupOpen = false; //close group if (gd.Group.ShowFooter) { for (int c = 0; c < Columns.Length; c++) { if (Columns[c].AggregateFunction == AggregateFunction.Avg) { gd.GroupAccumulator[c] = CalculateAggregate(Columns[c].AggregateFunction, gd.GroupAccumulator[c], gd.GroupCounter[c]); } var style = gd.GetFooterCellStyle(Columns[c].ColumnType); switch (Columns[c].FooterType) { case ColumnFooterType.FooterText: cells.Add(new Cell { Column = pos.Col + c, Row = pos.Row, FormattedValue = Columns[c].FooterText, Value = Columns[c].FooterText, CellStyleIndex = style, Alignment = Columns[c].FooterAlignment }); break; case ColumnFooterType.AggregateValue: String fv = (Columns[c].FooterFormat != null) ? String.Format(Columns[c].FooterFormat, gd.GroupAccumulator[c]) : (gd.GroupAccumulator[c] != null ? gd.GroupAccumulator[c].ToString() : null); var al = Columns[c]._DataFieldIndex >= 0 ? CalcAlignment(Columns[c].FooterAlignment, data.TypeHelper[Columns[c]._DataFieldIndex]) : CellAlignment.Auto; cells.Add(new Cell { Column = pos.Col + c, Row = pos.Row, FormattedValue = fv, Value = gd.GroupAccumulator[c], CellStyleIndex = style, Alignment = al, Format = Columns[c].FooterFormat }); break; case ColumnFooterType.GroupFooter: String gfv = gd.PreparedFooterColumns == null ? gd.PreparedFooterFormat : String.Format(gd.PreparedFooterFormat, prevRow.GetMany(gd.PreparedFooterColumns)); var gal = Columns[c]._DataFieldIndex >= 0 ? CalcAlignment(Columns[c].FooterAlignment, data.TypeHelper[Columns[c]._DataFieldIndex]) : CellAlignment.Auto; cells.Add(new Cell { Column = pos.Col + c, Row = pos.Row, FormattedValue = gfv, Value = gfv, CellStyleIndex = style, Alignment = gal }); break; } if (Columns[c].FooterColSpan > 1) { report.MergedCells.Add(new Rect { Col1 = pos.Col + c, Col2 = pos.Col + c + Columns[c].FooterColSpan - 1, Row1 = pos.Row, Row2 = pos.Row }); c += Columns[c].FooterColSpan - 1; } } pos.Row++; } } } for (int g = 0; g < groupData.Count; g++) { var gd = groupData[g]; //add row if (row != null) { if (!gd.GroupOpen) { gd.GroupOpen = true; rowIndex = 0; if (gd.Group.ShowCaption) { String caption = gd.PreparedCaptionColumns == null ? gd.PreparedCaptionFormat : String.Format(gd.PreparedCaptionFormat, row.GetMany(gd.PreparedCaptionColumns)); cells.Add(new Cell { Column = pos.Col, Row = pos.Row, FormattedValue = caption, Value = caption, CellStyleIndex = gd.GetCaptionStyle() }); report.MergedCells.Add(new Rect { Col1 = pos.Col, Col2 = pos.Col + Columns.Length - 1, Row1 = pos.Row, Row2 = pos.Row }); pos.Row++; } if (gd.Group.ShowHeader) { for (int c = 0; c < Columns.Length; c++) { var ht = Columns[c].HeaderText; var style = gd.GetHeaderCellStyle(Columns[c].ColumnType); var a = Columns[c]._DataFieldIndex >= 0 ? CalcAlignment(Columns[c].HeaderAlignment, data.TypeHelper[Columns[c]._DataFieldIndex]) : CellAlignment.Right; cells.Add(new Cell { Column = pos.Col + c, Row = pos.Row, FormattedValue = ht, Value = ht, CellStyleIndex = style, Alignment = a }); } pos.Row++; } gd.GroupAccumulator = new object[Columns.Length]; gd.GroupCounter = new decimal[Columns.Length]; //reset group accumulator for (int c = 0; c < Columns.Length; c++) { var th = Columns[c]._DataFieldIndex >= 0 ? data.TypeHelper[Columns[c]._DataFieldIndex] : null; if (th != null) { switch (Columns[c].AggregateFunction) { case AggregateFunction.Sum: gd.GroupAccumulator[c] = th.Math.Zero; break; case AggregateFunction.Count: gd.GroupAccumulator[c] = 0; break; case AggregateFunction.Avg: if (Columns[c].AggregateWeightDataField != null) { gd.GroupAccumulator[c] = 0m; gd.GroupCounter[c] = 0; } else { gd.GroupAccumulator[c] = th.Math.Zero; gd.GroupCounter[c] = 0; } break; case AggregateFunction.Product: gd.GroupAccumulator[c] = th.Math.One; break; } } } } for (int c = 0; c < Columns.Length; c++) { var dfi = Columns[c]._DataFieldIndex; var v = row[dfi]; var th = dfi >= 0 ? data.TypeHelper[dfi] : null; if (th != null) { switch (Columns[c].AggregateFunction) { case AggregateFunction.Sum: gd.GroupAccumulator[c] = th.Math.SumNullAsZero(gd.GroupAccumulator[c], v); break; case AggregateFunction.Count: if (v != null) { gd.GroupAccumulator[c] = (int)gd.GroupAccumulator[c] + 1; } break; case AggregateFunction.Product: gd.GroupAccumulator[c] = th.Math.Multiply(gd.GroupAccumulator[c], v); break; case AggregateFunction.Avg: if (v != null) { if (Columns[c].AggregateWeightDataField != null) { var w = row[Columns[c]._AggregateWeightDataFieldIndex]; if (w != null) { var wd = Convert.ToDecimal(w); var wv = wd * Convert.ToDecimal(v); gd.GroupAccumulator[c] = (decimal)gd.GroupAccumulator[c] + wv; gd.GroupCounter[c] += wd; } } else { gd.GroupAccumulator[c] = th.Math.Sum(gd.GroupAccumulator[c], v); ++gd.GroupCounter[c]; } } break; case AggregateFunction.Min: if (gd.GroupAccumulator[c] == null) { gd.GroupAccumulator[c] = v; } else if (v != null) { gd.GroupAccumulator[c] = th.Math.Min(gd.GroupAccumulator[c], v); } break; case AggregateFunction.Max: if (gd.GroupAccumulator[c] == null) { gd.GroupAccumulator[c] = v; } else if (v != null) { gd.GroupAccumulator[c] = th.Math.Max(gd.GroupAccumulator[c], v); } break; } } switch (Columns[c].CellDisplayMode) { default: case CellDisplayMode.Normal: v = Columns[c].DataField == "#" ? rowIndex + 1 : row[dfi]; break; case CellDisplayMode.RowNumber: v = rowIndex + 1; break; case CellDisplayMode.AccumulatorValue: v = CalculateAggregate(Columns[c].AggregateFunction, gd.GroupAccumulator[c], gd.GroupCounter[c]); break; } CellStyle addStyle = null; if (Columns[c].ConditionalFormatting != null) { addStyle = Columns[c].ConditionalFormatting(v); } String fv = (Columns[c].Format != null) ? String.Format(Columns[c].Format, v) : (v != null ? v.ToString() : null); if (g + 1 == groupData.Count) { cells.Add(new Cell { Column = pos.Col + c, Row = pos.Row, Value = v, FormattedValue = fv, CellStyleIndex = Columns[c].ColumnType == TableColumnType.HeaderColumn ? CellStyleIndex.TableRowHeader : Columns[c].ColumnType == TableColumnType.FooterColumn ? CellStyleIndex.TableRowFooter : CellStyleIndex.TableRow, Alignment = align[c], Format = Columns[c].Format, CustomStyle = addStyle }); } } if (g + 1 == groupData.Count) { pos.Row++; } } } prevRow = row; } fm.GetRect(RowCol.Zero, 0, pos.Row - startRow); report.Cells.AddRange(cells); }