Fast Reports Non Database
Asked Answered
P

4

7

I have been using Report Builder for some years, but I am getting tired of the cha-ching, cha-ching. It is a great reporting tool for "non database" reports.

I have started playing around with Fast Reports and I am utterly flustered with it. It seems a great reporting tool for databases but big question mark concerning complex "non database" reports. Their demos and help are horrible.

Wished I could show a report I am talking about. The report is a serial communications report that has operating system information which of course is single in nature. It has 4 distinct table which has installed serial ports and USB Serial Device tables. It also has a summary memo.

Has anyone successfully designed a report of the above configuration in Fast Reports? And yes, I have posted the same query with Fast Reports. Just want other opinions.

Thanks in advance.

Putnam answered 12/1, 2014 at 18:3 Comment(7)
Are you aware that you can access report controls from Delphi code ? So even if you want to avoid using datasets (even when they could be just in-memory tables), you can still fill those controls "manually".Floorman
Yes, I am aware of that and I have tried every trick in the world to access those controls. Perhaps you have knowledge to do this. If so, please enlighten me. Just need to know how to place text in a memo control. I tried TfrxMemoView(FindComponent('Memo1').Memo.<text or add or commatext> and each produced an error. By the way, I have 14 years experience in Delphi, so I am no rookie.Putnam
For example this post may give you a starting point on how to access report controls... (you need to search for the control on the report, not on the report's parent; instead of TComponent.FindComponent use TfrxReport.FindObject).Floorman
That did the trick. TfrxMemoView(frxReport1.FindObject('Memo4')).Memo.Text := 'Hello'; Thanks. If you want credit, submit your comments as an answer, okay.Putnam
Maybe you can have in-memory tables or even sql-servers to prepare data for the report?Stretcherbearer
@Arioch, having a database server to prepare system info, RS232 and USB device list along with some summary would be overkill. In-memory tables I've mentioned in my first comment...Floorman
@Floorman not server, just in-memory SQL, like in-memory tables but with SQL engine. Actually FireDAC seems to gonna have it, and BDE had, not mentioning NexusDB and SQLiteStretcherbearer
F
9

I've extended the option provided by @jrodenhi's answer, which seems to be the proper way to do what you want (thus I've made this answer a community wiki). So here are the two options you can use (and I think there will be more of them):

1. Define custom variables

The answer by @jrodenhi shows how to add report variables in code. I'll try to show here, how to define them in report designer.

  1. Open report designer
  2. Go to menu Report / Variables...
  3. In the Edit Variables window create a new category by clicking the Category button. Then you can rename the category the same way as you do e.g. for files in Windows Explorer: enter image description here

  4. Then you can declare a custom variable by clicking Variable button. You can give to the variable some meaningful name the same way as you do e.g. for files in Windows Explorer: enter image description here

  5. After this save your changes by clicking OK button: enter image description here

  6. Then you'll get back to the report designer, where you can find your just declared variables in the Data Tree pane tab Variables from where you can drag and drop the variables to the report: enter image description here

  7. After you refine all component positions and properties you can close the report designer and go back to the Delphi IDE. There you can write a handler for the OnGetValue event of your report and if its VarName parameter equals to your variable, change its Value parameter to the value you want to give to the associated report component:

procedure TForm1.frxReport1GetValue(const VarName: string; var Value: Variant);
begin
  if VarName = 'MyVariable' then
    Value := 'This is a new value!';
end;

2. Modify report components directly from Delphi code

There is an option of direct access to report components from your Delphi code. For instance, to find a certain report component by name you can use the FindObject method of the TfrxReport object. Then you can follow the usual pattern of checking if the returned reference is of type of the control you want to access and if so, you can access the instance by typecasting, as usually.

For example to find a TfrxMemoView object of name Memo1 on the frxReport1 report and modify its text you may write:

var
  Component: TfrxComponent;
begin
  Component := frxReport1.FindObject('Memo1');

  if Component is TfrxMemoView then
    TfrxMemoView(Component).Memo.Text := 'New text';
end;
Floorman answered 12/1, 2014 at 18:4 Comment(4)
Nice job! Worthy of inclusion in an unofficial FastReports user guide. Thanks for the tip on creating variables in the report designer.Picayune
Thanks! But I've learnt using variables from the other answer and I'd glad if you accept it.Floorman
I would accept your answer, but I guess the OP has to accept it. Maybe he will get a nudge in a day or two to revisit this question and accept an answer.Picayune
You saved my life mate, one of the greatest doc about VCL FR :)Antique
P
7

Most of the reports I write are for payroll. In addition to the table based data that makes up the bulk of the report, there is usually a significant amount of singular data, such as user and employer information that is frequently most easily entered as a series of variables taken from a filter dialog that runs before the report. Once the filter has run I iterate through all of its variables and add them to the report variables. Maybe you could pick up your singular system variables and do the same.

This is my routine that runs just before I prepare a report. It not only adds variables, it also adds functions defined in Delphi that can be used in the report:

procedure TFastReportDriver.SetVariables(sVariables: String; var frxReport: TfrxReport);
var i,
    iDetail: Integer;
    sl: TStringList;
    sVariable,
    sValue: String;
begin
  sl := TStringList.Create;
  sl.CommaText := sVariables;
  frxReport.Variables.Clear;
  frxReport.Variables[' Filter'] := Null;
  for i := 0 to sl.Count - 1 do begin
    sVariable := sl.Names[i];
    sValue := Qtd(sl.ValueFromIndex[i]);
    frxReport.Variables.AddVariable('Filter', sVariable, sValue);
  end;
  frxReport.AddFunction('procedure CreateCheck(hPaystub, iCheckNo: Integer)');
  frxReport.AddFunction('function NumberToWords(cAmount: Currency): String');
  frxReport.OnUserFunction := repChecksUserFunction;
  sl.Free;
end;

Then, in your code, you call frxReport.DesignReport and at run time you can drag and drop your variables onto your report: enter image description here

And, if you have defined any functions like above, they show up under the functions tab.

Picayune answered 12/1, 2014 at 18:37 Comment(6)
You say "drag and drop variable"; is there a way to specify component type for those variables ? I mean, can we explicitly select e.g. a barcode component for a certain variable (or vice-versa, bind a variable e.g. to a barcode component) ? [sorry for bothering, I don't have FR by hand at this moment :-)]Floorman
I have not used a barcode yet. Isn't there a component that produces a suitable barcode when you provide it with a suitable string? I have not tried this with pictures (such as a logo on a paycheck) yet. It works fine for strings, numbers and dates. The variables are all variants.Picayune
I couldn't find any way to explicitly choose (or later bind somehow) a component that you want to use for your variable. It seems it always uses TfrxMemoView component...Floorman
You can just use [myVariable] as the content of the TfrxBarCodeViewCogitate
@Floorman almost, I think FastReport uses square brackets [] instead of angle brackets <>Cogitate
@Gloegg, angle brackets offered me designer when I've used space in the variable name, so I've assumed it's proper there. Thanks for the info!Floorman
J
1

I've had success with this method:

  1. Use an in-memory table, such as TkbmMemTable, TdxMemTable or any in-memory table.

  2. Link the in-memory table to the TfrDataSet.

  3. Populate the in-memory table using usual TDataset methods and run the report.

Jolda answered 28/6, 2014 at 16:26 Comment(0)
J
0

You might want to take a look at using NexusDB as a way to hold data for the report. NexusDB is a database which besides being a full client server database can also run as a totaly in-memory database with full SQL support and no external dlls or anything required as it is compiled into your app. They have a free embedded version that will satisfy your needs. I use it for many things, it honestly a wonderful tool to have in your toolbox.

Jungle answered 6/5, 2014 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.