rptgrouping.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. unit rptgrouping;
  2. {$mode objfpc}{$H+}
  3. {$I demos.inc}
  4. interface
  5. uses
  6. Classes,
  7. SysUtils,
  8. fpreport,
  9. udapp;
  10. type
  11. { TGroupingDemo }
  12. TGroupingDemo = class(TReportDemoApp)
  13. private
  14. lReportData: TFPReportUserData;
  15. sl: TStringList;
  16. procedure GetReportDataFirst(Sender: TObject);
  17. procedure GetReportDataValue(Sender: TObject; const AValueName: String; var AValue: Variant);
  18. procedure GetReportDataEOF(Sender: TObject; var IsEOF: Boolean);
  19. procedure GetReportFieldNames(Sender: TObject; List: TStrings);
  20. Protected
  21. procedure InitialiseData; override;
  22. procedure CreateReportDesign;override;
  23. procedure LoadDesignFromFile(const AFilename: string);
  24. procedure HookupData(const AComponentName: string; const AData: TFPReportData);
  25. public
  26. constructor Create(AOWner :TComponent); override;
  27. destructor Destroy; override;
  28. Class function Description : string; override;
  29. end;
  30. implementation
  31. uses
  32. fpReportStreamer,
  33. fpTTF,
  34. fpJSON,
  35. fpexprpars,
  36. jsonparser;
  37. { TGroupingDemo }
  38. procedure TGroupingDemo.GetReportDataFirst(Sender: TObject);
  39. begin
  40. {$IFDEF gdebug}
  41. writeln('GetReportDataFirst');
  42. {$ENDIF}
  43. end;
  44. procedure TGroupingDemo.GetReportDataValue(Sender: TObject; const AValueName: String; var AValue: Variant);
  45. begin
  46. {$IFDEF gdebug}
  47. writeln(Format('GetReportDataValue - %d', [lReportData.RecNo]));
  48. {$ENDIF}
  49. if AValueName = 'country' then
  50. begin
  51. AValue := sl.Names[lReportData.RecNo-1];
  52. end
  53. else if AValueName = 'population' then
  54. begin
  55. AValue := sl.Values[sl.Names[lReportData.RecNo-1]];
  56. end;
  57. end;
  58. procedure TGroupingDemo.GetReportDataEOF(Sender: TObject; var IsEOF: Boolean);
  59. begin
  60. {$IFDEF gdebug}
  61. writeln(Format('GetReportDataEOF - %d', [lReportData.RecNo]));
  62. {$ENDIF}
  63. if lReportData.RecNo > sl.Count then
  64. IsEOF := True
  65. else
  66. IsEOF := False;
  67. end;
  68. procedure TGroupingDemo.GetReportFieldNames(Sender: TObject; List: TStrings);
  69. begin
  70. {$IFDEF gdebug}
  71. writeln('********** GetReportFieldNames');
  72. {$ENDIF}
  73. List.Add('country');
  74. List.Add('population');
  75. end;
  76. procedure TGroupingDemo.InitialiseData;
  77. begin
  78. sl := TStringList.Create;
  79. {$I countries.inc}
  80. sl.Sort;
  81. end;
  82. procedure TGroupingDemo.CreateReportDesign;
  83. var
  84. p: TFPReportPage;
  85. TitleBand: TFPReportTitleBand;
  86. DataBand: TFPReportDataBand;
  87. GroupHeader: TFPReportGroupHeaderBand;
  88. Memo: TFPReportMemo;
  89. PageFooter: TFPReportPageFooterBand;
  90. GroupFooter: TFPReportGroupFooterBand;
  91. begin
  92. Inherited;
  93. rpt.Author := 'Graeme Geldenhuys';
  94. rpt.Title := 'FPReport Demo 3 - Grouping';
  95. {*** page ***}
  96. p := TFPReportPage.Create(rpt);
  97. p.Orientation := poPortrait;
  98. p.PageSize.PaperName := 'A4';
  99. { page margins }
  100. p.Margins.Left := 30;
  101. p.Margins.Top := 20;
  102. p.Margins.Right := 30;
  103. p.Margins.Bottom := 20;
  104. p.Data := lReportData;
  105. p.Font.Name := 'LiberationSans';
  106. {*** title ***}
  107. TitleBand := TFPReportTitleBand.Create(p);
  108. TitleBand.Layout.Height := 40;
  109. {$IFDEF ColorBands}
  110. TitleBand.Frame.Shape := fsRectangle;
  111. TitleBand.Frame.BackgroundColor := clReportTitleSummary;
  112. {$ENDIF}
  113. Memo := TFPReportMemo.Create(TitleBand);
  114. Memo.Layout.Left := 0;
  115. Memo.Layout.Top := 20;
  116. Memo.Layout.Width := p.PageSize.Width - p.Margins.Left - p.Margins.Right;
  117. Memo.Layout.Height := 10;
  118. Memo.TextAlignment.Horizontal := taCentered;
  119. Memo.Text := 'COUNTRY AND POPULATION AS OF 2014';
  120. Memo := TFPReportMemo.Create(TitleBand);
  121. Memo.Layout.Left := 0;
  122. Memo.Layout.Top := 25;
  123. Memo.Layout.Width := p.PageSize.Width - p.Margins.Left - p.Margins.Right;
  124. Memo.Layout.Height := 10;
  125. Memo.TextAlignment.Horizontal := taCentered;
  126. Memo.Text := '(Total [formatfloat(''#,##0.0'',sum_population_in_M / 1000)] B)';
  127. {*** group header ***}
  128. GroupHeader := TFPReportGroupHeaderBand.Create(p);
  129. GroupHeader.Layout.Height := 15;
  130. GroupHeader.GroupCondition := 'copy(data.country,1,1)';
  131. {$ifdef ColorBands}
  132. GroupHeader.Frame.Shape := fsRectangle;
  133. GroupHeader.Frame.BackgroundColor := clGroupHeaderFooter;
  134. {$endif}
  135. Memo := TFPReportMemo.Create(GroupHeader);
  136. Memo.Layout.Left := 5;
  137. Memo.Layout.Top := 3;
  138. Memo.Layout.Width := 10;
  139. Memo.Layout.Height := 8;
  140. Memo.UseParentFont := False;
  141. Memo.Text := '[copy(data.country,1,1)]';
  142. Memo.Font.Size := 16;
  143. Memo := TFPReportMemo.Create(GroupHeader);
  144. Memo.Layout.Left := 25;
  145. Memo.Layout.Top := 3;
  146. Memo.Layout.Width := 100;
  147. Memo.Layout.Height := 8;
  148. Memo.UseParentFont := False;
  149. Memo.TextAlignment.Horizontal := taRightJustified;
  150. Memo.Text := '[formatfloat(''#,##0.0'', grp_sum_population_in_M)] M - [formatfloat(''#0.0'', grp_sum_population / sum_population * 100)] % ';
  151. Memo.Font.Size := 16;
  152. Memo := TFPReportMemo.Create(GroupHeader);
  153. Memo.Layout.Left := 105;
  154. Memo.Layout.Top := 11;
  155. Memo.Layout.Width := 20;
  156. Memo.Layout.Height := 4;
  157. Memo.TextAlignment.Horizontal := taRightJustified;
  158. Memo.Text := 'Group %';
  159. Memo := TFPReportMemo.Create(GroupHeader);
  160. Memo.Layout.Left := 130;
  161. Memo.Layout.Top := 11;
  162. Memo.Layout.Width := 15;
  163. Memo.Layout.Height := 4;
  164. Memo.TextAlignment.Horizontal := taRightJustified;
  165. Memo.Text := 'Total %';
  166. {*** variables ***}
  167. rpt.Variables.AddExprVariable('population_in_M', 'sum(StrToFloat(data.population) / 1000000)', rtFloat, rtNone, '');
  168. rpt.Variables.AddExprVariable('grp_sum_population', 'sum(StrToFloat(data.population))',rtFloat , GroupHeader);
  169. rpt.Variables.AddExprVariable('grp_sum_population_in_M', 'sum(StrToFloat(data.population) / 1000000)', rtFloat, GroupHeader);
  170. rpt.Variables.AddExprVariable('sum_population', 'sum(StrToFloat(data.population))', rtFloat, rtnone, '');
  171. rpt.Variables.AddExprVariable('sum_population_in_M', 'sum(StrToFloat(data.population) / 1000000)', rtFloat,rtnone,'');
  172. {*** detail ***}
  173. DataBand := TFPReportDataBand.Create(p);
  174. DataBand.Layout.Height := 8;
  175. {$ifdef ColorBands}
  176. DataBand.Frame.Shape := fsRectangle;
  177. DataBand.Frame.BackgroundColor := clDataBand;
  178. {$endif}
  179. //DataBand.VisibleExpr := 'StrToFloat(''[population]'') > 50000000';
  180. Memo := TFPReportMemo.Create(DataBand);
  181. Memo.Layout.Left := 15;
  182. Memo.Layout.Top := 2;
  183. Memo.Layout.Width := 45;
  184. Memo.Layout.Height := 5;
  185. Memo.Text := '[data.country]';
  186. Memo := TFPReportMemo.Create(DataBand);
  187. Memo.Layout.Left := 55;
  188. Memo.Layout.Top := 2;
  189. Memo.Layout.Width := 25;
  190. Memo.Layout.Height := 5;
  191. Memo.TextAlignment.Horizontal := taRightJustified;
  192. Memo.Text := '[formatfloat(''#,##0.0'', population_in_M)] M';
  193. //Memo.VisibleExpr := 'StrToFloat(''[population]'') > 50000000';
  194. Memo := TFPReportMemo.Create(DataBand);
  195. Memo.Layout.Left := 85;
  196. Memo.Layout.Top := 2;
  197. Memo.Layout.Width := 20;
  198. Memo.Layout.Height := 5;
  199. Memo.Text := '> Germany';
  200. Memo.UseParentFont := false;
  201. Memo.Font.Color := clGreen;
  202. Memo.VisibleExpr := 'StrToFloat(data.population) > 80890000';
  203. Memo := TFPReportMemo.Create(DataBand);
  204. Memo.Layout.Left := 85;
  205. Memo.Layout.Top := 2;
  206. Memo.Layout.Width := 20;
  207. Memo.Layout.Height := 5;
  208. Memo.Text := '< Germany';
  209. Memo.UseParentFont := false;
  210. Memo.Font.Color := clRed;
  211. Memo.VisibleExpr := 'StrToFloat(data.population) < 80890000';
  212. Memo := TFPReportMemo.Create(DataBand);
  213. Memo.Layout.Left := 110;
  214. Memo.Layout.Top := 2;
  215. Memo.Layout.Width := 15;
  216. Memo.Layout.Height := 5;
  217. Memo.TextAlignment.Horizontal := taRightJustified;
  218. Memo.Text := '[formatfloat(''#,##0.0'',StrToFloat(data.population)/grp_sum_population*100)] %';
  219. Memo := TFPReportMemo.Create(DataBand);
  220. Memo.Layout.Left := 130;
  221. Memo.Layout.Top := 2;
  222. Memo.Layout.Width := 15;
  223. Memo.Layout.Height := 5;
  224. Memo.TextAlignment.Horizontal := taRightJustified;
  225. Memo.Text := '[formatfloat(''#,##0.0'',StrToFloat(data.population)/sum_population*100)] %';
  226. {*** group footer ***}
  227. GroupFooter := TFPReportGroupFooterBand.Create(p);
  228. GroupFooter.Layout.Height := 15;
  229. GroupFooter.GroupHeader := GroupHeader;
  230. {$ifdef ColorBands}
  231. GroupFooter.Frame.Shape := fsRectangle;
  232. GroupFooter.Frame.BackgroundColor := clGroupHeaderFooter;
  233. {$endif}
  234. Memo := TFPReportMemo.Create(GroupFooter);
  235. Memo.Layout.Left := 25;
  236. Memo.Layout.Top := 5;
  237. Memo.Layout.Width := 100;
  238. Memo.Layout.Height := 8;
  239. Memo.UseParentFont := False;
  240. Memo.TextAlignment.Horizontal := taRightJustified;
  241. Memo.Text := '[formatfloat(''#,##0'', grp_sum_population)] - [formatfloat(''#0.0'', grp_sum_population / sum_population * 100)] % ';
  242. Memo.Font.Size := 16;
  243. {*** page footer ***}
  244. PageFooter := TFPReportPageFooterBand.Create(p);
  245. PageFooter.Layout.Height := 20;
  246. {$ifdef ColorBands}
  247. PageFooter.Frame.Shape := fsRectangle;
  248. PageFooter.Frame.BackgroundColor := clPageHeaderFooter;
  249. {$endif}
  250. Memo := TFPReportMemo.Create(PageFooter);
  251. Memo.Layout.Left := 100;
  252. Memo.Layout.Top := 13;
  253. Memo.Layout.Width := 50;
  254. Memo.Layout.Height := 5;
  255. Memo.Text := 'Page [PageNo] of [PAGECOUNT]';
  256. Memo.TextAlignment.Vertical := tlCenter;
  257. Memo.TextAlignment.Horizontal := taRightJustified;
  258. Memo := TFPReportMemo.Create(PageFooter);
  259. Memo.Layout.Left := 25;
  260. Memo.Layout.Top := 5;
  261. Memo.Layout.Width := 100;
  262. Memo.Layout.Height := 8;
  263. Memo.UseParentFont := False;
  264. Memo.TextAlignment.Horizontal := taRightJustified;
  265. Memo.Text := '[formatfloat(''#,##0'', sum_population)]';
  266. Memo.Font.Size := 16;
  267. end;
  268. procedure TGroupingDemo.LoadDesignFromFile(const AFilename: string);
  269. var
  270. rs: TFPReportJSONStreamer;
  271. fs: TFileStream;
  272. lJSON: TJSONObject;
  273. begin
  274. if AFilename = '' then
  275. Exit;
  276. if not FileExists(AFilename) then
  277. raise Exception.CreateFmt('The file "%s" can not be found', [AFilename]);
  278. fs := TFileStream.Create(AFilename, fmOpenRead or fmShareDenyNone);
  279. try
  280. lJSON := TJSONObject(GetJSON(fs));
  281. finally
  282. fs.Free;
  283. end;
  284. rs := TFPReportJSONStreamer.Create(nil);
  285. rs.JSON := lJSON; // rs takes ownership of lJSON
  286. try
  287. rpt.ReadElement(rs);
  288. finally
  289. rs.Free;
  290. end;
  291. end;
  292. procedure TGroupingDemo.HookupData(const AComponentName: string; const AData: TFPReportData);
  293. var
  294. b: TFPReportCustomBandWithData;
  295. begin
  296. b := TFPReportCustomBandWithData(rpt.FindRecursive(AComponentName));
  297. if Assigned(b) then
  298. b.Data := AData;
  299. end;
  300. constructor TGroupingDemo.Create(AOwner: TComponent);
  301. begin
  302. inherited;
  303. lReportData := TFPReportUserData.Create(nil);
  304. lReportData.Name := 'data';
  305. lReportData.OnGetValue := @GetReportDataValue;
  306. lReportData.OnGetEOF := @GetReportDataEOF;
  307. lReportData.OnFirst := @GetReportDataFirst;
  308. lReportData.OnGetNames := @GetReportFieldNames;
  309. end;
  310. destructor TGroupingDemo.Destroy;
  311. begin
  312. FreeAndNil(lReportData);
  313. FreeAndNil(sl);
  314. inherited Destroy;
  315. end;
  316. class function TGroupingDemo.Description: string;
  317. begin
  318. Result:='Demo showing grouping';
  319. end;
  320. end.