FastReport

Форк
0
497 строк · 16.3 Кб
1
using System;
2
using System.Collections;
3
using System.Collections.Generic;
4
using System.Text;
5
using System.Drawing;
6
using System.ComponentModel;
7
using System.Drawing.Drawing2D;
8
using FastReport.Utils;
9
using FastReport.Data;
10

11
namespace FastReport.Table
12
{
13
    /// <summary>
14
    /// Represents a table object that consists of several rows and columns.
15
    /// </summary>
16
    /// <remarks>
17
    /// <para/>To add/remove columns, use the <see cref="TableBase.Columns"/> collection. To add/remove 
18
    /// rows, use the <see cref="TableBase.Rows"/> collection. To initialize a table with specified number of
19
    /// columns and rows, use <see cref="ColumnCount"/> and <see cref="RowCount"/> properties.
20
    /// <para/>To print a table in code, use the <see cref="ManualBuild"/> event. In the manual build
21
    /// mode, you can use aggregate functions. The following functions available:
22
    /// <list type="table">
23
    ///   <listheader>
24
    ///     <term>Aggregate function</term>
25
    ///     <description>Description</description>
26
    ///   </listheader>
27
    ///   <item>
28
    ///     <term>Sum(cell)</term>
29
    ///     <description>Calculates the sum of values in specified table cell.</description>
30
    ///   </item>
31
    ///   <item>
32
    ///     <term>Min(cell)</term>
33
    ///     <description>Calculates the minimum of values in specified table cell.</description>
34
    ///   </item>
35
    ///   <item>
36
    ///     <term>Max(cell)</term>
37
    ///     <description>Calculates the maximum of values in specified table cell.</description>
38
    ///   </item>
39
    ///   <item>
40
    ///     <term>Avg(cell)</term>
41
    ///     <description>Calculates the average of values in specified table cell.</description>
42
    ///   </item>
43
    ///   <item>
44
    ///     <term>Count(cell)</term>
45
    ///     <description>Calculates the number of repeats of a specified table cell.</description>
46
    ///   </item>
47
    /// </list>
48
    /// <para/>To print aggregate value, place the aggregate function call in the table cell:
49
    /// <c>[Count(Cell2)]</c>. 
50
    /// </remarks>
51
    public partial class TableObject : TableBase
52
    {
53
        #region Fields
54
        private string manualBuildEvent;
55
        private TableHelper helper;
56
        private bool saveVisible;
57
        private bool saveStateSkipped;
58
        private bool manualBuildAutoSpans;
59
        #endregion
60

61
        #region Properties
62
        /// <summary>
63
        /// Allows to print table rows/columns dynamically.
64
        /// </summary>
65
        /// <remarks>
66
        /// This event is used to handle the table print process in a code. Using special methods
67
        /// like <see cref="PrintRow"/>, <see cref="PrintColumn"/> you can print specified rows/columns.
68
        /// 
69
        /// <para/>First way is to repeat specified row(s) to get a table that will grow downwards. 
70
        /// To do this, you have to call the <b>PrintRow</b> method followed by the <b>PrintColumns</b> method.
71
        /// 
72
        /// <para/>Another way is to repeat the specified column(s) to get a table that grows sidewards.
73
        /// To do this, call the <b>PrintColumn</b> method followed by the <b>PrintRows</b> method.
74
        /// 
75
        /// <para/>Finally, the third way is to repeat rows and columns. The table will grow downwards and
76
        /// sidewards. To do this, call the <b>PrintRow</b> method followed by the <b>PrintColumn</b>
77
        /// method (or vice versa).
78
        /// 
79
        /// <para/>
80
        /// <note type="caution">
81
        /// When you print a table row-by-row, you must call one of the <b>PrintColumn</b>,
82
        /// <b>PrintColumns</b> methods right after the <b>PrintRow</b> method. 
83
        /// In the same manner, when you print a table column-by-column, call one of the 
84
        /// <b>PrintRow</b>, <b>PrintRows</b> methods right after the <b>PrintColumn</b> method. 
85
        /// If you ignore this rule you will get an exception.
86
        /// </note>
87
        /// </remarks>
88
        /// <example>
89
        /// In this example, we will consider all three ways to print a table which has 3 rows and 3 columns.
90
        /// <para/>Case 1: print a table downwards.
91
        /// <code>
92
        /// // print table header (the first row)
93
        /// Table1.PrintRow(0);
94
        /// Table1.PrintColumns();
95
        /// // print table body (the second row)
96
        /// for (int i = 0; i &lt; 10; i++)
97
        /// {
98
        ///   Table1.PrintRow(1);
99
        ///   Table1.PrintColumns();
100
        /// }
101
        /// // print table footer (the third row)
102
        /// Table1.PrintRow(2);
103
        /// Table1.PrintColumns();
104
        /// </code>
105
        /// 
106
        /// <para/>Case 2: print a table sidewards.
107
        /// <code>
108
        /// // print table header (the first column)
109
        /// Table1.PrintColumn(0);
110
        /// Table1.PrintRows();
111
        /// // print table body (the second column)
112
        /// for (int i = 0; i &lt; 10; i++)
113
        /// {
114
        ///   Table1.PrintColumn(1);
115
        ///   Table1.PrintRows();
116
        /// }
117
        /// // print table footer (the third column)
118
        /// Table1.PrintColumn(2);
119
        /// Table1.PrintRows();
120
        /// </code>
121
        /// 
122
        /// <para/>Case 3: print a table downwards and sidewards.
123
        /// <code>
124
        /// // print the first row with all its columns
125
        /// Table1.PrintRow(0);
126
        /// // print header column
127
        /// Table1.PrintColumn(0);
128
        /// // print 10 data columns
129
        /// for (int i = 0; i &lt; 10; i++)
130
        /// {
131
        ///   Table1.PrintColumn(1);
132
        /// }
133
        /// // print footer column
134
        /// Table1.PrintColumn(2);
135
        /// 
136
        /// // print table body (the second row)
137
        /// for (int i = 0; i &lt; 10; i++)
138
        /// {
139
        ///   // print data row with all its columns
140
        ///   Table1.PrintRow(1);
141
        ///   Table1.PrintColumn(0);
142
        ///   for (int j = 0; j &lt; 10; j++)
143
        ///   {
144
        ///     Table1.PrintColumn(1);
145
        ///   }
146
        ///   Table1.PrintColumn(2);
147
        /// }
148
        /// 
149
        /// // print table footer (the third row)
150
        /// Table1.PrintRow(2);
151
        /// // again print all columns in the table footer
152
        /// Table1.PrintColumn(0);
153
        /// for (int i = 0; i &lt; 10; i++)
154
        /// {
155
        ///   Table1.PrintColumn(1);
156
        /// }
157
        /// Table1.PrintColumn(2);
158
        /// </code>
159
        /// </example>
160
        public event EventHandler ManualBuild;
161

162
        /// <summary>
163
        /// Gets or sets a script method name that will be used to handle the 
164
        /// <see cref="ManualBuild"/> event.
165
        /// </summary>
166
        /// <remarks>
167
        /// If you use this event, you must handle the table print process manually.
168
        /// See the <see cref="ManualBuild"/> event for details.
169
        /// </remarks>
170
        [Category("Build")]
171
        public string ManualBuildEvent
172
        {
173
            get { return manualBuildEvent; }
174
            set { manualBuildEvent = value; }
175
        }
176

177
        /// <summary>
178
        /// Determines whether to manage cell spans automatically during manual build.
179
        /// </summary>
180
        /// <remarks>
181
        /// The default value for this property is <b>true</b>. If you set it to <b>false</b>, you need to manage
182
        /// spans in your ManualBuild event handler.
183
        /// </remarks>
184
        [Category("Build")]
185
        [DefaultValue(true)]
186
        public bool ManualBuildAutoSpans
187
        {
188
            get { return manualBuildAutoSpans; }
189
            set { manualBuildAutoSpans = value; }
190
        }
191

192
        /// <inheritdoc/>
193
        public override int ColumnCount
194
        {
195
            get { return base.ColumnCount; }
196
            set
197
            {
198
                base.ColumnCount = value;
199
                CreateUniqueNames();
200
            }
201
        }
202

203
        /// <inheritdoc/>
204
        public override int RowCount
205
        {
206
            get { return base.RowCount; }
207
            set
208
            {
209
                base.RowCount = value;
210
                CreateUniqueNames();
211
            }
212
        }
213

214
        internal bool IsManualBuild
215
        {
216
            get { return !String.IsNullOrEmpty(ManualBuildEvent) || ManualBuild != null; }
217
        }
218
        #endregion
219

220
        #region Private Methods
221
        partial void InitTag();
222
        #endregion
223

224
        #region Public Methods
225
        /// <inheritdoc/>
226
        public override void Assign(Base source)
227
        {
228
            base.Assign(source);
229

230
            TableObject src = source as TableObject;
231
            ManualBuildEvent = src.ManualBuildEvent;
232
            ManualBuildAutoSpans = src.ManualBuildAutoSpans;
233
        }
234

235
        /// <inheritdoc/>
236
        public override void Serialize(FRWriter writer)
237
        {
238
            TableObject c = writer.DiffObject as TableObject;
239
            base.Serialize(writer);
240

241
            if (ManualBuildEvent != c.ManualBuildEvent)
242
                writer.WriteStr("ManualBuildEvent", ManualBuildEvent);
243
            if (ManualBuildAutoSpans != c.ManualBuildAutoSpans)
244
                writer.WriteBool("ManualBuildAutoSpans", ManualBuildAutoSpans);
245
        }
246
        #endregion
247

248
        #region Report Engine
249
        private string GetFunctionCode(string function)
250
        {
251
            string result = "";
252

253
            switch (Report.ScriptLanguage)
254
            {
255
                case Language.CSharp:
256
                    result =
257
                      "    private object " + function + "(TableCell cell)\r\n" +
258
                      "    {\r\n" +
259
                      "      return cell.Table." + function + "(cell);\r\n" +
260
                      "    }\r\n\r\n";
261
                    break;
262

263
                case Language.Vb:
264
                    result =
265
                      "    Private Function " + function + "(ByVal cell As TableCell) As Object\r\n" +
266
                      "      Return cell.Table." + function + "(cell)\r\n" +
267
                      "    End Function\r\n\r\n";
268
                    break;
269
            }
270

271
            return result;
272
        }
273

274
        /// <inheritdoc/>
275
        public override string GetCustomScript()
276
        {
277
            string result = "";
278
            string[] functions = new string[] { "Sum", "Min", "Max", "Avg", "Count" };
279

280
            foreach (string function in functions)
281
            {
282
                result += GetFunctionCode(function);
283
            }
284

285
            return result;
286
        }
287

288
        /// <inheritdoc/>
289
        public override void SaveState()
290
        {
291
            saveVisible = Visible;
292
            BandBase parent = Parent as BandBase;
293
            saveStateSkipped = !Visible || (parent != null && !parent.Visible);
294
            if (saveStateSkipped)
295
                return;
296

297
            if (!IsManualBuild)
298
            {
299
                base.SaveState();
300
            }
301
            else
302
            {
303
                // create the result table that will be rendered in the preview
304
                SetResultTable(new TableResult());
305
                ResultTable.Assign(this);
306
                ResultTable.SetReport(Report);
307
                helper = new TableHelper(this, ResultTable);
308

309
                Visible = false;
310

311
                if (parent != null && !PrintOnParent)
312
                {
313
                    parent.Height = Top;
314
                    parent.CanGrow = false;
315
                    parent.CanShrink = false;
316
                    parent.AfterPrint += ResultTable.GeneratePages;
317
                }
318

319
                OnManualBuild(EventArgs.Empty);
320
            }
321
        }
322

323
        /// <inheritdoc/>
324
        public override void RestoreState()
325
        {
326
            BandBase parent = Parent as BandBase;
327
            // SaveState was skipped, there is nothing to restore
328
            if (saveStateSkipped)
329
                return;
330

331
            if (!IsManualBuild)
332
            {
333
                base.RestoreState();
334
            }
335
            else
336
            {
337
                if (parent != null && !PrintOnParent)
338
                    parent.AfterPrint -= ResultTable.GeneratePages;
339

340
                helper = null;
341
                ResultTable.Dispose();
342
                SetResultTable(null);
343
                Visible = saveVisible;
344
            }
345
        }
346

347
        /// <inheritdoc/>
348
        public override void GetData()
349
        {
350
            base.GetData();
351

352
            if (!IsManualBuild)
353
            {
354
                for (int y = 0; y < Rows.Count; y++)
355
                {
356
                    for (int x = 0; x < Columns.Count; x++)
357
                    {
358
                        this[x, y].GetData();
359
                    }
360
                }
361
            }
362
        }
363

364
        /// <inheritdoc/>
365
        public override void OnAfterData(EventArgs e)
366
        {
367
            base.OnAfterData(e);
368

369
            if (IsManualBuild && PrintOnParent)
370
                ResultTable.AddToParent(Parent);
371
        }
372

373
        /// <summary>
374
        /// This method fires the <b>ManualBuild</b> event and the script code connected to the <b>ManualBuildEvent</b>.
375
        /// </summary>
376
        /// <param name="e">Event data.</param>
377
        public void OnManualBuild(EventArgs e)
378
        {
379
            if (ManualBuild != null)
380
                ManualBuild(this, e);
381
            InvokeEvent(ManualBuildEvent, e);
382
        }
383

384
        /// <summary>
385
        /// Prints a row with specified index.
386
        /// </summary>
387
        /// <param name="index">Index of a row to print.</param>
388
        /// <remarks>
389
        /// See the <see cref="ManualBuild"/> event for more details.
390
        /// </remarks>
391
        public void PrintRow(int index)
392
        {
393
            if (!IsManualBuild)
394
                throw new TableManualBuildException();
395
            helper.PrintRow(index);
396
        }
397

398
        /// <summary>
399
        /// Prints rows with specified indices.
400
        /// </summary>
401
        /// <param name="indices">Indices of rows to print.</param>
402
        /// <remarks>
403
        /// See the <see cref="ManualBuild"/> event for more details.
404
        /// </remarks>
405
        public void PrintRows(int[] indices)
406
        {
407
            foreach (int index in indices)
408
            {
409
                PrintRow(index);
410
            }
411
        }
412

413
        /// <summary>
414
        /// Prints all rows.
415
        /// </summary>
416
        /// <remarks>
417
        /// See the <see cref="ManualBuild"/> event for more details.
418
        /// </remarks>
419
        public void PrintRows()
420
        {
421
            for (int i = 0; i < Rows.Count; i++)
422
            {
423
                PrintRow(i);
424
            }
425
        }
426

427
        /// <summary>
428
        /// Prints a column with specified index.
429
        /// </summary>
430
        /// <param name="index">Index of a column to print.</param>
431
        /// <remarks>
432
        /// See the <see cref="ManualBuild"/> event for more details.
433
        /// </remarks>
434
        public void PrintColumn(int index)
435
        {
436
            if (!IsManualBuild)
437
                throw new TableManualBuildException();
438
            helper.PrintColumn(index);
439
        }
440

441
        /// <summary>
442
        /// Prints columns with specified indices.
443
        /// </summary>
444
        /// <param name="indices">Indices of columns to print.</param>
445
        /// <remarks>
446
        /// See the <see cref="ManualBuild"/> event for more details.
447
        /// </remarks>
448
        public void PrintColumns(int[] indices)
449
        {
450
            foreach (int index in indices)
451
            {
452
                PrintColumn(index);
453
            }
454
        }
455

456
        /// <summary>
457
        /// Prints all columns.
458
        /// </summary>
459
        /// <remarks>
460
        /// See the <see cref="ManualBuild"/> event for more details.
461
        /// </remarks>
462
        public void PrintColumns()
463
        {
464
            for (int i = 0; i < Columns.Count; i++)
465
            {
466
                PrintColumn(i);
467
            }
468
        }
469

470
        /// <summary>
471
        /// Adds a page before rows or columns.
472
        /// </summary>
473
        /// <remarks>
474
        /// Call this method to insert a page break before the next row or column that you intend to print
475
        /// using <b>PrintRow(s)</b> or <b>PrintColumn(s)</b> methods.
476
        /// See the <see cref="ManualBuild"/> event for more details.
477
        /// </remarks>
478
        public void PageBreak()
479
        {
480
            if (!IsManualBuild)
481
                throw new TableManualBuildException();
482
            if (!Report.Engine.UnlimitedHeight && !Report.Engine.UnlimitedWidth)
483
                helper.PageBreak();
484
        }
485
        #endregion
486

487
        /// <summary>
488
        /// Initializes a new instance of the <see cref="TableObject"/> class.
489
        /// </summary>
490
        public TableObject()
491
        {
492
            manualBuildEvent = "";
493
            manualBuildAutoSpans = true;
494
            InitTag();
495
        }
496
    }
497
}
498

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.