MatrixObject.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using FastReport.Table;
  5. using FastReport.Data;
  6. using FastReport.Utils;
  7. using System.Drawing.Design;
  8. namespace FastReport.Matrix
  9. {
  10. /// <summary>
  11. /// Describes how the even style is applied to a matrix.
  12. /// </summary>
  13. public enum MatrixEvenStylePriority
  14. {
  15. /// <summary>
  16. /// The even style is applied to matrix rows.
  17. /// </summary>
  18. Rows,
  19. /// <summary>
  20. /// The even style is applied to matrix columns.
  21. /// </summary>
  22. Columns
  23. }
  24. /// <summary>
  25. /// Represents the matrix object that is used to print pivot table (also known as cross-tab).
  26. /// </summary>
  27. /// <remarks>
  28. /// The matrix consists of the following elements: columns, rows and data cells. Each element is
  29. /// represented by the <b>descriptor</b>. The <see cref="MatrixHeaderDescriptor"/> class is used
  30. /// for columns and rows; the <see cref="MatrixCellDescriptor"/> is used for data cells.
  31. /// The <see cref="Data"/> property holds three collections of descriptors - <b>Columns</b>,
  32. /// <b>Rows</b> and <b>Cells</b>.
  33. /// <para/>To create the matrix in a code, you should perform the following actions:
  34. /// <list type="bullet">
  35. /// <item>
  36. /// <description>create an instance of the <b>MatrixObject</b> and add it to the report;</description>
  37. /// </item>
  38. /// <item>
  39. /// <description>create descriptors for columns, rows and cells and add it to the
  40. /// collections inside the <see cref="Data"/> property;</description>
  41. /// </item>
  42. /// <item>
  43. /// <description>call the <see cref="BuildTemplate"/> method to create the matrix template
  44. /// that will be used to create a result;</description>
  45. /// </item>
  46. /// <item>
  47. /// <description>modify the matrix template (change captions, set the visual appearance).</description>
  48. /// </item>
  49. /// </list>
  50. /// <para/>To connect the matrix to a datasource, use the <see cref="DataSource"/> property. If
  51. /// this property is not set, the result matrix will be empty. In this case you may use
  52. /// the <see cref="ManualBuild"/> event handler to fill the matrix.
  53. /// </remarks>
  54. /// <example>This example demonstrates how to create a matrix in a code.
  55. /// <code>
  56. /// // create an instance of MatrixObject
  57. /// MatrixObject matrix = new MatrixObject();
  58. /// matrix.Name = "Matrix1";
  59. /// // add it to the report title band of the first report page
  60. /// matrix.Parent = (report.Pages[0] as ReportPage).ReportTitle;
  61. ///
  62. /// // create two column descriptors
  63. /// MatrixHeaderDescriptor column = new MatrixHeaderDescriptor("[MatrixDemo.Year]");
  64. /// matrix.Data.Columns.Add(column);
  65. /// column = new MatrixHeaderDescriptor("[MatrixDemo.Month]");
  66. /// matrix.Data.Columns.Add(column);
  67. ///
  68. /// // create one row descriptor
  69. /// MatrixHeaderDescriptor row = new MatrixHeaderDescriptor("[MatrixDemo.Name]");
  70. /// matrix.Data.Rows.Add(row);
  71. ///
  72. /// // create one data cell
  73. /// MatrixCellDescriptor cell = new MatrixCellDescriptor("[MatrixDemo.Revenue]", MatrixAggregateFunction.Sum);
  74. /// matrix.Data.Cells.Add(cell);
  75. ///
  76. /// // connect matrix to a datasource
  77. /// matrix.DataSource = Report.GetDataSource("MatrixDemo");
  78. ///
  79. /// // create the matrix template
  80. /// matrix.BuildTemplate();
  81. ///
  82. /// // change the style
  83. /// matrix.Style = "Green";
  84. ///
  85. /// // change the column and row total's text to "Grand Total"
  86. /// matrix.Data.Columns[0].TemplateTotalCell.Text = "Grand Total";
  87. /// matrix.Data.Rows[0].TemplateTotalCell.Text = "Grand Total";
  88. /// </code>
  89. /// </example>
  90. public partial class MatrixObject : TableBase
  91. {
  92. #region Fields
  93. private bool autoSize;
  94. private bool cellsSideBySide;
  95. private bool keepCellsSideBySide;
  96. private DataSourceBase dataSource;
  97. private string filter;
  98. private bool showTitle;
  99. private string style;
  100. private MatrixData data;
  101. private string manualBuildEvent;
  102. private string modifyResultEvent;
  103. private string afterTotalsEvent;
  104. private MatrixHelper helper;
  105. private bool saveVisible;
  106. private MatrixStyleSheet styleSheet;
  107. private object[] columnValues;
  108. private object[] rowValues;
  109. private int columnIndex;
  110. private int rowIndex;
  111. private MatrixEvenStylePriority matrixEvenStylePriority;
  112. private bool splitRows;
  113. private bool printIfEmpty;
  114. #endregion
  115. #region Properties
  116. /// <summary>
  117. /// Allows to fill the matrix in code.
  118. /// </summary>
  119. /// <remarks>
  120. /// In most cases the matrix is connected to a datasource via the <see cref="DataSource"/>
  121. /// property. When you run a report, the matrix is filled with datasource values automatically.
  122. /// <para/>Using this event, you can put additional values to the matrix or even completely fill it
  123. /// with own values (if <see cref="DataSource"/> is set to <b>null</b>. To do this, call the
  124. /// <b>Data.AddValue</b> method. See the <see cref="MatrixData.AddValue(object[],object[],object[])"/>
  125. /// method for more details.
  126. /// </remarks>
  127. /// <example>This example shows how to fill a matrix with own values.
  128. /// <code>
  129. /// // suppose we have a matrix with one column, row and data cell.
  130. /// // provide 3 one-dimensional arrays with one element in each to the AddValue method
  131. /// Matrix1.Data.AddValue(
  132. /// new object[] { 1996 },
  133. /// new object[] { "Andrew Fuller" },
  134. /// new object[] { 123.45f });
  135. /// Matrix1.Data.AddValue(
  136. /// new object[] { 1997 },
  137. /// new object[] { "Andrew Fuller" },
  138. /// new object[] { 21.35f });
  139. /// Matrix1.Data.AddValue(
  140. /// new object[] { 1997 },
  141. /// new object[] { "Nancy Davolio" },
  142. /// new object[] { 421.5f });
  143. ///
  144. /// // this code will produce the following matrix:
  145. /// // | 1996 | 1997 |
  146. /// // --------------+--------+--------+
  147. /// // Andrew Fuller | 123.45| 21.35|
  148. /// // --------------+--------+--------+
  149. /// // Nancy Davolio | | 421.50|
  150. /// // --------------+--------+--------+
  151. /// </code>
  152. /// </example>
  153. public event EventHandler ManualBuild;
  154. /// <summary>
  155. /// Allows to modify the prepared matrix elements such as cells, rows, columns.
  156. /// </summary>
  157. public event EventHandler ModifyResult;
  158. /// <summary>
  159. /// Allows to modify the prepared matrix elements such as cells, rows, columns.
  160. /// </summary>
  161. public event EventHandler AfterTotals;
  162. /// <summary>
  163. /// Gets or sets a value that determines whether the matrix must calculate column/row sizes automatically.
  164. /// </summary>
  165. [DefaultValue(true)]
  166. [Category("Behavior")]
  167. public bool AutoSize
  168. {
  169. get { return autoSize; }
  170. set
  171. {
  172. autoSize = value;
  173. foreach (TableColumn column in Columns)
  174. {
  175. column.AutoSize = AutoSize;
  176. }
  177. foreach (TableRow row in Rows)
  178. {
  179. row.AutoSize = AutoSize;
  180. }
  181. }
  182. }
  183. /// <summary>
  184. /// Gets or sets a value that determines how to print multiple data cells.
  185. /// </summary>
  186. /// <remarks>
  187. /// This property can be used if matrix has two or more data cells. Default property value
  188. /// is <b>false</b> - that means the data cells will be stacked.
  189. /// </remarks>
  190. [DefaultValue(false)]
  191. [Category("Behavior")]
  192. public bool CellsSideBySide
  193. {
  194. get { return cellsSideBySide; }
  195. set
  196. {
  197. if (cellsSideBySide != value)
  198. {
  199. cellsSideBySide = value;
  200. if (IsDesigning)
  201. {
  202. foreach (MatrixCellDescriptor descr in Data.Cells)
  203. {
  204. descr.TemplateColumn = null;
  205. descr.TemplateRow = null;
  206. }
  207. BuildTemplate();
  208. }
  209. }
  210. }
  211. }
  212. /// <summary>
  213. /// Gets or sets a value indicating that the side-by-side cells must be kept together on the same page.
  214. /// </summary>
  215. [DefaultValue(false)]
  216. [Category("Behavior")]
  217. public bool KeepCellsSideBySide
  218. {
  219. get { return keepCellsSideBySide; }
  220. set { keepCellsSideBySide = value; }
  221. }
  222. /// <summary>
  223. /// Gets or sets a data source.
  224. /// </summary>
  225. /// <remarks>
  226. /// When you create the matrix in the designer by drag-drop data columns into it,
  227. /// this property will be set automatically. However you need to set it if you create
  228. /// the matrix in code.
  229. /// </remarks>
  230. [Category("Data")]
  231. public DataSourceBase DataSource
  232. {
  233. get { return dataSource; }
  234. set
  235. {
  236. if (dataSource != value)
  237. {
  238. if (dataSource != null)
  239. dataSource.Disposed -= new EventHandler(DataSource_Disposed);
  240. if (value != null)
  241. value.Disposed += new EventHandler(DataSource_Disposed);
  242. }
  243. dataSource = value;
  244. }
  245. }
  246. /// <summary>
  247. /// Gets the row filter expression.
  248. /// </summary>
  249. /// <remarks>
  250. /// This property can contain any valid boolean expression. If the expression returns <b>false</b>,
  251. /// the corresponding data row will be skipped.
  252. /// </remarks>
  253. [Category("Data")]
  254. [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
  255. public string Filter
  256. {
  257. get { return filter; }
  258. set { filter = value; }
  259. }
  260. /// <summary>
  261. /// Gets or sets a value indicating whether to show a title row.
  262. /// </summary>
  263. [DefaultValue(false)]
  264. [Category("Behavior")]
  265. public bool ShowTitle
  266. {
  267. get { return showTitle; }
  268. set
  269. {
  270. showTitle = value;
  271. if (IsDesigning)
  272. BuildTemplate();
  273. }
  274. }
  275. /// <summary>
  276. /// Gets or sets a matrix style.
  277. /// </summary>
  278. [Category("Appearance")]
  279. [Editor("FastReport.TypeEditors.MatrixStyleEditor, FastReport", typeof(UITypeEditor))]
  280. public new string Style
  281. {
  282. get { return style; }
  283. set
  284. {
  285. style = value;
  286. Helper.UpdateStyle();
  287. }
  288. }
  289. /// <summary>
  290. /// Gets or sets even style priority for matrix cells.
  291. /// </summary>
  292. [Category("Behavior")]
  293. [DefaultValue(MatrixEvenStylePriority.Rows)]
  294. public MatrixEvenStylePriority MatrixEvenStylePriority
  295. {
  296. get { return matrixEvenStylePriority; }
  297. set { matrixEvenStylePriority = value; }
  298. }
  299. /// <summary>
  300. /// Gets or sets need split rows.
  301. /// </summary>
  302. [Category("Behavior")]
  303. [DefaultValue(false)]
  304. public bool SplitRows
  305. {
  306. get { return splitRows; }
  307. set { splitRows = value; }
  308. }
  309. /// <summary>
  310. /// Gets or sets a value indicating that empty matrix should be printed.
  311. /// </summary>
  312. [Category("Behavior")]
  313. [DefaultValue(true)]
  314. public bool PrintIfEmpty
  315. {
  316. get { return printIfEmpty; }
  317. set { printIfEmpty = value; }
  318. }
  319. /// <summary>
  320. /// Gets or sets a script method name that will be used to handle the
  321. /// <see cref="ManualBuild"/> event.
  322. /// </summary>
  323. /// <remarks>
  324. /// See the <see cref="ManualBuild"/> event for more details.
  325. /// </remarks>
  326. [Category("Build")]
  327. public string ManualBuildEvent
  328. {
  329. get { return manualBuildEvent; }
  330. set { manualBuildEvent = value; }
  331. }
  332. /// <summary>
  333. /// Gets or sets a script method name that will be used to handle the
  334. /// <see cref="ModifyResult"/> event.
  335. /// </summary>
  336. /// <remarks>
  337. /// See the <see cref="ModifyResult"/> event for more details.
  338. /// </remarks>
  339. [Category("Build")]
  340. public string ModifyResultEvent
  341. {
  342. get { return modifyResultEvent; }
  343. set { modifyResultEvent = value; }
  344. }
  345. /// <summary>
  346. /// Gets or sets a script method name that will be used to handle the
  347. /// <see cref="AfterTotals"/> event.
  348. /// </summary>
  349. /// <remarks>
  350. /// See the <see cref="AfterTotals"/> event for more details.
  351. /// </remarks>
  352. [Category("Build")]
  353. public string AfterTotalsEvent
  354. {
  355. get { return afterTotalsEvent; }
  356. set { afterTotalsEvent = value; }
  357. }
  358. /// <summary>
  359. /// Gets the object that holds the collection of descriptors used
  360. /// to build a matrix.
  361. /// </summary>
  362. /// <remarks>
  363. /// See the <see cref="MatrixData"/> class for more details.
  364. /// </remarks>
  365. [Browsable(false)]
  366. public MatrixData Data
  367. {
  368. get { return data; }
  369. }
  370. /// <summary>
  371. /// Gets or sets array of values that describes the currently printing column.
  372. /// </summary>
  373. /// <remarks>
  374. /// Use this property when report is running. It can be used to highlight matrix elements
  375. /// depending on values of the currently printing column. To do this:
  376. /// <list type="bullet">
  377. /// <item>
  378. /// <description>select the cell that you need to highlight;</description>
  379. /// </item>
  380. /// <item>
  381. /// <description>click the "Highlight" button on the "Text" toolbar;</description>
  382. /// </item>
  383. /// <item>
  384. /// <description>add a new highlight condition. Use the <b>Matrix.ColumnValues</b> to
  385. /// refer to the value you need to analyze. Note: these values are arrays of <b>System.Object</b>,
  386. /// so you need to cast it to actual type before making any comparisons. Example of highlight
  387. /// condition: <c>(int)Matrix1.ColumnValues[0] == 2000</c>.
  388. /// </description>
  389. /// </item>
  390. /// </list>
  391. /// </remarks>
  392. [Browsable(false)]
  393. public object[] ColumnValues
  394. {
  395. get { return columnValues; }
  396. set { columnValues = value; }
  397. }
  398. /// <summary>
  399. /// Gets or sets array of values that describes the currently printing row.
  400. /// </summary>
  401. /// <remarks>
  402. /// Use this property when report is running. It can be used to highlight matrix elements
  403. /// depending on values of the currently printing row. To do this:
  404. /// <list type="bullet">
  405. /// <item>
  406. /// <description>select the cell that you need to highlight;</description>
  407. /// </item>
  408. /// <item>
  409. /// <description>click the "Highlight" button on the "Text" toolbar;</description>
  410. /// </item>
  411. /// <item>
  412. /// <description>add a new highlight condition. Use the <b>Matrix.RowValues</b> to
  413. /// refer to the value you need to analyze. Note: these values are arrays of <b>System.Object</b>,
  414. /// so you need to cast it to actual type before making any comparisons. Example of highlight
  415. /// condition: <c>(string)Matrix1.RowValues[0] == "Andrew Fuller"</c>.
  416. /// </description>
  417. /// </item>
  418. /// </list>
  419. /// </remarks>
  420. [Browsable(false)]
  421. public object[] RowValues
  422. {
  423. get { return rowValues; }
  424. set { rowValues = value; }
  425. }
  426. /// <summary>
  427. /// Gets or sets the index of currently printing column.
  428. /// </summary>
  429. /// <remarks>
  430. /// This property may be used to print even columns with alternate color. To do this:
  431. /// <list type="bullet">
  432. /// <item>
  433. /// <description>select the cell that you need to highlight;</description>
  434. /// </item>
  435. /// <item>
  436. /// <description>click the "Highlight" button on the "Text" toolbar;</description>
  437. /// </item>
  438. /// <item>
  439. /// <description>add a new highlight condition that uses the <b>Matrix.ColumnIndex</b>,
  440. /// for example: <c>Matrix1.ColumnIndex % 2 == 1</c>.
  441. /// </description>
  442. /// </item>
  443. /// </list>
  444. /// </remarks>
  445. [Browsable(false)]
  446. public int ColumnIndex
  447. {
  448. get { return columnIndex; }
  449. set { columnIndex = value; }
  450. }
  451. /// <summary>
  452. /// Gets or sets the index of currently printing row.
  453. /// </summary>
  454. /// <remarks>
  455. /// This property may be used to print even rows with alternate color. To do this:
  456. /// <list type="bullet">
  457. /// <item>
  458. /// <description>select the cell that you need to highlight;</description>
  459. /// </item>
  460. /// <item>
  461. /// <description>click the "Highlight" button on the "Text" toolbar;</description>
  462. /// </item>
  463. /// <item>
  464. /// <description>add a new highlight condition that uses the <b>Matrix.RowIndex</b>,
  465. /// for example: <c>Matrix1.RowIndex % 2 == 1</c>.
  466. /// </description>
  467. /// </item>
  468. /// </list>
  469. /// </remarks>
  470. [Browsable(false)]
  471. public int RowIndex
  472. {
  473. get { return rowIndex; }
  474. set { rowIndex = value; }
  475. }
  476. internal MatrixStyleSheet StyleSheet
  477. {
  478. get { return styleSheet; }
  479. }
  480. private MatrixHelper Helper
  481. {
  482. get { return helper; }
  483. }
  484. internal bool IsResultMatrix
  485. {
  486. get { return !IsDesigning && Data.Columns.Count == 0 && Data.Rows.Count == 0; }
  487. }
  488. private BandBase ParentBand
  489. {
  490. get
  491. {
  492. BandBase parentBand = this.Band;
  493. if (parentBand is ChildBand)
  494. parentBand = (parentBand as ChildBand).GetTopParentBand;
  495. return parentBand;
  496. }
  497. }
  498. private DataBand FootersDataBand
  499. {
  500. get
  501. {
  502. DataBand dataBand = null;
  503. if (ParentBand is GroupFooterBand)
  504. dataBand = ((ParentBand as GroupFooterBand).Parent as GroupHeaderBand).GroupDataBand;
  505. else if (ParentBand is DataFooterBand)
  506. dataBand = ParentBand.Parent as DataBand;
  507. return dataBand;
  508. }
  509. }
  510. private bool IsOnFooter
  511. {
  512. get
  513. {
  514. DataBand dataBand = FootersDataBand;
  515. if (dataBand != null)
  516. {
  517. return DataSource == dataBand.DataSource;
  518. }
  519. return false;
  520. }
  521. }
  522. #endregion
  523. #region Private Methods
  524. private void CreateResultTable()
  525. {
  526. SetResultTable(new TableResult());
  527. // assign properties from this object. Do not use Assign method: TableResult is incompatible with MatrixObject.
  528. ResultTable.OriginalComponent = OriginalComponent;
  529. ResultTable.Alias = Alias;
  530. ResultTable.Border = Border.Clone();
  531. ResultTable.Fill = Fill.Clone();
  532. ResultTable.Bounds = Bounds;
  533. ResultTable.PrintOnParent = PrintOnParent;
  534. ResultTable.RepeatHeaders = RepeatHeaders;
  535. ResultTable.RepeatRowHeaders = RepeatRowHeaders;
  536. ResultTable.RepeatColumnHeaders = RepeatColumnHeaders;
  537. ResultTable.Layout = Layout;
  538. ResultTable.WrappedGap = WrappedGap;
  539. ResultTable.AdjustSpannedCellsWidth = AdjustSpannedCellsWidth;
  540. ResultTable.SetReport(Report);
  541. ResultTable.AfterData += new EventHandler(ResultTable_AfterData);
  542. }
  543. private void DisposeResultTable()
  544. {
  545. ResultTable.Dispose();
  546. SetResultTable(null);
  547. }
  548. private void ResultTable_AfterData(object sender, EventArgs e)
  549. {
  550. OnModifyResult(e);
  551. }
  552. private void DataSource_Disposed(object sender, EventArgs e)
  553. {
  554. dataSource = null;
  555. }
  556. private void WireEvents(bool wire)
  557. {
  558. if (IsOnFooter)
  559. {
  560. DataBand dataBand = FootersDataBand;
  561. if (wire)
  562. dataBand.BeforePrint += new EventHandler(dataBand_BeforePrint);
  563. else
  564. dataBand.BeforePrint -= new EventHandler(dataBand_BeforePrint);
  565. }
  566. }
  567. private void dataBand_BeforePrint(object sender, EventArgs e)
  568. {
  569. bool firstRow = (sender as DataBand).IsFirstRow;
  570. if (firstRow)
  571. Helper.StartPrint();
  572. object match = true;
  573. if (!String.IsNullOrEmpty(Filter))
  574. match = Report.Calc(Filter);
  575. if (match is bool && (bool)match == true)
  576. Helper.AddDataRow();
  577. }
  578. #endregion
  579. #region Protected Methods
  580. /// <inheritdoc/>
  581. protected override void DeserializeSubItems(FRReader reader)
  582. {
  583. if (String.Compare(reader.ItemName, "MatrixColumns", true) == 0)
  584. reader.Read(Data.Columns);
  585. else if (String.Compare(reader.ItemName, "MatrixRows", true) == 0)
  586. reader.Read(Data.Rows);
  587. else if (String.Compare(reader.ItemName, "MatrixCells", true) == 0)
  588. reader.Read(Data.Cells);
  589. else
  590. base.DeserializeSubItems(reader);
  591. }
  592. #endregion
  593. #region Public Methods
  594. /// <inheritdoc/>
  595. public override void Assign(Base source)
  596. {
  597. base.Assign(source);
  598. MatrixObject src = source as MatrixObject;
  599. AutoSize = src.AutoSize;
  600. CellsSideBySide = src.CellsSideBySide;
  601. KeepCellsSideBySide = src.KeepCellsSideBySide;
  602. DataSource = src.DataSource;
  603. Filter = src.Filter;
  604. ShowTitle = src.ShowTitle;
  605. Style = src.Style;
  606. MatrixEvenStylePriority = src.MatrixEvenStylePriority;
  607. SplitRows = src.SplitRows;
  608. PrintIfEmpty = src.PrintIfEmpty;
  609. data = src.Data;
  610. }
  611. /// <inheritdoc/>
  612. public override void Serialize(FRWriter writer)
  613. {
  614. if (writer.SerializeTo != SerializeTo.SourcePages)
  615. {
  616. writer.Write(Data.Columns);
  617. writer.Write(Data.Rows);
  618. writer.Write(Data.Cells);
  619. }
  620. else
  621. RefreshTemplate(true);
  622. base.Serialize(writer);
  623. MatrixObject c = writer.DiffObject as MatrixObject;
  624. if (AutoSize != c.AutoSize)
  625. writer.WriteBool("AutoSize", AutoSize);
  626. if (CellsSideBySide != c.CellsSideBySide)
  627. writer.WriteBool("CellsSideBySide", CellsSideBySide);
  628. if (KeepCellsSideBySide != c.KeepCellsSideBySide)
  629. writer.WriteBool("KeepCellsSideBySide", KeepCellsSideBySide);
  630. if (DataSource != c.DataSource)
  631. writer.WriteRef("DataSource", DataSource);
  632. if (Filter != c.Filter)
  633. writer.WriteStr("Filter", Filter);
  634. if (ShowTitle != c.ShowTitle)
  635. writer.WriteBool("ShowTitle", ShowTitle);
  636. if (Style != c.Style)
  637. writer.WriteStr("Style", Style);
  638. if (MatrixEvenStylePriority != c.MatrixEvenStylePriority)
  639. writer.WriteValue("MatrixEvenStylePriority", MatrixEvenStylePriority);
  640. if (SplitRows != c.SplitRows)
  641. writer.WriteBool("SplitRows", SplitRows);
  642. if (PrintIfEmpty != c.PrintIfEmpty)
  643. writer.WriteBool("PrintIfEmpty", PrintIfEmpty);
  644. if (ManualBuildEvent != c.ManualBuildEvent)
  645. writer.WriteStr("ManualBuildEvent", ManualBuildEvent);
  646. if (ModifyResultEvent != c.ModifyResultEvent)
  647. writer.WriteStr("ModifyResultEvent", ModifyResultEvent);
  648. if (AfterTotalsEvent != c.AfterTotalsEvent)
  649. writer.WriteStr("AfterTotalsEvent", AfterTotalsEvent);
  650. }
  651. /// <summary>
  652. /// Creates or updates the matrix template.
  653. /// </summary>
  654. /// <remarks>
  655. /// Call this method after you modify the matrix descriptors using the <see cref="Data"/>
  656. /// object's properties.
  657. /// </remarks>
  658. public void BuildTemplate()
  659. {
  660. Helper.BuildTemplate();
  661. }
  662. #endregion
  663. #region Report Engine
  664. /// <inheritdoc/>
  665. public override void InitializeComponent()
  666. {
  667. base.InitializeComponent();
  668. WireEvents(true);
  669. }
  670. /// <inheritdoc/>
  671. public override void FinalizeComponent()
  672. {
  673. base.FinalizeComponent();
  674. WireEvents(false);
  675. }
  676. /// <inheritdoc/>
  677. public override string[] GetExpressions()
  678. {
  679. List<string> expressions = new List<string>();
  680. expressions.AddRange(base.GetExpressions());
  681. Helper.UpdateDescriptors();
  682. List<MatrixDescriptor> descrList = new List<MatrixDescriptor>();
  683. descrList.AddRange(Data.Columns.ToArray());
  684. descrList.AddRange(Data.Rows.ToArray());
  685. descrList.AddRange(Data.Cells.ToArray());
  686. foreach (MatrixDescriptor descr in descrList)
  687. {
  688. expressions.Add(descr.Expression);
  689. if (descr.TemplateCell != null)
  690. descr.TemplateCell.AllowExpressions = false;
  691. }
  692. if (!String.IsNullOrEmpty(Filter))
  693. expressions.Add(Filter);
  694. return expressions.ToArray();
  695. }
  696. /// <inheritdoc/>
  697. public override void SaveState()
  698. {
  699. saveVisible = Visible;
  700. BandBase parent = Parent as BandBase;
  701. if (!Visible || (parent != null && !parent.Visible))
  702. return;
  703. // create the result table that will be rendered in the preview
  704. CreateResultTable();
  705. Visible = false;
  706. if (parent != null && !PrintOnParent)
  707. {
  708. parent.Height = Top;
  709. parent.CanGrow = false;
  710. parent.CanShrink = false;
  711. parent.AfterPrint += ResultTable.GeneratePages;
  712. }
  713. }
  714. /// <inheritdoc/>
  715. public override void GetData()
  716. {
  717. base.GetData();
  718. if (!IsOnFooter)
  719. {
  720. Helper.StartPrint();
  721. Helper.AddDataRows();
  722. }
  723. }
  724. /// <inheritdoc/>
  725. public override void OnAfterData(EventArgs e)
  726. {
  727. base.OnAfterData(e);
  728. Helper.FinishPrint();
  729. if (PrintOnParent)
  730. ResultTable.AddToParent(Parent);
  731. }
  732. /// <inheritdoc/>
  733. public override void RestoreState()
  734. {
  735. BandBase parent = Parent as BandBase;
  736. if (!saveVisible || (parent != null && !parent.Visible))
  737. return;
  738. if (parent != null && !PrintOnParent)
  739. parent.AfterPrint -= ResultTable.GeneratePages;
  740. DisposeResultTable();
  741. Visible = saveVisible;
  742. }
  743. /// <summary>
  744. /// This method fires the <b>ManualBuild</b> event and the script code connected to the <b>ManualBuildEvent</b>.
  745. /// </summary>
  746. /// <param name="e">Event data.</param>
  747. public void OnManualBuild(EventArgs e)
  748. {
  749. if (ManualBuild != null)
  750. ManualBuild(this, e);
  751. InvokeEvent(ManualBuildEvent, e);
  752. }
  753. /// <summary>
  754. /// This method fires the <b>ModifyResult</b> event and the script code connected to the <b>ModifyResultEvent</b>.
  755. /// </summary>
  756. /// <param name="e">Event data.</param>
  757. public void OnModifyResult(EventArgs e)
  758. {
  759. if (ModifyResult != null)
  760. ModifyResult(this, e);
  761. InvokeEvent(ModifyResultEvent, e);
  762. }
  763. /// <summary>
  764. /// This method fires the <b>AfterTotals</b> event and the script code connected to the <b>AfterTotalsEvent</b>.
  765. /// </summary>
  766. /// <param name="e">Event data.</param>
  767. public void OnAfterTotals(EventArgs e)
  768. {
  769. if (AfterTotals != null)
  770. AfterTotals(this, e);
  771. InvokeEvent(AfterTotalsEvent, e);
  772. }
  773. /// <summary>
  774. /// Adds a value in the matrix.
  775. /// </summary>
  776. /// <param name="columnValues">Array of column values.</param>
  777. /// <param name="rowValues">Array of row values.</param>
  778. /// <param name="cellValues">Array of data values.</param>
  779. /// <remarks>
  780. /// This is a shortcut method to call the matrix <b>Data.AddValue</b>.
  781. /// See the <see cref="MatrixData.AddValue(object[],object[],object[])"/> method for more details.
  782. /// </remarks>
  783. public void AddValue(object[] columnValues, object[] rowValues, object[] cellValues)
  784. {
  785. Data.AddValue(columnValues, rowValues, cellValues, 0);
  786. }
  787. /// <summary>
  788. /// Gets the value of the data cell with the specified index.
  789. /// </summary>
  790. /// <param name="index">Zero-based index of the data cell.</param>
  791. /// <returns>The cell's value.</returns>
  792. /// <remarks>
  793. /// Use this method in the cell's expression if the cell has custom totals
  794. /// (the total function is set to "Custom"). The example:
  795. /// <para/>Matrix1.Value(0) / Matrix1.Value(1)
  796. /// <para/>will return the result of dividing the first data cell's value by the second one.
  797. /// </remarks>
  798. public Variant Value(int index)
  799. {
  800. object value = Helper.CellValues[index];
  801. if (value == null)
  802. value = 0;
  803. return new Variant(value);
  804. }
  805. #endregion
  806. /// <summary>
  807. /// Initializes a new instance of the <see cref="MatrixObject"/> class.
  808. /// </summary>
  809. public MatrixObject()
  810. {
  811. autoSize = true;
  812. data = new MatrixData();
  813. manualBuildEvent = "";
  814. afterTotalsEvent = "";
  815. helper = new MatrixHelper(this);
  816. InitDesign();
  817. styleSheet = new MatrixStyleSheet();
  818. styleSheet.Load(ResourceLoader.GetStream("cross.frss"));
  819. style = "";
  820. filter = "";
  821. splitRows = false;
  822. printIfEmpty = true;
  823. }
  824. }
  825. }