Repository navigation
Expand file tree
/
Copy pathTableObject.cs
More file actions
492 lines (453 loc) · 16.2 KB
/
Copy pathTableObject.cs
File metadata and controls
492 lines (453 loc) · 16.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
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
{
/// <summary>
/// Represents a table object that consists of several rows and columns.
/// </summary>
/// <remarks>
/// <para/>To add/remove columns, use the <see cref="TableBase.Columns"/> collection. To add/remove
/// rows, use the <see cref="TableBase.Rows"/> collection. To initialize a table with specified number of
/// columns and rows, use <see cref="ColumnCount"/> and <see cref="RowCount"/> properties.
/// <para/>To print a table in code, use the <see cref="ManualBuild"/> event. In the manual build
/// mode, you can use aggregate functions. The following functions available:
/// <list type="table">
/// <listheader>
/// <term>Aggregate function</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>Sum(cell)</term>
/// <description>Calculates the sum of values in specified table cell.</description>
/// </item>
/// <item>
/// <term>Min(cell)</term>
/// <description>Calculates the minimum of values in specified table cell.</description>
/// </item>
/// <item>
/// <term>Max(cell)</term>
/// <description>Calculates the maximum of values in specified table cell.</description>
/// </item>
/// <item>
/// <term>Avg(cell)</term>
/// <description>Calculates the average of values in specified table cell.</description>
/// </item>
/// <item>
/// <term>Count(cell)</term>
/// <description>Calculates the number of repeats of a specified table cell.</description>
/// </item>
/// </list>
/// <para/>To print aggregate value, place the aggregate function call in the table cell:
/// <c>[Count(Cell2)]</c>.
/// </remarks>
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
/// <summary>
/// Allows to print table rows/columns dynamically.
/// </summary>
/// <remarks>
/// This event is used to handle the table print process in a code. Using special methods
/// like <see cref="PrintRow"/>, <see cref="PrintColumn"/> you can print specified rows/columns.
///
/// <para/>First way is to repeat specified row(s) to get a table that will grow downwards.
/// To do this, you have to call the <b>PrintRow</b> method followed by the <b>PrintColumns</b> method.
///
/// <para/>Another way is to repeat the specified column(s) to get a table that grows sidewards.
/// To do this, call the <b>PrintColumn</b> method followed by the <b>PrintRows</b> method.
///
/// <para/>Finally, the third way is to repeat rows and columns. The table will grow downwards and
/// sidewards. To do this, call the <b>PrintRow</b> method followed by the <b>PrintColumn</b>
/// method (or vice versa).
///
/// <para/>
/// <note type="caution">
/// When you print a table row-by-row, you must call one of the <b>PrintColumn</b>,
/// <b>PrintColumns</b> methods right after the <b>PrintRow</b> method.
/// In the same manner, when you print a table column-by-column, call one of the
/// <b>PrintRow</b>, <b>PrintRows</b> methods right after the <b>PrintColumn</b> method.
/// If you ignore this rule you will get an exception.
/// </note>
/// </remarks>
/// <example>
/// In this example, we will consider all three ways to print a table which has 3 rows and 3 columns.
/// <para/>Case 1: print a table downwards.
/// <code>
/// // 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();
/// </code>
///
/// <para/>Case 2: print a table sidewards.
/// <code>
/// // 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();
/// </code>
///
/// <para/>Case 3: print a table downwards and sidewards.
/// <code>
/// // 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);
/// </code>
/// </example>
public event EventHandler ManualBuild;
/// <summary>
/// Gets or sets a script method name that will be used to handle the
/// <see cref="ManualBuild"/> event.
/// </summary>
/// <remarks>
/// If you use this event, you must handle the table print process manually.
/// See the <see cref="ManualBuild"/> event for details.
/// </remarks>
[Category("Build")]
public string ManualBuildEvent
{
get { return manualBuildEvent; }
set { manualBuildEvent = value; }
}
/// <summary>
/// Determines whether to manage cell spans automatically during manual build.
/// </summary>
/// <remarks>
/// The default value for this property is <b>true</b>. If you set it to <b>false</b>, you need to manage
/// spans in your ManualBuild event handler.
/// </remarks>
[Category("Build")]
[DefaultValue(true)]
public bool ManualBuildAutoSpans
{
get { return manualBuildAutoSpans; }
set { manualBuildAutoSpans = value; }
}
/// <inheritdoc/>
public override int ColumnCount
{
get { return base.ColumnCount; }
set
{
base.ColumnCount = value;
CreateUniqueNames();
}
}
/// <inheritdoc/>
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
/// <inheritdoc/>
public override void Assign(Base source)
{
base.Assign(source);
TableObject src = source as TableObject;
ManualBuildEvent = src.ManualBuildEvent;
ManualBuildAutoSpans = src.ManualBuildAutoSpans;
}
/// <inheritdoc/>
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;
}
/// <inheritdoc/>
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;
}
/// <inheritdoc/>
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);
}
}
/// <inheritdoc/>
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;
}
}
/// <inheritdoc/>
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();
}
}
}
}
/// <inheritdoc/>
public override void OnAfterData(EventArgs e)
{
base.OnAfterData(e);
if (IsManualBuild && PrintOnParent)
ResultTable.AddToParent(Parent);
}
/// <summary>
/// This method fires the <b>ManualBuild</b> event and the script code connected to the <b>ManualBuildEvent</b>.
/// </summary>
/// <param name="e">Event data.</param>
public void OnManualBuild(EventArgs e)
{
if (ManualBuild != null)
ManualBuild(this, e);
InvokeEvent(ManualBuildEvent, e);
}
/// <summary>
/// Prints a row with specified index.
/// </summary>
/// <param name="index">Index of a row to print.</param>
/// <remarks>
/// See the <see cref="ManualBuild"/> event for more details.
/// </remarks>
public void PrintRow(int index)
{
if (!IsManualBuild)
throw new TableManualBuildException();
helper.PrintRow(index);
}
/// <summary>
/// Prints rows with specified indices.
/// </summary>
/// <param name="indices">Indices of rows to print.</param>
/// <remarks>
/// See the <see cref="ManualBuild"/> event for more details.
/// </remarks>
public void PrintRows(int[] indices)
{
foreach (int index in indices)
{
PrintRow(index);
}
}
/// <summary>
/// Prints all rows.
/// </summary>
/// <remarks>
/// See the <see cref="ManualBuild"/> event for more details.
/// </remarks>
public void PrintRows()
{
for (int i = 0; i < Rows.Count; i++)
{
PrintRow(i);
}
}
/// <summary>
/// Prints a column with specified index.
/// </summary>
/// <param name="index">Index of a column to print.</param>
/// <remarks>
/// See the <see cref="ManualBuild"/> event for more details.
/// </remarks>
public void PrintColumn(int index)
{
if (!IsManualBuild)
throw new TableManualBuildException();
helper.PrintColumn(index);
}
/// <summary>
/// Prints columns with specified indices.
/// </summary>
/// <param name="indices">Indices of columns to print.</param>
/// <remarks>
/// See the <see cref="ManualBuild"/> event for more details.
/// </remarks>
public void PrintColumns(int[] indices)
{
foreach (int index in indices)
{
PrintColumn(index);
}
}
/// <summary>
/// Prints all columns.
/// </summary>
/// <remarks>
/// See the <see cref="ManualBuild"/> event for more details.
/// </remarks>
public void PrintColumns()
{
for (int i = 0; i < Columns.Count; i++)
{
PrintColumn(i);
}
}
/// <summary>
/// Adds a page before rows or columns.
/// </summary>
/// <remarks>
/// Call this method to insert a page break before the next row or column that you intend to print
/// using <b>PrintRow(s)</b> or <b>PrintColumn(s)</b> methods.
/// See the <see cref="ManualBuild"/> event for more details.
/// </remarks>
public void PageBreak()
{
if (!IsManualBuild)
throw new TableManualBuildException();
if (!Report.Engine.UnlimitedHeight && !Report.Engine.UnlimitedWidth)
helper.PageBreak();
}
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="TableObject"/> class.
/// </summary>
public TableObject()
{
manualBuildEvent = "";
manualBuildAutoSpans = true;
}
}
}