ReportEngine.Pages.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. using FastReport.Utils;
  2. using System;
  3. namespace FastReport.Engine
  4. {
  5. public partial class ReportEngine
  6. {
  7. #region Fields
  8. private ReportPage page;
  9. private float columnStartY;
  10. private string pageNameForRecalc;
  11. #endregion Fields
  12. #region Private Methods
  13. private DataBand FindDeepmostDataBand(ReportPage page)
  14. {
  15. DataBand result = null;
  16. foreach (Base c in page.AllObjects)
  17. {
  18. if (c is DataBand)
  19. result = c as DataBand;
  20. }
  21. return result;
  22. }
  23. private void RunReportPage(ReportPage page)
  24. {
  25. this.page = page;
  26. InitReprint();
  27. pageNameForRecalc = null;
  28. this.page.OnStartPage(EventArgs.Empty);
  29. bool previousPage = StartFirstPage();
  30. OnStateChanged(this.page, EngineState.ReportPageStarted);
  31. OnStateChanged(this.page, EngineState.PageStarted);
  32. DataBand keepSummaryBand = FindDeepmostDataBand(page);
  33. if (keepSummaryBand != null)
  34. keepSummaryBand.KeepSummary = true;
  35. if (this.page.IsManualBuild)
  36. this.page.OnManualBuild(EventArgs.Empty);
  37. else
  38. RunBands(page.Bands);
  39. OnStateChanged(this.page, EngineState.PageFinished);
  40. OnStateChanged(this.page, EngineState.ReportPageFinished);
  41. EndLastPage();
  42. //recalculate unlimited
  43. if (page.UnlimitedHeight || page.UnlimitedWidth)
  44. {
  45. PreparedPages.ModifyPageSize(page.Name);
  46. if (previousPage && pageNameForRecalc != null)
  47. PreparedPages.ModifyPageSize(pageNameForRecalc);
  48. }
  49. //recalculate unlimited
  50. this.page.OnFinishPage(EventArgs.Empty);
  51. if (this.page.BackPage)
  52. {
  53. PreparedPages.InterleaveWithBackPage(PreparedPages.CurPage);
  54. }
  55. }
  56. private bool CalcVisibleExpression(string expression)
  57. {
  58. bool result = true;
  59. object expressionObj = null;
  60. // Calculate expressions with TotalPages only on FinalPass.
  61. if (!expression.Contains("TotalPages") || (Report.DoublePass && FinalPass))
  62. {
  63. expressionObj = Report.Calc(Code.CodeUtils.FixExpressionWithBrackets(expression));
  64. }
  65. if (expressionObj != null && expressionObj is bool)
  66. {
  67. if (!expression.Contains("TotalPages"))
  68. {
  69. result = (bool)expressionObj;
  70. }
  71. else if (FirstPass)
  72. {
  73. result = true;
  74. }
  75. else
  76. {
  77. result = (bool)expressionObj;
  78. }
  79. }
  80. return result;
  81. }
  82. private void RunReportPages()
  83. {
  84. #if TIMETRIAL
  85. if (new DateTime($YEAR, $MONTH, $DAY) < System.DateTime.Now)
  86. throw new Exception("The trial version is now expired!");
  87. #endif
  88. for (int i = 0; i < Report.Pages.Count; i++)
  89. {
  90. ReportPage page = Report.Pages[i] as ReportPage;
  91. // Calc and apply visible expression if needed.
  92. if (page != null && !String.IsNullOrEmpty(page.VisibleExpression))
  93. {
  94. page.Visible = CalcVisibleExpression(page.VisibleExpression);
  95. }
  96. if (page != null && page.Visible && page.Subreport == null)
  97. RunReportPage(page);
  98. if (Report.Aborted)
  99. break;
  100. }
  101. }
  102. private void RunBands(BandCollection bands)
  103. {
  104. for (int i = 0; i < bands.Count; i++)
  105. {
  106. BandBase band = bands[i];
  107. if (band is DataBand)
  108. RunDataBand(band as DataBand);
  109. else if (band is GroupHeaderBand)
  110. RunGroup(band as GroupHeaderBand);
  111. if (Report.Aborted)
  112. break;
  113. }
  114. }
  115. private void ShowPageHeader()
  116. {
  117. ShowBand(page.PageHeader);
  118. }
  119. private void ShowPageFooter(bool startPage)
  120. {
  121. if (!FirstPass &&
  122. CurPage == TotalPages - 1 &&
  123. page.PageFooter != null &&
  124. (page.PageFooter.PrintOn & PrintOn.LastPage) > 0 &&
  125. (page.PageFooter.PrintOn & PrintOn.FirstPage) == 0 &&
  126. startPage)
  127. {
  128. ShiftLastPage();
  129. }
  130. else
  131. ShowBand(page.PageFooter);
  132. }
  133. private bool StartFirstPage()
  134. {
  135. page.InitializeComponents();
  136. CurX = 0;
  137. CurY = 0;
  138. curColumn = 0;
  139. if (page.ResetPageNumber)
  140. ResetLogicalPageNumber();
  141. bool previousPage = page.PrintOnPreviousPage && PreparedPages.Count > 0;
  142. // check that previous page has the same size
  143. if (previousPage)
  144. {
  145. using (ReportPage page0 = PreparedPages.GetPage(PreparedPages.Count - 1))
  146. {
  147. if (page0.PaperWidth == this.page.PaperWidth)
  148. {
  149. if (page0.UnlimitedWidth == this.page.UnlimitedWidth)
  150. {
  151. previousPage = true;
  152. if (this.page.UnlimitedWidth)
  153. pageNameForRecalc = page0.Name;
  154. }
  155. else
  156. {
  157. previousPage = false;
  158. }
  159. }
  160. else if (page0.UnlimitedWidth && this.page.UnlimitedWidth)
  161. {
  162. previousPage = true;
  163. pageNameForRecalc = page0.Name;
  164. }
  165. else
  166. {
  167. previousPage = false;
  168. }
  169. if (previousPage)
  170. {
  171. if (page0.PaperHeight == this.page.PaperHeight)
  172. {
  173. if (page0.UnlimitedHeight == this.page.UnlimitedHeight)
  174. {
  175. previousPage = true;
  176. if (this.page.UnlimitedHeight)
  177. pageNameForRecalc = page0.Name;
  178. }
  179. else
  180. {
  181. previousPage = false;
  182. }
  183. }
  184. else if (page0.UnlimitedHeight && this.page.UnlimitedHeight)
  185. {
  186. previousPage = true;
  187. }
  188. else
  189. {
  190. previousPage = false;
  191. }
  192. }
  193. }
  194. }
  195. // update CurY or add new page
  196. if (previousPage)
  197. CurY = PreparedPages.GetLastY();
  198. else
  199. {
  200. PreparedPages.AddPage(page);
  201. if (page.StartOnOddPage && (CurPage % 2) == 1)
  202. PreparedPages.AddPage(page);
  203. }
  204. // page numbers
  205. if (isFirstReportPage)
  206. firstReportPage = CurPage;
  207. if (isFirstReportPage && previousPage)
  208. IncLogicalPageNumber();
  209. isFirstReportPage = false;
  210. OutlineRoot();
  211. AddPageOutline();
  212. // show report title and page header
  213. if (previousPage)
  214. ShowBand(page.ReportTitle);
  215. else
  216. {
  217. if (page.Overlay != null)
  218. ShowBand(page.Overlay);
  219. if (page.TitleBeforeHeader)
  220. {
  221. ShowBand(page.ReportTitle);
  222. ShowPageHeader();
  223. }
  224. else
  225. {
  226. ShowPageHeader();
  227. ShowBand(page.ReportTitle);
  228. }
  229. }
  230. // show column header
  231. columnStartY = CurY;
  232. ShowBand(page.ColumnHeader);
  233. // calculate CurX before starting column event depending on Right to Left or Left to Right layout
  234. if (Config.RightToLeft)
  235. {
  236. CurX = page.Columns.Positions[page.Columns.Positions.Count - 1] * Units.Millimeters;
  237. }
  238. else
  239. {
  240. CurX = 0;
  241. }
  242. // start column event
  243. OnStateChanged(page, EngineState.ColumnStarted);
  244. ShowProgress();
  245. return previousPage;
  246. }
  247. private void EndLastPage()
  248. {
  249. // end column event
  250. OnStateChanged(page, EngineState.ColumnFinished);
  251. if (page.ReportSummary != null)
  252. {
  253. // do not show column footer here! It's a special case and is handled in the ShowBand.
  254. ShowBand(page.ReportSummary);
  255. }
  256. else
  257. {
  258. ShowBand(page.ColumnFooter);
  259. }
  260. ShowPageFooter(false);
  261. OutlineRoot();
  262. page.FinalizeComponents();
  263. }
  264. internal void EndColumn()
  265. {
  266. EndColumn(true);
  267. }
  268. private void EndColumn(bool showColumnFooter)
  269. {
  270. // end column event
  271. OnStateChanged(page, EngineState.ColumnFinished);
  272. // check keep
  273. if (keeping)
  274. CutObjects();
  275. ShowReprintFooters();
  276. if (showColumnFooter)
  277. ShowBand(page.ColumnFooter);
  278. curColumn++;
  279. if (curColumn >= page.Columns.Count)
  280. curColumn = 0;
  281. // apply Right to Left layot if needed
  282. if (Config.RightToLeft)
  283. {
  284. curX = page.Columns.Positions[page.Columns.Count - curColumn - 1] * Units.Millimeters;
  285. }
  286. else
  287. {
  288. curX = curColumn == 0 ? 0 : page.Columns.Positions[curColumn] * Units.Millimeters;
  289. }
  290. if (CurColumn == 0)
  291. {
  292. EndPage();
  293. }
  294. else
  295. {
  296. StartColumn();
  297. }
  298. // end keep
  299. if (keeping)
  300. PasteObjects();
  301. }
  302. private void StartColumn()
  303. {
  304. curY = columnStartY;
  305. ShowBand(page.ColumnHeader);
  306. ShowReprintHeaders();
  307. // start column event
  308. OnStateChanged(page, EngineState.ColumnStarted);
  309. }
  310. private void EndPage()
  311. {
  312. EndPage(true);
  313. }
  314. private void StartPage()
  315. {
  316. // apply Right to Left layout if needed
  317. if (Config.RightToLeft)
  318. {
  319. CurX = page.Columns.Positions[page.Columns.Positions.Count - 1] * Units.Millimeters;
  320. }
  321. else
  322. {
  323. CurX = 0;
  324. }
  325. CurY = 0;
  326. curColumn = 0;
  327. PreparedPages.AddPage(page);
  328. AddPageOutline();
  329. if (page.Overlay != null)
  330. ShowBand(page.Overlay);
  331. ShowPageHeader();
  332. OnStateChanged(page, EngineState.PageStarted);
  333. columnStartY = CurY;
  334. StartColumn();
  335. ShowProgress();
  336. }
  337. #endregion Private Methods
  338. #region Internal Methods
  339. internal void EndPage(bool startPage)
  340. {
  341. OnStateChanged(page, EngineState.PageFinished);
  342. ShowPageFooter(startPage);
  343. if (pagesLimit > 0 && PreparedPages.Count >= pagesLimit)
  344. Report.Abort();
  345. if (Report.MaxPages > 0 && PreparedPages.Count >= Report.MaxPages)
  346. Report.Abort();
  347. if (startPage)
  348. StartPage();
  349. }
  350. #endregion Internal Methods
  351. #region Public Methods
  352. /// <summary>
  353. /// Starts a new page.
  354. /// </summary>
  355. public void StartNewPage()
  356. {
  357. EndPage();
  358. }
  359. /// <summary>
  360. /// Starts a new column.
  361. /// </summary>
  362. public void StartNewColumn()
  363. {
  364. EndColumn();
  365. }
  366. #endregion Public Methods
  367. }
  368. }