rptgrouping.pp 10 KB

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