using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using FastReport.Utils;
using FastReport.Data;
namespace FastReport.Table
{
///
/// Represents a table object that consists of several rows and columns.
///
///
/// To add/remove columns, use the collection. To add/remove
/// rows, use the collection. To initialize a table with specified number of
/// columns and rows, use and properties.
/// To print a table in code, use the event. In the manual build
/// mode, you can use aggregate functions. The following functions available:
///
///
/// Aggregate function
/// Description
///
/// -
/// Sum(cell)
/// Calculates the sum of values in specified table cell.
///
/// -
/// Min(cell)
/// Calculates the minimum of values in specified table cell.
///
/// -
/// Max(cell)
/// Calculates the maximum of values in specified table cell.
///
/// -
/// Avg(cell)
/// Calculates the average of values in specified table cell.
///
/// -
/// Count(cell)
/// Calculates the number of repeats of a specified table cell.
///
///
/// To print aggregate value, place the aggregate function call in the table cell:
/// [Count(Cell2)].
///
public partial class TableObject : TableBase
{
#region Fields
private string manualBuildEvent;
private TableHelper helper;
private bool saveVisible;
private bool saveStateSkipped;
private bool manualBuildAutoSpans;
#endregion
#region Properties
///
/// Allows to print table rows/columns dynamically.
///
///
/// This event is used to handle the table print process in a code. Using special methods
/// like , you can print specified rows/columns.
///
/// First way is to repeat specified row(s) to get a table that will grow downwards.
/// To do this, you have to call the PrintRow method followed by the PrintColumns method.
///
/// Another way is to repeat the specified column(s) to get a table that grows sidewards.
/// To do this, call the PrintColumn method followed by the PrintRows method.
///
/// Finally, the third way is to repeat rows and columns. The table will grow downwards and
/// sidewards. To do this, call the PrintRow method followed by the PrintColumn
/// method (or vice versa).
///
///
///
/// When you print a table row-by-row, you must call one of the PrintColumn,
/// PrintColumns methods right after the PrintRow method.
/// In the same manner, when you print a table column-by-column, call one of the
/// PrintRow, PrintRows methods right after the PrintColumn method.
/// If you ignore this rule you will get an exception.
///
///
///
/// In this example, we will consider all three ways to print a table which has 3 rows and 3 columns.
/// Case 1: print a table downwards.
///
/// // print table header (the first row)
/// Table1.PrintRow(0);
/// Table1.PrintColumns();
/// // print table body (the second row)
/// for (int i = 0; i < 10; i++)
/// {
/// Table1.PrintRow(1);
/// Table1.PrintColumns();
/// }
/// // print table footer (the third row)
/// Table1.PrintRow(2);
/// Table1.PrintColumns();
///
///
/// Case 2: print a table sidewards.
///
/// // print table header (the first column)
/// Table1.PrintColumn(0);
/// Table1.PrintRows();
/// // print table body (the second column)
/// for (int i = 0; i < 10; i++)
/// {
/// Table1.PrintColumn(1);
/// Table1.PrintRows();
/// }
/// // print table footer (the third column)
/// Table1.PrintColumn(2);
/// Table1.PrintRows();
///
///
/// Case 3: print a table downwards and sidewards.
///
/// // print the first row with all its columns
/// Table1.PrintRow(0);
/// // print header column
/// Table1.PrintColumn(0);
/// // print 10 data columns
/// for (int i = 0; i < 10; i++)
/// {
/// Table1.PrintColumn(1);
/// }
/// // print footer column
/// Table1.PrintColumn(2);
///
/// // print table body (the second row)
/// for (int i = 0; i < 10; i++)
/// {
/// // print data row with all its columns
/// Table1.PrintRow(1);
/// Table1.PrintColumn(0);
/// for (int j = 0; j < 10; j++)
/// {
/// Table1.PrintColumn(1);
/// }
/// Table1.PrintColumn(2);
/// }
///
/// // print table footer (the third row)
/// Table1.PrintRow(2);
/// // again print all columns in the table footer
/// Table1.PrintColumn(0);
/// for (int i = 0; i < 10; i++)
/// {
/// Table1.PrintColumn(1);
/// }
/// Table1.PrintColumn(2);
///
///
public event EventHandler ManualBuild;
///
/// Gets or sets a script method name that will be used to handle the
/// event.
///
///
/// If you use this event, you must handle the table print process manually.
/// See the event for details.
///
[Category("Build")]
public string ManualBuildEvent
{
get { return manualBuildEvent; }
set { manualBuildEvent = value; }
}
///
/// Determines whether to manage cell spans automatically during manual build.
///
///
/// The default value for this property is true. If you set it to false, you need to manage
/// spans in your ManualBuild event handler.
///
[Category("Build")]
[DefaultValue(true)]
public bool ManualBuildAutoSpans
{
get { return manualBuildAutoSpans; }
set { manualBuildAutoSpans = value; }
}
///
public override int ColumnCount
{
get { return base.ColumnCount; }
set
{
base.ColumnCount = value;
CreateUniqueNames();
}
}
///
public override int RowCount
{
get { return base.RowCount; }
set
{
base.RowCount = value;
CreateUniqueNames();
}
}
internal bool IsManualBuild
{
get { return !String.IsNullOrEmpty(ManualBuildEvent) || ManualBuild != null; }
}
#endregion
#region Public Methods
///
public override void Assign(Base source)
{
base.Assign(source);
TableObject src = source as TableObject;
ManualBuildEvent = src.ManualBuildEvent;
ManualBuildAutoSpans = src.ManualBuildAutoSpans;
}
///
public override void Serialize(FRWriter writer)
{
TableObject c = writer.DiffObject as TableObject;
base.Serialize(writer);
if (ManualBuildEvent != c.ManualBuildEvent)
writer.WriteStr("ManualBuildEvent", ManualBuildEvent);
if (ManualBuildAutoSpans != c.ManualBuildAutoSpans)
writer.WriteBool("ManualBuildAutoSpans", ManualBuildAutoSpans);
}
#endregion
#region Report Engine
private string GetFunctionCode(string function)
{
string result = "";
switch (Report.ScriptLanguage)
{
case Language.CSharp:
result =
" private object " + function + "(TableCell cell)\r\n" +
" {\r\n" +
" return cell.Table." + function + "(cell);\r\n" +
" }\r\n\r\n";
break;
case Language.Vb:
result =
" Private Function " + function + "(ByVal cell As TableCell) As Object\r\n" +
" Return cell.Table." + function + "(cell)\r\n" +
" End Function\r\n\r\n";
break;
}
return result;
}
///
public override string GetCustomScript()
{
string result = "";
string[] functions = new string[] { "Sum", "Min", "Max", "Avg", "Count" };
foreach (string function in functions)
{
result += GetFunctionCode(function);
}
return result;
}
///
public override void SaveState()
{
saveVisible = Visible;
BandBase parent = Parent as BandBase;
saveStateSkipped = !Visible || (parent != null && !parent.Visible);
if (saveStateSkipped)
return;
if (!IsManualBuild)
{
base.SaveState();
}
else
{
// create the result table that will be rendered in the preview
SetResultTable(new TableResult());
ResultTable.Assign(this);
ResultTable.SetReport(Report);
helper = new TableHelper(this, ResultTable);
Visible = false;
if (parent != null && !PrintOnParent)
{
parent.Height = Top;
parent.CanGrow = false;
parent.CanShrink = false;
parent.AfterPrint += ResultTable.GeneratePages;
}
OnManualBuild(EventArgs.Empty);
}
}
///
public override void RestoreState()
{
BandBase parent = Parent as BandBase;
// SaveState was skipped, there is nothing to restore
if (saveStateSkipped)
return;
if (!IsManualBuild)
{
base.RestoreState();
}
else
{
if (parent != null && !PrintOnParent)
parent.AfterPrint -= ResultTable.GeneratePages;
helper = null;
ResultTable.Dispose();
SetResultTable(null);
Visible = saveVisible;
}
}
///
public override void GetData()
{
base.GetData();
if (!IsManualBuild)
{
for (int y = 0; y < Rows.Count; y++)
{
for (int x = 0; x < Columns.Count; x++)
{
this[x, y].GetData();
}
}
}
}
///
public override void OnAfterData(EventArgs e)
{
base.OnAfterData(e);
if (IsManualBuild && PrintOnParent)
ResultTable.AddToParent(Parent);
}
///
/// This method fires the ManualBuild event and the script code connected to the ManualBuildEvent.
///
/// Event data.
public void OnManualBuild(EventArgs e)
{
if (ManualBuild != null)
ManualBuild(this, e);
InvokeEvent(ManualBuildEvent, e);
}
///
/// Prints a row with specified index.
///
/// Index of a row to print.
///
/// See the event for more details.
///
public void PrintRow(int index)
{
if (!IsManualBuild)
throw new TableManualBuildException();
helper.PrintRow(index);
}
///
/// Prints rows with specified indices.
///
/// Indices of rows to print.
///
/// See the event for more details.
///
public void PrintRows(int[] indices)
{
foreach (int index in indices)
{
PrintRow(index);
}
}
///
/// Prints all rows.
///
///
/// See the event for more details.
///
public void PrintRows()
{
for (int i = 0; i < Rows.Count; i++)
{
PrintRow(i);
}
}
///
/// Prints a column with specified index.
///
/// Index of a column to print.
///
/// See the event for more details.
///
public void PrintColumn(int index)
{
if (!IsManualBuild)
throw new TableManualBuildException();
helper.PrintColumn(index);
}
///
/// Prints columns with specified indices.
///
/// Indices of columns to print.
///
/// See the event for more details.
///
public void PrintColumns(int[] indices)
{
foreach (int index in indices)
{
PrintColumn(index);
}
}
///
/// Prints all columns.
///
///
/// See the event for more details.
///
public void PrintColumns()
{
for (int i = 0; i < Columns.Count; i++)
{
PrintColumn(i);
}
}
///
/// Adds a page before rows or columns.
///
///
/// Call this method to insert a page break before the next row or column that you intend to print
/// using PrintRow(s) or PrintColumn(s) methods.
/// See the event for more details.
///
public void PageBreak()
{
if (!IsManualBuild)
throw new TableManualBuildException();
if (!Report.Engine.UnlimitedHeight && !Report.Engine.UnlimitedWidth)
helper.PageBreak();
}
#endregion
///
/// Initializes a new instance of the class.
///
public TableObject()
{
manualBuildEvent = "";
manualBuildAutoSpans = true;
}
}
}