Tips_todo   >   Reports   >   Reports (All Contents)
.Writing and trying to control reports in Omnis Studio can be frustrating! In this section I give some tips on some stuff I've learned, but I've got a long ways to go.
ADVICE ON LEARNING REPORT WRITING IN STUDIO
When learning to use the report writer, as soon as I wanted to do anything out of the ordinary, I would spend hours upon hours getting lots of different results, rarely the result I wanted.
After wasting far too much time on trying on my own to understand and control reports I gave in and signed up for a training course with David Swain. If you have the opportunity get some training. David Swain has the best understanding of anyone I know on controlling the report writer. (Other than the engineers at Mitford House?)
One thing David said to me in the training session, "Don't complain about the report writer in Studio, instead work to understand it". Very true. The coding logic for the report writer in Studio is different than the coding you do in other areas of Studio. The reasons for this will become clearer as you work to understand the Report writer.
The report writer is complex. Just stop and think about all the different platforms, printers, page sizes, printer trays, etc. etc. that exist on the planet. Now give yourself the job of coming up with a report writer that will work for all of them. (Good Luck!)
Once you understand the report writer, like the rest of Omnis, you can do pretty well anything you want. Your imagination is the limit. (I have a LONG way to go before I reach that point in Studio
reports)
The report I'm proudest of is a labels report which can print sorted labels side to side or up and down on the label paper AND the user can specify which label to start on on the first page. (so we can use up the half finished page from the last run)
Good Luck learning report in Studio! Hang in there! Keep a positive attitude! Everytime something goes wrong, remind yourself, "This is an opportunity for me to learn something new." :-)
FOOTNOTE: What we need, is for someone to write a book on writing reports in Studio. (David Swain are you listening?) The book should be the thickness of the current Omnis Programming manual and include a tutorial on CD with loads of examples. I'd like to order my copy. Where can I place my order?Did you know that you can assign names to background objects in reports? Once you have done so, you can then assign methods (like $print, just to give a randon name...) to those background objects. Here's how:
In design mode, put lines for each background object you want to name in $construct like:
Calculate $cclass().$objs.1004.$name as 'extLine'
Calculate $cclass().$objs.1006.$name as 'otherLine'
Then print the report to the screen. (You don't even need data, just the attempt is enough!) The names for these objects will then appear in both the Property Manager and in the Method Editor.
You can then remove the naming code -- it has done its job.
Thank to David Swain for this tip. David remains the unchallenged "Omnis Reports Guru" champion. If you have a question about reports ... David's your man. Visit www.polymath-bus-sys.comDo you have horizontal lines in any of your reports? When you are moving or aligning fields in the report, the horizontal lines always seem to be getting in the way of the selection marquee.
In the training session with David Swain we were having an off topic discussion about the $sendall when a light bulb turned on inside my head. Why not make my horizontal lines 1" (25mm) long and place them way off past the right margin of the report? Then in the $construct of the report use a $sendall to position and stretch all lines across the full width of the report?
It worked like charm! I have the code in an object class (what else is new), therefore it uses "prReport" instead of $cinst. Here's the code. Feel free to copy it.It took me a long time to understand the 'Load page setup' logic for different reports and getting the report page setups to work properly between our Mac and Wintel computers. Tinkering with it myself for a day and then reading the explanation by Rudolf (see Load Page Setup Background) cleared a lot of things up.
I set out to create a 'Generic' Load Page Setup method in my application, so that I could ignore the margins, scale, copies, orientation, and leave the $pagesetupdata empty in all my reports. I would then allow the users to store their own Local Page Setups, and they or I could set whatever margins, scale, and in some cases orientation needed for different reports without the 'Prompt for page setup' every time a report had to be printed.
I also wanted to give the users the ability to set and edit a 'message' to print in the Page header of page 1 of the reports. Primarily to be used as a 'cc' line for printing the names or initials of people who should get copies of the report. There were a couple 'gotchas' I ran into.
GOTCHAS
________________
GENERIC METHOD FOR LOAD PAGE SETUP
Here's the logic of what I did in my application to work with Load Page Setup.
1. Create a separate library called PRINT.LBS and store it in a separate 'Setups' folder. This way when you release an update, the local page setups stored in PRINT.LBS won't get overwritten by the update.
2. In the PRINT.LBS create a default dummy report called 'rDefault' (would likely be USLetter or A4).
Click on the Page setup > pagesetupdata in the Property Manager and set the page settings as required. (Don't worry about scale, orientation, copies ... that can be set using notation) Create addition dummy reports as needed in your application. (ie. rUSLegal, for Canada/US).
3. In the Startup_Task.$construct of my main library, open PRINT.LBS, Set report name rDefault, Load page setup. Now your default page setup is localized to the platform/printer provided you've done so in design mode on the right platform(s) with the right printer(s).
4. Create a 'reports' table which will store the report instance name, page setup dummy report name, orientation, margins, scale, copies for each report which does not use the default settings. (And in my application the 'message' to print in the header of Page 1)
Insert 2 records: 'Default Portrait' & 'Default Landscape' which will be the system wide defaults for orientation, margin, scale, and copies for all standard Portrait and Landscape reports.
Add additional Report Instance records to this table for Report Instances which will use settings other than the Default Portrait or Default Landscape.
NOTE: I always declare a Report Instance name when printing any report, and print [$cinst().$name] at the top of the report. That way it is obvious to the user and the developer what report has been printed. (A single report class can be used to print many different report instances.)
5. Before printing a report instance, check if there is a matching report instance name in the 'reports' table, if so return the record row to the method. If the report instance name uses a different dummy report setup than rDefault, Set report name PRINT.rDefault, Begin reversible block, Load the Page Setup, End reversible block, then continue with Set report name REPORTNAME,
Print report {(REPORTINSTANCE, REPORTLIST, REPORTSETTINGSROW) ;; }
6. In the $construct of the report, using the REPORTSETTINGSROW passed to the report, notationally set the margins, $orientation, $scale, $copies (very little overhead involved in doing this)
7. If the default page setup was changed for this report, it will reverse back to the default after the report has been printed.
8. Leave the $pagesetupdata empty in all your reports. This saves on having to manually create and maintain a multitude of page setups for every single report that you create.
That's it.The following explanation on Report Page Setups was done by Rudolf Bargholz. Thanks to Rudolf for permission to include it in StudioTips.
Problem
-------
When reports to different printers one is often faced with the situation:
a) How is the printer set up?
b) What orientation is the report to be printed in?
c) How does one ensure that some reports will get sent to one printer, others to another, without
having to specify the printer each time?
Solution
--------
What is a page setup? Basically it is the settings a printer is to use when printing a document. See the screenshot
below for an example:
Screenshot of a Studio page setup dialog for a printer
As can be seen, all reports sent to this printer will be printed in Portrait, the paper size is A4, etc. Some printers allow one to change more settings, for example label printers.
There are numerous places where page setup information can be stored. Omnis can store a page setup in a report. One can also store and use a page setup defined by a specific printer. On windows platforms one has a Printer folder in which all the installed printers can be viewed. These printers each have their own printer/page setup. Omnis has a specific logic that allows one to mix and match these page setups with different reports, i.e. one can print reports based on the page setup stored in a report or use the settings defined under Windows. The logic Omnis uses is ...
1) when you start Omnis and print a report, the page setup of the default printer of that computer will automatically be loaded and used for printing all subsequent reports.
2) if you use the command 'Select printer', explicitly specifying the parameter 'Discard previous settings', Omnis will load the page setup of that specific printer, i.e. the settings entered under the properties of that printer in the Printer folder in Windows. This is a windows specific attribute.
Select printer (Discard previous settings) {HP LaserJet 5000 GN PCL 5e,FILE:}
will then use the printer properties I set up under Windows for this printer driver.
3) you can explicitly load the page setup of a report using the command 'load page setup'. Note that this page setup will be used in the printing of all reports until a new page setup is loaded or the page setup of a printer is loaded as described in 2) above. The code below uses the page setup of the report 'r1':
Set report name r1
Load page setup
Send to printer
Select printer {HP LaserJet 5000 GN PCL 5e,FILE:}
Print report
This concept of a page setup is important to understand. A report can store page setup information.
Set report name r1
Prompt for page setup
will open a dialog in which one can choose printer settings, e.g. the orientation of the paper, the printer to which the report is to be printed, etc. When one closes the dialog with Ok, the settings are stored in the report. When one then says
Set report name r1
Load page setup
one loads the printer settings of that report into memory. Every report one prints from now on will use the printer settings of the report 'r1'.
Set report name r1
Load page setup
Print report
Set report name r2
Print report
In this case both reports 'r1' and 'r2' will be printed using the page setup of the report 'r1'.
Let us look at the case where one has two printers. Some reports are to be printed to one printer, other reports to the other printer.
HP LaserJet 4
- Report1 (portrait)
- Report2 (landscape)
- Report3 (portrait)
- Report4 (landscape)
Zebra Label Printer
- Report5
- Report6
In this case one can do the following: define three new EMPTY reports. These reports are simply dummy reports that hold the page setup information for the specific printers.
The end user has to perform the following code ONCE:
Set report name MyLaserJet4DummyReport_Portrait
Prompt for page setup
Set report name MyLaserJet4DummyReport_Landscape
Prompt for page setup
Set report name MyLabelDummyReport
Prompt for page setup
Each time the customer saves the page setup for that specific printer WITH THE DUMMY REPORT. Now,
whenever I wish to print to the LaserJet 4 in Portrait the following code can be used:
Set report name MyLaserJet4DummyReport_Portrait
Load page setup
Set report name Report3
Print report
If I wish to print to the Label printer the following code can be used:
Set report name MyLabelDummyReport
Load page setup
Set report name Report5
Print report
Remember, that Omnis uses the page setup one has loaded for each report until one loads a new page setup of another report or loads the page setup information for a specific printer.
The following will fail:
Set report name MyLabelDummyReport
Load page setup
Set report name Report5
Print report
Set report name Report3
Print report
'Report3' is supposed to be printed to a LaserJet 4 in portrait mode; the code is telling Omnis to
print 'Report3' to the printer based on the printer settings stored in the report 'MyLabelDummyReport', the label printer, which is not correct. The code won't fail to function but it will print the report that was meant to go to the LaserJet to the Label printer; all the text in the report will get printed out one lots of little labels. To get the code to work correctly, it has to be edited:
Set report name MyLabelDummyReport
Load page setup
Set report name Report5
Print report
Set report name MyLaserJet4DummyReport_Portrait
Load page setup
Set report name Report3
Print report
The reports 'MyLabelDummyReport' and 'MyLaserJet4DummyReport_Portrait' are simply printer groups with predefined properties that can be loaded when needed for another report. It is important to remember that the printer name is stored with the page setup when one uses 'Prompt for page setup' and 'Load page setup'. It is because of this fact that one does not have to specify which printer one wants to print to when one loads a page setup of a report. Sometimes this can cause problems. The developer might not have the same printer as the customer. The report works fine at the developers, at the customer's site the report fails to print correctly. The reason for this is, that the page setup of the developer is used to print the report and the report tries to print to a non-existent printer. The customer must 'Prompt for page setup' once to set up the page setup of the report once with the settings of HIS printer. Note, that if the customer changes his printer or wants to print to another printer, he will have to 'Prompt for page setup' again.
Another situation can arise when an application is used in a large company that share a library but have many printers. Some people print a specific report to one printer, others print the same report to another printer. For each printer it is advisable to have one dummy report. One then has to adjust one's code in such a manner to account for this complexity in the organization. It might be advisable to store a list in the database, which user prints which report to which printer.
There are other really cool things one can do with Omnis reports in Omnis Studio. For example, we want the second page of a report to be landscape, the following to be portrait. In your page footer place the following code in the $print method:
Switch #P
Case 1
Calculate $cinst.$orientation as kOrientLandscape
Case 2
Calculate $cinst.$orientation as kOrientPortrait
End Switch
Do default
This will print the first page using your page setup, the second page explicitly in landscape, the following pages in portrait.
Another point to remember is the 'job setup' with which it is possible to determine the tray to which the first page is printed as well as the tray to which the other report pages are printed.
On evClick ;; Event Parameters - pRow( Itemreference )Need to print "Page x of y" on your report page headings? Where x=current page, and y=total pages in the report.
Omnis provides a great external object in the F3 Component Store that does this for you.
1. Open the report in design mode.
2. Press F3 to open the Component Store.
3. In the Component Store toolbar, click the "External Components" icon. (It looks like 2 lego blocks with 4 little arrows.)
4. Drag the "Page Count" (#) object from the Component Store into your report header.
5. Select the page count component. Press F6 Property Manager.
6. Set the various properties to suit your requirements. ($prefix, $maintext, $fieldstyle, etc.)
@BUG: When moving from Omnis v2x to v3x there was a bug with the page count component that caused Studio to crash if you tried to open the report to modify it. The work around was to $remove the page count component using notation, then readding the newer version page count external. Not elegant, but necessary to do. Hopefully, that doesn't happen in the future.You may notice a small slice of the report printout which appears to be getting cut off the right-hand side of that field. On the screen, it looks fine, but when it gets to the printer, it is missing the last character of some of the lines.
This is a problem which had been there for a long time - reports look different on the screen than actual print because of differences in the fonts used to display the fields.
There is a difference betweeen printing directly to the printer and displaying on the screen and then printing. A succesful solution to this exeption is to tell the users that if they want to see the report on the screen first, they will need to re-print it directly to the printer.Do you find that the page header on 80% of your reports contains the exact same information?
Do you find it redundant to have the same page header fields on 80% of your reports?
Have you found out that subclassed reports do not inherit fields from the superclass report?
There's a relatively easy solution for this. Leave the page header blank in all your reports that use a standard page header and add the Page Header fields and text to the report instance using notation. Omnis can add your standard page header fields to a report instance in the blink of an eye. The beauty of this is that if you need to make a change to the page header in 80% of your reports, you only have to change the $constructPageHeader method. Positioning, font sizes and styles will be 100% consistent in all the reports which call $constructPageHeader.
1. Create an object class called oReportTools.
2. Create a method called $constructPageHeader
3. Figure out the notation for adding your standard Page Header fields to a report.
4. In the $construct of your reports, call the $constructPageHeader, sending it $cinst
Test, debug it, and you're done! No more tinkering around with standard page header fields in reports.
Sample code for Standard Page Header is as follows:
$construct(rTemplateStd) ;; the $construct in the reportIf a printer has not been chosen, it causes a problem for reports. The problem occurs so infrequently that when it happens it often takes an hour to solve. To avoid this problem, always test for printer before running a report. (It only takes a nano second)
sys(101) ;; returns the current printer name, and network path (empty if not connected).