123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using FastReport.Gauge;
- using FastReport.Gauge.Simple.Progress;
- #if MSCHART
- using FastReport.MSChart;
- #endif
- using FastReport.Table;
- namespace FastReport.AdvMatrix
- {
- internal static class ResultBuilder
- {
- private static int EnumColumnData(HeaderData root, int columnIndex, int rowIndex, Action<HeaderData, int, int, bool> func)
- {
- foreach (HeaderData d in root)
- {
- func(d, columnIndex, rowIndex, true);
- if (d.Items.Count > 0)
- {
- if (d.Descriptor.Stepped)
- columnIndex = EnumColumnData(d, columnIndex + 1, rowIndex, func);
- else
- columnIndex = EnumColumnData(d, columnIndex, rowIndex + 1, func);
- }
- columnIndex++;
- }
- return columnIndex - 1;
- }
- private static int EnumRowData(HeaderData root, int columnIndex, int rowIndex, Action<HeaderData, int, int, bool> func)
- {
- foreach (HeaderData d in root)
- {
- func(d, columnIndex, rowIndex, false);
- if (d.Items.Count > 0)
- {
- if (d.Descriptor.Stepped)
- rowIndex = EnumRowData(d, columnIndex, rowIndex + 1, func);
- else
- rowIndex = EnumRowData(d, columnIndex + 1, rowIndex, func);
- }
- rowIndex++;
- }
- return rowIndex - 1;
- }
- private static void PrintHeaderCell(AdvMatrixObject matrix, HeaderData item, TableCellData resultCell, bool isColumn, bool isEven)
- {
- HeaderDescriptor descr = item.Descriptor;
- TableCell templateCell = descr.TemplateCell;
- if (matrix.DataSource != null)
- matrix.DataSource.CurrentRowNo = item.DataRowNo;
- matrix.RowNo = item.RowNo;
- matrix.ItemCount = item.ItemCount;
- MatrixCollapseButton btn = templateCell.GetCollapseButton();
- if (btn != null)
- matrix.ItemCount = btn.GetLinkedItemsCount(item);
- templateCell.SaveState();
- if (isEven)
- templateCell.ApplyEvenStyle();
- object value = item.Value;
- if (value != null)
- {
- templateCell.SetValue(value);
- templateCell.Text = templateCell.Format.FormatValue(value);
- }
- if (!String.IsNullOrEmpty(descr.DisplayText))
- {
- templateCell.Text = descr.DisplayText;
- templateCell.AllowExpressions = true;
- }
- templateCell.GetData();
- if (String.IsNullOrEmpty(templateCell.Hyperlink.Expression) &&
- (templateCell.Hyperlink.Kind == HyperlinkKind.DetailReport ||
- templateCell.Hyperlink.Kind == HyperlinkKind.DetailPage ||
- templateCell.Hyperlink.Kind == HyperlinkKind.Custom))
- templateCell.Hyperlink.Value = templateCell.Text;
- if (templateCell.Objects != null)
- {
- foreach (Base c in templateCell.Objects)
- {
- if (c is MatrixButton)
- {
- MatrixButton b = c as MatrixButton;
- b.IsColumn = isColumn;
- b.Index = item.Index;
- }
- if (c is MatrixCollapseButton)
- {
- MatrixCollapseButton b = c as MatrixCollapseButton;
- foreach (HeaderDataList dl in b.GetLinkedItems(item))
- {
- b.Collapsed = !dl.Visible;
- break;
- }
- }
- if (c is MatrixSortButton)
- {
- MatrixSortButton b = c as MatrixSortButton;
- b.Sort = SortOrder.None;
- InteractiveSortInfo info = matrix.Data.InteractiveSort;
- if (isColumn && item.Index == info.Column.Index)
- b.Sort = info.Column.Sort;
- if (!isColumn && item.Index == info.Row.Index)
- b.Sort = info.Row.Sort;
- }
- }
- }
- resultCell.RunTimeAssign(templateCell, true);
- templateCell.RestoreState();
- }
- private static void PrintCornerCell(TableCell templateCell, TableCellData resultCell)
- {
- templateCell.SaveState();
- templateCell.GetData();
- resultCell.RunTimeAssign(templateCell, true);
- templateCell.RestoreState();
- }
- private static void PrintDataCell(AdvMatrixObject matrix, TableCell templateCell, TableCellData resultCell, bool isEven)
- {
- templateCell.SaveState();
- if (isEven)
- templateCell.ApplyEvenStyle();
- CellDescriptor descriptor = templateCell.GetDescriptor();
- switch (descriptor.ContentType)
- {
- case CellContentType.MixedText:
- templateCell.AllowExpressions = true;
- templateCell.Text = descriptor.Text;
- break;
- case CellContentType.Aggregate:
- templateCell.SetValue(descriptor.Aggregates[0].GetValue(matrix.Data.Context.ColumnItem.Index, matrix.Data.Context.RowItem.Index));
- templateCell.Text = templateCell.FormatValue(templateCell.Value);
- break;
- case CellContentType.SingleExpression:
- templateCell.SetValue(matrix.Report.Calc(descriptor.Text));
- templateCell.Text = templateCell.FormatValue(templateCell.Value);
- break;
- }
- templateCell.GetData();
- ProcessCellObjects(templateCell);
- if (String.IsNullOrEmpty(templateCell.Hyperlink.Expression) &&
- (templateCell.Hyperlink.Kind == HyperlinkKind.DetailReport ||
- templateCell.Hyperlink.Kind == HyperlinkKind.DetailPage ||
- templateCell.Hyperlink.Kind == HyperlinkKind.Custom))
- {
- string hyperlinkValue = "";
- string separator = templateCell.Hyperlink.ValuesSeparator;
- foreach (object obj in matrix.ColumnValues)
- {
- hyperlinkValue += obj.ToString() + separator;
- }
- foreach (object obj in matrix.RowValues)
- {
- hyperlinkValue += obj.ToString() + separator;
- }
- templateCell.Hyperlink.Value = hyperlinkValue.Substring(0, hyperlinkValue.Length - separator.Length);
- }
- resultCell.RunTimeAssign(templateCell, true);
- templateCell.RestoreState();
- resultCell.ColSpan = templateCell.ColSpan;
- resultCell.RowSpan = templateCell.RowSpan;
- }
- private static IList ReduceValues(this IList list, int valuesCount)
- {
- int ratio = list.Count / valuesCount;
- if (ratio < 2)
- return list;
- ArrayList reducedList = new ArrayList();
- for (int i = 0; i < list.Count; i += ratio)
- {
- dynamic v = list[i];
- for (int j = 0; j < ratio && i + j < list.Count; j++)
- {
- if ((dynamic)list[i + j] > v)
- v = list[i + j];
- }
- reducedList.Add(v);
- }
- return reducedList;
- }
- private static void ProcessCellObjects(TableCell templateCell)
- {
- if (templateCell.Objects != null)
- {
- foreach (ReportComponentBase c in templateCell.Objects)
- {
- #if MSCHART
- MSChartObject chart = c as MSChartObject;
- if (chart != null && chart.Series.Count == 1)
- {
- chart.Series[0].ClearValues();
- if (templateCell.Value is IList)
- {
- IList list = (templateCell.Value as IList).ReduceValues((int)chart.Width / 3);
- for (int i = 0; i < list.Count; i++)
- {
- chart.Series[0].AddValue(i, list[i]);
- }
- }
- templateCell.Text = "";
- }
- #endif
- GaugeObject gauge = c as GaugeObject;
- if (gauge != null)
- {
- if (templateCell.Value == null || templateCell.Value is DBNull)
- gauge.Visible = false;
- else
- gauge.Value = (double)(dynamic)templateCell.Value;
- templateCell.Text = "";
- }
- }
- }
- }
- public static void BuildResult(AdvMatrixObject matrix)
- {
- TableResult resultTable = matrix.ResultTable;
- int cornerWidth = matrix.Data.Rows.Size;
- int cornerHeight = matrix.Data.Columns.Size;
- resultTable.FixedColumns = cornerWidth;
- resultTable.FixedRows = cornerHeight;
- // rows/columns in the corner area. Enumerate on descriptors to do it fast.
- // We need this code because some rows and columns may be invisible due to its collapsed state,
- // so its properties will not be assigned to resultTable
- resultTable.ColumnCount = cornerWidth;
- resultTable.RowCount = cornerHeight;
- Action<HeaderDescriptor, int, int, bool> func = (d, columnIndex, rowIndex, isColumn) =>
- {
- if (!isColumn && d.TemplateColumn != null)
- resultTable.Columns[columnIndex].Assign(d.TemplateColumn);
- if (isColumn && d.TemplateRow != null)
- resultTable.Rows[rowIndex].Assign(d.TemplateRow);
- };
- TemplateBuilder.EnumColumnDescriptors(matrix.Data.Columns.Descriptor, cornerWidth, 0, func);
- TemplateBuilder.EnumRowDescriptors(matrix.Data.Rows.Descriptor, 0, cornerHeight, func);
- // rows/columns
- Action<HeaderData, int, int, bool> func1 = (data, columnIndex, rowIndex, isColumn) =>
- {
- // create resultTable columns and rows
- while (columnIndex >= resultTable.Columns.Count)
- resultTable.Columns.Add(new TableColumn());
- while (rowIndex >= resultTable.Rows.Count)
- resultTable.Rows.Add(new TableRow());
- // assign properties from existing template columns/rows.
- // The same assignment may occur several times, but it's a cheap operation so it's ok
- HeaderDescriptor d = data.Descriptor;
- if (isColumn && d.TemplateColumn != null)
- resultTable.Columns[columnIndex].Assign(d.TemplateColumn);
- if (!isColumn && d.TemplateRow != null)
- resultTable.Rows[rowIndex].Assign(d.TemplateRow);
- // page breaks
- if (d.PageBreak && data.RowNo > 1)
- {
- if (isColumn)
- resultTable.Columns[columnIndex].PageBreak = true;
- else
- resultTable.Rows[rowIndex].PageBreak = true;
- }
- };
- EnumColumnData(matrix.Data.Columns.Data, cornerWidth, 0, func1);
- EnumRowData(matrix.Data.Rows.Data, 0, cornerHeight, func1);
- // corner cells
- for (int left = 0; left < cornerWidth; left++)
- {
- for (int top = 0; top < cornerHeight; top++)
- {
- TableCellData resultCell = resultTable.GetCellData(left, top);
- TableCell templateCell = matrix[left, top];
- PrintCornerCell(templateCell, resultCell);
- // do not allow spans to go outside corner area. Fix template cells as well (else we will get empty cells in the header area)
- templateCell.ColSpan = Math.Min(templateCell.ColSpan, cornerWidth - left);
- templateCell.RowSpan = Math.Min(templateCell.RowSpan, cornerHeight - top);
- resultCell.ColSpan = templateCell.ColSpan;
- resultCell.RowSpan = templateCell.RowSpan;
- }
- }
- // header cells
- Action<HeaderData, int, int, bool> func2 = (data, columnIndex, rowIndex, isColumn) =>
- {
- TableCellData resultCell = resultTable.GetCellData(columnIndex, rowIndex);
- // required check for MergeSingleItem
- if (resultTable.IsInsideSpan(resultCell.Cell))
- return;
- PrintHeaderCell(matrix, data, resultCell, isColumn, (isColumn ? columnIndex - cornerWidth : rowIndex - cornerHeight) % 2 == 0);
- HeaderDescriptor descr = data.Descriptor;
- if (isColumn)
- {
- resultCell.ColSpan = data.Span;
- if (data.Items.Count == 0 || (descr.MergeSingleItem && data.TerminalItems.Count == 1) || descr.Stepped)
- resultCell.RowSpan = cornerHeight - rowIndex;
- else if (descr.MergeSingleItem && data.ItemCount == 1)
- resultCell.RowSpan = 2;
- }
- else
- {
- resultCell.RowSpan = data.Span;
- if (data.Items.Count == 0 || (descr.MergeSingleItem && data.TerminalItems.Count == 1) || descr.Stepped)
- resultCell.ColSpan = cornerWidth - columnIndex;
- else if (descr.MergeSingleItem && data.ItemCount == 1)
- resultCell.ColSpan = 2;
- }
- if (descr.ColSpan > 0)
- resultCell.ColSpan = descr.ColSpan;
- if (descr.RowSpan > 0)
- resultCell.RowSpan = descr.RowSpan;
- };
- EnumColumnData(matrix.Data.Columns.Data, cornerWidth, 0, func2);
- EnumRowData(matrix.Data.Rows.Data, 0, cornerHeight, func2);
- // data cells
- List<HeaderData> columnTerminalItems = matrix.Data.Columns.Data.TerminalItems;
- List<HeaderData> rowTerminalItems = matrix.Data.Rows.Data.TerminalItems;
- matrix.ColumnIndex = 0;
- foreach (HeaderData columnItem in columnTerminalItems)
- {
- matrix.RowIndex = 0;
- matrix.ColumnValues = columnItem.Values;
- foreach (HeaderData rowItem in rowTerminalItems)
- {
- matrix.RowValues = rowItem.Values;
- TableCellData resultCell = resultTable.GetCellData(matrix.ColumnIndex + cornerWidth, matrix.RowIndex + cornerHeight);
- TableCell templateCell = matrix[columnItem.Descriptor.TemplateColumn.Index, rowItem.Descriptor.TemplateRow.Index];
- // set context required by aggregate calculation
- matrix.Data.Context.Descriptor = templateCell.GetDescriptor();
- matrix.Data.Context.ColumnItem = columnItem;
- matrix.Data.Context.RowItem = rowItem;
- if (matrix.DataSource != null)
- matrix.DataSource.CurrentRowNo = matrix.DataRowPriority == HeaderPriority.Columns ? columnItem.DataRowNo : rowItem.DataRowNo;
- int evenStyleIndex = matrix.EvenStylePriority == HeaderPriority.Columns ? matrix.ColumnIndex : matrix.RowIndex;
- PrintDataCell(matrix, templateCell, resultCell, evenStyleIndex % 2 == 0);
- matrix.RowIndex++;
- }
- matrix.ColumnIndex++;
- }
- }
- }
- }
|