ReportEngine.Pages.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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 void RunReportPages()
  57. {
  58. #if TIMETRIAL
  59. if (new DateTime($YEAR, $MONTH, $DAY) < System.DateTime.Now)
  60. throw new Exception("The trial version is now expired!");
  61. #endif
  62. for (int i = 0; i < Report.Pages.Count; i++)
  63. {
  64. ReportPage page = Report.Pages[i] as ReportPage;
  65. // Calc and apply visible expression if needed.
  66. if (page != null && !String.IsNullOrEmpty(page.VisibleExpression))
  67. {
  68. page.Visible = page.CalcVisibleExpression(page.VisibleExpression);
  69. }
  70. if (page != null && page.Visible && page.Subreport == null)
  71. RunReportPage(page);
  72. if (Report.Aborted)
  73. break;
  74. }
  75. }
  76. private void RunBands(BandCollection bands)
  77. {
  78. for (int i = 0; i < bands.Count; i++)
  79. {
  80. BandBase band = bands[i];
  81. if (band is DataBand)
  82. RunDataBand(band as DataBand);
  83. else if (band is GroupHeaderBand)
  84. RunGroup(band as GroupHeaderBand);
  85. if (Report.Aborted)
  86. break;
  87. }
  88. }
  89. private void ShowPageHeader()
  90. {
  91. ShowBand(page.PageHeader);
  92. }
  93. private void ShowPageFooter(bool startPage)
  94. {
  95. if (!FirstPass &&
  96. CurPage == TotalPages - 1 &&
  97. page.PageFooter != null &&
  98. (page.PageFooter.PrintOn & PrintOn.LastPage) > 0 &&
  99. (page.PageFooter.PrintOn & PrintOn.FirstPage) == 0 &&
  100. startPage)
  101. {
  102. ShiftLastPage();
  103. }
  104. else
  105. ShowBand(page.PageFooter);
  106. }
  107. private bool StartFirstPage()
  108. {
  109. page.InitializeComponents();
  110. CurX = 0;
  111. CurY = 0;
  112. curColumn = 0;
  113. // Disable columns of page when page has DataBand with columns and these columns has "across then down" layout.
  114. // Without this fix, columns of page will be printed over columns of band when pages more than one.
  115. if (page.Columns.Count > 1)
  116. {
  117. foreach (BandBase band in page.Bands)
  118. {
  119. if (band is DataBand && (band as DataBand).Columns.Count > 1 &&
  120. (band as DataBand).Columns.Layout == ColumnLayout.AcrossThenDown)
  121. page.Columns.Count = 1;
  122. }
  123. }
  124. if (page.ResetPageNumber)
  125. ResetLogicalPageNumber();
  126. bool previousPage = page.PrintOnPreviousPage && PreparedPages.Count > 0;
  127. // check that previous page has the same size
  128. if (previousPage)
  129. {
  130. using (ReportPage page0 = PreparedPages.GetPage(PreparedPages.Count - 1))
  131. {
  132. if (page0.PaperWidth == this.page.PaperWidth)
  133. {
  134. if (page0.UnlimitedWidth == this.page.UnlimitedWidth)
  135. {
  136. previousPage = true;
  137. if (this.page.UnlimitedWidth)
  138. pageNameForRecalc = page0.Name;
  139. }
  140. else
  141. {
  142. previousPage = false;
  143. }
  144. }
  145. else if (page0.UnlimitedWidth && this.page.UnlimitedWidth)
  146. {
  147. previousPage = true;
  148. pageNameForRecalc = page0.Name;
  149. }
  150. else
  151. {
  152. previousPage = false;
  153. }
  154. if (previousPage)
  155. {
  156. if (page0.PaperHeight == this.page.PaperHeight)
  157. {
  158. if (page0.UnlimitedHeight == this.page.UnlimitedHeight)
  159. {
  160. previousPage = true;
  161. if (this.page.UnlimitedHeight)
  162. pageNameForRecalc = page0.Name;
  163. }
  164. else
  165. {
  166. previousPage = false;
  167. }
  168. }
  169. else if (page0.UnlimitedHeight && this.page.UnlimitedHeight)
  170. {
  171. previousPage = true;
  172. }
  173. else
  174. {
  175. previousPage = false;
  176. }
  177. }
  178. }
  179. }
  180. // update CurY or add new page
  181. if (previousPage)
  182. CurY = PreparedPages.GetLastY();
  183. else
  184. {
  185. page.OnCreatePage(EventArgs.Empty);
  186. PreparedPages.AddPage(page);
  187. if (page.StartOnOddPage && (CurPage % 2) == 1)
  188. PreparedPages.AddPage(page);
  189. }
  190. // page numbers
  191. if (isFirstReportPage)
  192. firstReportPage = CurPage;
  193. if (isFirstReportPage && previousPage)
  194. IncLogicalPageNumber();
  195. isFirstReportPage = false;
  196. OutlineRoot();
  197. AddPageOutline();
  198. // show report title and page header
  199. if (previousPage)
  200. ShowBand(page.ReportTitle);
  201. else
  202. {
  203. if (page.Overlay != null)
  204. ShowBand(page.Overlay);
  205. if (page.TitleBeforeHeader)
  206. {
  207. ShowBand(page.ReportTitle);
  208. ShowPageHeader();
  209. }
  210. else
  211. {
  212. ShowPageHeader();
  213. ShowBand(page.ReportTitle);
  214. }
  215. }
  216. // show column header
  217. columnStartY = CurY;
  218. ShowBand(page.ColumnHeader);
  219. // calculate CurX before starting column event depending on Right to Left or Left to Right layout
  220. if (Config.RightToLeft)
  221. {
  222. CurX = page.Columns.Positions[page.Columns.Positions.Count - 1] * Units.Millimeters;
  223. }
  224. else
  225. {
  226. CurX = page.Columns.Positions[0] * Units.Millimeters;
  227. }
  228. // start column event
  229. OnStateChanged(page, EngineState.ColumnStarted);
  230. ShowProgress();
  231. return previousPage;
  232. }
  233. private void EndLastPage()
  234. {
  235. // end column event
  236. OnStateChanged(page, EngineState.ColumnFinished);
  237. if (page.ReportSummary != null)
  238. {
  239. // do not show column footer here! It's a special case and is handled in the ShowBand.
  240. ShowBand(page.ReportSummary);
  241. }
  242. else
  243. {
  244. ShowBand(page.ColumnFooter);
  245. }
  246. ShowPageFooter(false);
  247. OutlineRoot();
  248. page.FinalizeComponents();
  249. }
  250. internal void EndColumn()
  251. {
  252. EndColumn(true);
  253. }
  254. private void EndColumn(bool showColumnFooter)
  255. {
  256. // end column event
  257. OnStateChanged(page, EngineState.ColumnFinished);
  258. // check keep
  259. if (keeping)
  260. CutObjects();
  261. ShowReprintFooters();
  262. if (showColumnFooter)
  263. ShowBand(page.ColumnFooter);
  264. curColumn++;
  265. if (curColumn >= page.Columns.Count)
  266. curColumn = 0;
  267. // apply Right to Left layout if needed
  268. if (Config.RightToLeft)
  269. {
  270. curX = page.Columns.Positions[page.Columns.Count - curColumn - 1] * Units.Millimeters;
  271. }
  272. else
  273. {
  274. curX = page.Columns.Positions[curColumn] * Units.Millimeters;
  275. }
  276. if (CurColumn == 0)
  277. {
  278. EndPage();
  279. }
  280. else
  281. {
  282. StartColumn();
  283. }
  284. // end keep
  285. if (keeping)
  286. PasteObjects();
  287. }
  288. private void StartColumn()
  289. {
  290. curY = columnStartY;
  291. ShowBand(page.ColumnHeader);
  292. ShowReprintHeaders();
  293. // start column event
  294. OnStateChanged(page, EngineState.ColumnStarted);
  295. }
  296. private void EndPage()
  297. {
  298. EndPage(true);
  299. }
  300. private void StartPage()
  301. {
  302. page.OnCreatePage(EventArgs.Empty);
  303. // apply Right to Left layout if needed
  304. if (Config.RightToLeft)
  305. {
  306. CurX = page.Columns.Positions[page.Columns.Positions.Count - 1] * Units.Millimeters;
  307. }
  308. else
  309. {
  310. CurX = page.Columns.Positions[0] * Units.Millimeters;
  311. }
  312. CurY = 0;
  313. curColumn = 0;
  314. PreparedPages.AddPage(page);
  315. AddPageOutline();
  316. if (page.Overlay != null)
  317. ShowBand(page.Overlay);
  318. ShowPageHeader();
  319. OnStateChanged(page, EngineState.PageStarted);
  320. columnStartY = CurY;
  321. StartColumn();
  322. ShowProgress();
  323. }
  324. #endregion Private Methods
  325. #region Internal Methods
  326. internal void EndPage(bool startPage)
  327. {
  328. OnStateChanged(page, EngineState.PageFinished);
  329. ShowPageFooter(startPage);
  330. if (pagesLimit > 0 && PreparedPages.Count >= pagesLimit)
  331. Report.Abort();
  332. if (Report.MaxPages > 0 && PreparedPages.Count >= Report.MaxPages)
  333. Report.Abort();
  334. if (startPage)
  335. StartPage();
  336. }
  337. #endregion Internal Methods
  338. #region Public Methods
  339. /// <summary>
  340. /// Starts a new page.
  341. /// </summary>
  342. public void StartNewPage()
  343. {
  344. EndPage();
  345. }
  346. /// <summary>
  347. /// Starts a new column.
  348. /// </summary>
  349. public void StartNewColumn()
  350. {
  351. EndColumn();
  352. }
  353. #endregion Public Methods
  354. }
  355. }