ReportEngine.Groups.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. using FastReport.Data;
  2. using System.Collections.Generic;
  3. namespace FastReport.Engine
  4. {
  5. public partial class ReportEngine
  6. {
  7. #region Private Classes
  8. private class GroupTreeItem
  9. {
  10. #region Fields
  11. private GroupHeaderBand band;
  12. private List<GroupTreeItem> items;
  13. private int rowNo;
  14. private int rowCount;
  15. #endregion Fields
  16. #region Properties
  17. public GroupHeaderBand Band
  18. {
  19. get { return band; }
  20. }
  21. public List<GroupTreeItem> Items
  22. {
  23. get { return items; }
  24. }
  25. public GroupTreeItem FirstItem
  26. {
  27. get { return Items.Count == 0 ? null : Items[0]; }
  28. }
  29. public GroupTreeItem LastItem
  30. {
  31. get { return Items.Count == 0 ? null : Items[Items.Count - 1]; }
  32. }
  33. public int RowNo
  34. {
  35. get { return rowNo; }
  36. set { rowNo = value; }
  37. }
  38. public int RowCount
  39. {
  40. get { return rowCount; }
  41. set { rowCount = value; }
  42. }
  43. #endregion Properties
  44. #region Constructors
  45. public GroupTreeItem(GroupHeaderBand band)
  46. {
  47. this.band = band;
  48. items = new List<GroupTreeItem>();
  49. }
  50. #endregion Constructors
  51. #region Public Methods
  52. public GroupTreeItem AddItem(GroupTreeItem item)
  53. {
  54. Items.Add(item);
  55. return item;
  56. }
  57. #endregion Public Methods
  58. }
  59. #endregion Private Classes
  60. #region Private Methods
  61. private void ShowDataHeader(GroupHeaderBand groupBand)
  62. {
  63. groupBand.RowNo = 0;
  64. DataHeaderBand header = groupBand.Header;
  65. if (header != null)
  66. {
  67. ShowBand(header);
  68. if (header.RepeatOnEveryPage)
  69. AddReprint(header);
  70. }
  71. DataFooterBand footer = groupBand.Footer;
  72. if (footer != null)
  73. {
  74. if (footer.RepeatOnEveryPage)
  75. AddReprint(footer);
  76. }
  77. }
  78. private void ShowDataFooter(GroupHeaderBand groupBand)
  79. {
  80. DataFooterBand footer = groupBand.Footer;
  81. RemoveReprint(footer);
  82. ShowBand(footer);
  83. RemoveReprint(groupBand.Header);
  84. }
  85. private void ShowGroupHeader(GroupHeaderBand header)
  86. {
  87. header.AbsRowNo++;
  88. header.RowNo++;
  89. if (header.ResetPageNumber && (header.FirstRowStartsNewPage || header.RowNo > 1))
  90. ResetLogicalPageNumber();
  91. if (header.KeepTogether)
  92. StartKeep(header);
  93. if (header.KeepWithData)
  94. StartKeep(header.GroupDataBand);
  95. // start group event
  96. OnStateChanged(header, EngineState.GroupStarted);
  97. ShowBand(header);
  98. if (header.RepeatOnEveryPage)
  99. AddReprint(header);
  100. GroupFooterBand footer = header.GroupFooter;
  101. if (footer != null)
  102. {
  103. if (footer.RepeatOnEveryPage)
  104. AddReprint(footer);
  105. }
  106. }
  107. private void ShowGroupFooter(GroupHeaderBand header)
  108. {
  109. // finish group event
  110. OnStateChanged(header, EngineState.GroupFinished);
  111. // rollback to previous data row to print the header condition in the footer.
  112. DataBand dataBand = header.GroupDataBand;
  113. DataSourceBase dataSource = dataBand.DataSource;
  114. dataSource.Prior();
  115. GroupFooterBand footer = header.GroupFooter;
  116. if (footer != null)
  117. {
  118. footer.AbsRowNo++;
  119. footer.RowNo++;
  120. }
  121. RemoveReprint(footer);
  122. ShowBand(footer);
  123. RemoveReprint(header);
  124. // restore current row
  125. dataSource.Next();
  126. OutlineUp(header);
  127. if (header.KeepTogether)
  128. EndKeep();
  129. if (footer != null && footer.KeepWithData)
  130. EndKeep();
  131. }
  132. private void InitGroupItem(GroupHeaderBand header, GroupTreeItem curItem)
  133. {
  134. while (header != null)
  135. {
  136. header.ResetGroupValue();
  137. header.AbsRowNo = 0;
  138. header.RowNo = 0;
  139. curItem = curItem.AddItem(new GroupTreeItem(header));
  140. curItem.RowNo = header.DataSource.CurrentRowNo;
  141. curItem.RowCount++;
  142. header = header.NestedGroup;
  143. }
  144. }
  145. private void CheckGroupItem(GroupHeaderBand header, GroupTreeItem curItem)
  146. {
  147. while (header != null)
  148. {
  149. if (header.GroupValueChanged())
  150. {
  151. InitGroupItem(header, curItem);
  152. break;
  153. }
  154. header = header.NestedGroup;
  155. curItem = curItem.LastItem;
  156. curItem.RowCount++;
  157. }
  158. }
  159. private GroupTreeItem MakeGroupTree(GroupHeaderBand groupBand)
  160. {
  161. GroupTreeItem rootItem = new GroupTreeItem(null);
  162. DataSourceBase dataSource = groupBand.DataSource;
  163. bool isFirstRow = true;
  164. // cycle through rows
  165. dataSource.First();
  166. while (dataSource.HasMoreRows)
  167. {
  168. if (isFirstRow)
  169. InitGroupItem(groupBand, rootItem);
  170. else
  171. CheckGroupItem(groupBand, rootItem);
  172. dataSource.Next();
  173. isFirstRow = false;
  174. if (Report.Aborted)
  175. break;
  176. }
  177. return rootItem;
  178. }
  179. private void ShowGroupTree(GroupTreeItem root)
  180. {
  181. if (root.Band != null)
  182. {
  183. root.Band.GroupDataBand.DataSource.CurrentRowNo = root.RowNo;
  184. ShowGroupHeader(root.Band);
  185. }
  186. if (root.Items.Count == 0)
  187. {
  188. if (root.RowCount != 0)
  189. {
  190. int rowCount = root.RowCount;
  191. int maxRows = root.Band.GroupDataBand.MaxRows;
  192. if (maxRows > 0 && rowCount > maxRows)
  193. rowCount = maxRows;
  194. bool keepFirstRow = NeedKeepFirstRow(root.Band);
  195. bool keepLastRow = NeedKeepLastRow(root.Band.GroupDataBand);
  196. RunDataBand(root.Band.GroupDataBand, rowCount, keepFirstRow, keepLastRow);
  197. }
  198. }
  199. else
  200. {
  201. ShowDataHeader(root.FirstItem.Band);
  202. for (int i = 0; i < root.Items.Count; i++)
  203. {
  204. GroupTreeItem item = root.Items[i];
  205. item.Band.IsFirstRow = i == 0;
  206. item.Band.IsLastRow = i == root.Items.Count - 1;
  207. ShowGroupTree(item);
  208. if (Report.Aborted)
  209. break;
  210. }
  211. ShowDataFooter(root.FirstItem.Band);
  212. }
  213. if (root.Band != null)
  214. ShowGroupFooter(root.Band);
  215. }
  216. private void RunGroup(GroupHeaderBand groupBand)
  217. {
  218. DataSourceBase dataSource = groupBand.DataSource;
  219. if (dataSource != null)
  220. {
  221. // init the datasource - set group conditions to sort data rows
  222. groupBand.InitDataSource();
  223. // show the group tree
  224. ShowGroupTree(MakeGroupTree(groupBand));
  225. // finalize the datasource, remove the group condition
  226. // from the databand sort
  227. groupBand.FinalizeDataSource();
  228. // do not leave the datasource in EOF state to allow print something in the footer
  229. dataSource.Prior();
  230. }
  231. }
  232. #endregion Private Methods
  233. }
  234. }