123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- namespace FastReport.Table
- {
- internal class TableHelper
- {
- private TableObject sourceTable;
- private TableResult resultTable;
- private enum NowPrinting { None, Row, Column }
- private NowPrinting nowPrinting;
- private bool rowsPriority;
- private int originalRowIndex;
- private int originalColumnIndex;
- private int printingRowIndex;
- private int printingColumnIndex;
- private List<SpanData> columnSpans;
- private List<SpanData> rowSpans;
- private bool pageBreak;
- private bool AutoSpans
- {
- get { return sourceTable.ManualBuildAutoSpans; }
- }
- #region Build the Table
- public void PrintRow(int rowIndex)
- {
- originalRowIndex = rowIndex;
- if (nowPrinting == NowPrinting.None)
- {
- // we are at the start. Rows will now have priority over columns.
- rowsPriority = true;
- }
- if (rowsPriority)
- {
- switch (nowPrinting)
- {
- case NowPrinting.None:
- printingRowIndex = 0;
- break;
- case NowPrinting.Column:
- printingRowIndex++;
- break;
- case NowPrinting.Row:
- // we have two sequential calls of the PrintRow. But we must print
- // some columns...
- break;
- }
- // add new row, do not copy cells: it will be done in the PrintColumn.
- TableRow row = new TableRow();
- row.Assign(sourceTable.Rows[rowIndex]);
- row.PageBreak = pageBreak;
- resultTable.Rows.Add(row);
- columnSpans.Clear();
- }
- else
- {
- if (nowPrinting == NowPrinting.Column)
- {
- // this is the first row inside a column, reset the index
- printingRowIndex = 0;
- }
- else
- {
- // not the first row, increment the index
- printingRowIndex++;
- }
- TableRow row = null;
- if (resultTable.Rows.Count <= printingRowIndex)
- {
- // index is outside existing rows. Probably not all rows created yet,
- // we're at the start. Add new row.
- row = new TableRow();
- row.Assign(sourceTable.Rows[rowIndex]);
- resultTable.Rows.Add(row);
- }
- else
- {
- // do not create row, use existing one
- row = resultTable.Rows[printingRowIndex];
- }
- // apply page break
- row.PageBreak = pageBreak;
- // copy cells from the template to the result
- CopyCells(originalColumnIndex, originalRowIndex,
- printingColumnIndex, printingRowIndex);
- }
- nowPrinting = NowPrinting.Row;
- pageBreak = false;
- }
- public void PrintColumn(int columnIndex)
- {
- originalColumnIndex = columnIndex;
- if (nowPrinting == NowPrinting.None)
- {
- // we are at the start. Columns will now have priority over rows.
- rowsPriority = false;
- }
- if (!rowsPriority)
- {
- switch (nowPrinting)
- {
- case NowPrinting.None:
- printingColumnIndex = 0;
- break;
- case NowPrinting.Column:
- // we have two sequential calls of the PrintColumn. But we must print
- // some rows...
- break;
- case NowPrinting.Row:
- printingColumnIndex++;
- break;
- }
- // add new column, do not copy cells: it will be done in the PrintRow.
- TableColumn column = new TableColumn();
- column.Assign(sourceTable.Columns[columnIndex]);
- column.PageBreak = pageBreak;
- resultTable.Columns.Add(column);
- rowSpans.Clear();
- }
- else
- {
- if (nowPrinting == NowPrinting.Row)
- {
- // this is the first column inside a row, reset the index
- printingColumnIndex = 0;
- }
- else
- {
- // not the first column, increment the index
- printingColumnIndex++;
- }
- TableColumn column = null;
- if (resultTable.Columns.Count <= printingColumnIndex)
- {
- // index is outside existing columns. Probably not all columns
- // created yet, we're at the start. Add new column.
- column = new TableColumn();
- column.Assign(sourceTable.Columns[columnIndex]);
- resultTable.Columns.Add(column);
- }
- else
- {
- // do not create column, use existing one
- column = resultTable.Columns[printingColumnIndex];
- }
- // apply page break
- column.PageBreak = pageBreak;
- // copy cells from the template to the result
- CopyCells(originalColumnIndex, originalRowIndex,
- printingColumnIndex, printingRowIndex);
- }
- nowPrinting = NowPrinting.Column;
- pageBreak = false;
- }
- public void PageBreak()
- {
- pageBreak = true;
- }
- private void CopyCells(int originalColumnIndex, int originalRowIndex,
- int resultColumnIndex, int resultRowIndex)
- {
- TableCell cell = sourceTable[originalColumnIndex, originalRowIndex];
- TableCellData cellTo = resultTable.GetCellData(resultColumnIndex, resultRowIndex);
- sourceTable.PrintingCell = cellTo;
- bool needData = true;
- if (AutoSpans)
- {
- if (rowsPriority)
- {
- // We are printing columns inside a row. Check if we need to finish the column cell.
- if (columnSpans.Count > 0)
- {
- SpanData spanData = columnSpans[0];
- // check if we are printing the last column of the cell's span. From now, we will not accept
- // the first column.
- if (originalColumnIndex == spanData.originalCellOrigin.X + spanData.originalCell.ColSpan - 1)
- spanData.finishFlag = true;
- if ((spanData.finishFlag && originalColumnIndex == spanData.originalCellOrigin.X) ||
- (originalColumnIndex < spanData.originalCellOrigin.X ||
- originalColumnIndex > spanData.originalCellOrigin.X + spanData.originalCell.ColSpan - 1))
- columnSpans.Clear();
- else
- {
- spanData.resultCell.ColSpan++;
- needData = false;
- }
- }
- // add the column cell if it has ColSpan > 1
- if (cell.ColSpan > 1 && columnSpans.Count == 0)
- {
- SpanData spanData = new SpanData();
- columnSpans.Add(spanData);
- spanData.originalCell = cell;
- spanData.resultCell = cellTo;
- spanData.originalCellOrigin = new Point(originalColumnIndex, originalRowIndex);
- spanData.resultCellOrigin = new Point(resultColumnIndex, resultRowIndex);
- }
- // now check the row cells. Do this once for each row.
- if (printingColumnIndex == 0)
- {
- for (int i = 0; i < rowSpans.Count; i++)
- {
- SpanData spanData = rowSpans[i];
- // check if we are printing the last row of the cell's span. From now, we will not accept
- // the first row.
- if (originalRowIndex == spanData.originalCellOrigin.Y + spanData.originalCell.RowSpan - 1)
- spanData.finishFlag = true;
- if ((spanData.finishFlag && originalRowIndex == spanData.originalCellOrigin.Y) ||
- (originalRowIndex < spanData.originalCellOrigin.Y ||
- originalRowIndex > spanData.originalCellOrigin.Y + spanData.originalCell.RowSpan - 1))
- {
- rowSpans.RemoveAt(i);
- i--;
- }
- else
- spanData.resultCell.RowSpan++;
- }
- }
- // check if we should skip current cell because it is inside a span
- for (int i = 0; i < rowSpans.Count; i++)
- {
- SpanData spanData = rowSpans[i];
- if (resultColumnIndex >= spanData.resultCellOrigin.X &&
- resultColumnIndex <= spanData.resultCellOrigin.X + spanData.resultCell.ColSpan - 1 &&
- resultRowIndex >= spanData.resultCellOrigin.Y &&
- resultRowIndex <= spanData.resultCellOrigin.Y + spanData.resultCell.RowSpan)
- {
- needData = false;
- break;
- }
- }
- // add the row cell if it has RowSpan > 1 and not added yet
- if (cell.RowSpan > 1 && needData)
- {
- SpanData spanData = new SpanData();
- rowSpans.Add(spanData);
- spanData.originalCell = cell;
- spanData.resultCell = cellTo;
- spanData.originalCellOrigin = new Point(originalColumnIndex, originalRowIndex);
- spanData.resultCellOrigin = new Point(resultColumnIndex, resultRowIndex);
- }
- }
- else
- {
- // We are printing rows inside a column. Check if we need to finish the row cell.
- if (rowSpans.Count > 0)
- {
- SpanData spanData = rowSpans[0];
- // check if we are printing the last row of the cell's span. From now, we will not accept
- // the first row.
- if (originalRowIndex == spanData.originalCellOrigin.Y + spanData.originalCell.RowSpan - 1)
- spanData.finishFlag = true;
- if ((spanData.finishFlag && originalRowIndex == spanData.originalCellOrigin.Y) ||
- (originalRowIndex < spanData.originalCellOrigin.Y ||
- originalRowIndex > spanData.originalCellOrigin.Y + spanData.originalCell.RowSpan - 1))
- rowSpans.Clear();
- else
- {
- spanData.resultCell.RowSpan++;
- needData = false;
- }
- }
- // add the row cell if it has RowSpan > 1
- if (cell.RowSpan > 1 && rowSpans.Count == 0)
- {
- SpanData spanData = new SpanData();
- rowSpans.Add(spanData);
- spanData.originalCell = cell;
- spanData.resultCell = cellTo;
- spanData.originalCellOrigin = new Point(originalColumnIndex, originalRowIndex);
- spanData.resultCellOrigin = new Point(resultColumnIndex, resultRowIndex);
- }
- // now check the column cells. Do this once for each column.
- if (printingRowIndex == 0)
- {
- for (int i = 0; i < columnSpans.Count; i++)
- {
- SpanData spanData = columnSpans[i];
- // check if we are printing the last column of the cell's span. From now, we will not accept
- // the first column.
- if (originalColumnIndex == spanData.originalCellOrigin.X + spanData.originalCell.ColSpan - 1)
- spanData.finishFlag = true;
- if ((spanData.finishFlag && originalColumnIndex == spanData.originalCellOrigin.X) ||
- (originalColumnIndex < spanData.originalCellOrigin.X ||
- originalColumnIndex > spanData.originalCellOrigin.X + spanData.originalCell.ColSpan - 1))
- {
- columnSpans.RemoveAt(i);
- i--;
- }
- else
- spanData.resultCell.ColSpan++;
- }
- }
- // check if we should skip current cell because it is inside a span
- for (int i = 0; i < columnSpans.Count; i++)
- {
- SpanData spanData = columnSpans[i];
- if (resultColumnIndex >= spanData.resultCellOrigin.X &&
- resultColumnIndex <= spanData.resultCellOrigin.X + spanData.resultCell.ColSpan - 1 &&
- resultRowIndex >= spanData.resultCellOrigin.Y &&
- resultRowIndex <= spanData.resultCellOrigin.Y + spanData.resultCell.RowSpan - 1)
- {
- needData = false;
- break;
- }
- }
- // add the column cell if it has ColSpan > 1 and not added yet
- if (cell.ColSpan > 1 && needData)
- {
- SpanData spanData = new SpanData();
- columnSpans.Add(spanData);
- spanData.originalCell = cell;
- spanData.resultCell = cellTo;
- spanData.originalCellOrigin = new Point(originalColumnIndex, originalRowIndex);
- spanData.resultCellOrigin = new Point(resultColumnIndex, resultRowIndex);
- }
- }
- }
- else
- {
- cellTo.ColSpan = cell.ColSpan;
- cellTo.RowSpan = cell.RowSpan;
- }
- if (needData)
- {
- cell.SaveState();
- cell.GetData();
- cellTo.RunTimeAssign(cell, true);
- cell.RestoreState();
- }
- }
- #endregion
- #region Aggregate Functions
- #endregion
- public TableHelper(TableObject source, TableResult result)
- {
- sourceTable = source;
- resultTable = result;
- columnSpans = new List<SpanData>();
- rowSpans = new List<SpanData>();
- }
- private class SpanData
- {
- public TableCell originalCell;
- public TableCellData resultCell;
- public Point originalCellOrigin;
- public Point resultCellOrigin;
- public bool finishFlag;
- }
- }
- }
|