Tips   >   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.
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.
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 Omnis Studio is different than the coding you do in other areas of Omnis 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 Studio, you can do pretty well anything you want. Your imagination is the limit. I have a LONG ways to go before I reach that point in Omnis 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 reports in OMST! Hang in there! Keep a positive attitude! Everytime something goes wrong, remind yourself, "This is an opportunity for me to learn something new." :-)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 the class methods $construct like:
; Assign names the the report background objects
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. If you have a question about reports... David's your man. Visit www.polymath-bus-sys.comIf you want to generically print a company's logo a consistent height, centred at the top of each report, the trouble you run into is that the image size, and the image width by height ratio will be different for each company. Some companies might insert a very large image of their logo, others a much smaller image. Some company logos might be square, others rectangular.
In order print each company's logo a consistent height, centred at the top of each report, you will need to dynamically set the picture field size and position in the report header.
The following sample code demonstrates:
Load the JEG file
; Get the logo image.
Do pths.$:DemosFolderPath() Returns DemosFolderPath
If len(DemosFolderPath)
Calculate FolderPath as con(DemosFolderPath,sys(9),'logos')
Calculate FilePath as con(FolderPath,sys(9),'VencorLogo.jpg')
Do FileOpsExt.$openfile(FilePath,bReadonly)
Do FileOpsExt.$readfile(iLogoBinVar)
Do FileOpsExt.$closefile()
Calculate FlagOK as kTrue
End If
Quit method FlagOK
Convert the JPEG binary to CS24 Picture binary
; Find out the format of the image.
Calculate Format as pictformat(iLogoBinVar)
; Make sure it is a type we can convert.
Calculate TypesList as pictconvtypes()
If not(TypesList.$search($ref.C1=Format,1,0,0,0))
; Log an error.
OK message (Icon,Sound bell) {Unable to convert a '[Format]' format image for printing on the report.}
Breakpoint
Else
; Convert the image to a CS24 picture that can be displayed by the kPicture fields.
Do pictconvto(Format,iLogoBinVar,'CS24') Returns iLogPictVar
Calculate FlagOK as kTrue
End If
Quit method FlagOK
Size and center the picture field on the report.
; Find the width and height of the picture. (In pixels?)
Do pictsize(iLogPictVar,PictWidth,PictHeight)
; Size the width of the picture field in correct ratio to the image and the field height.
Calculate FieldHeight as irLogoField.$height
Calculate FieldWidth as FieldHeight/PictHeight*PictWidth
Do irLogoField.$width.$assign(FieldWidth)
; Centre the logo on the report.
If $cinst.$orientation=kOrientLandscape
Calculate PrintWidth as ($cinst.$paperlength-$cinst.$leftmargin-$cinst.$rightmargin)*100/$cinst.$scale
Else
Calculate PrintWidth as ($cinst.$paperwidth-$cinst.$leftmargin-$cinst.$rightmargin)*100/$cinst.$scale
End If
Do irLogoField.$left.$assign((PrintWidth-irLogoField.$width)/2)
Quit method kTrue
If you want a fixed height for your report's record section you set the $printheight property of the kRecord section divider on the report.
This works fine if you don't have any kPosition dividers inside the kRecord section. As soon as you add a kPosition divider in the record section the $printheight property is ignored. (Working with Omnis Studio 4.2.0.6 - I reported this problem to Tech Support)
The work around is to add a kPosition section at the end of the record section and set it to start at a position that puts it at the bottom of the record section.
Each kPosition section is cumulative from the previous section object. In my situation I needed a print height of 3.5.
The end kPosition was set to 1.250 from top of previous section for a total of height of 3.5
The response I got from Tech Support was as follows: It must be noted that Positioning sections also have a $printheight equal to 3.5 inches in this case.
property, so you need to make the sum of the positioning sections and record sectionDo 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.
A trick I use is in design mode to create 1 cm (1/2") long horizontal lines and place them in the correct line of the report but off the right side of the page. In the $construct of the report I then use $sendall to position and stretch the horizontal lines across the full width of the report.
; setHorzLines (method called by $construct)
; Position and stretch $objtype=kLine which are off the right side
; of the report to the full width of the page.
; This allows the lines to be 1 cm long and off the right side in design mode)
; If the report is reduced or enlarged, we have to adjust the line length proportionally
If $cinst.$orientation=kOrientPortrait
Calculate Width as ($cinst.$paperwidth-$cinst.$leftmargin-$cinst.$rightmargin)*100/$cinst.$scale
Else
Calculate Width as ($cinst.$paperlength-$cinst.$leftmargin-$cinst.$rightmargin)*100/$cinst.$scale
End If
Do $cinst.$objs.$sendall($ref.$width.$assign(Width),$ref.$objtype=kLine&$ref.$left>Width)
; Slide the lines over to the left margin.
Do $cinst.$objs.$sendall($ref.$left.$assign(0),$ref.$objtype=kLine&$ref.$left>Width)
Quit method kTrue
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 Studio provides a great external object in the
that does this for you.To generate subtotals for a column in a report you must set include the column in the $sorts group of the report and set the $subtotal property to kTrue.
To do this in a report class:
You can access the subtotal value of any field in the subtotal section using the notation iList.ColName.$total (or $average, $maximum, $minimum, $count)
Click the button in the window to test a report class which has subtotals.By default I send reports to the screen so that the user has an opportunity to review the report before deciding whether or not to print the report.
Issuing the Send to screen command causes all reports that follow to be sent to the screen. In my applicaitons I normally issue a Send to screen command somewhere during the $construct of the application's Startup_Task.
If somewhere in the application I have a report which is to be sent directly to the printer, I'll put the Send to printer command in a reversible block.
Begin reversible block
Send to printer
End reversible block
The Send to screen command has several parameters
Click the Send to screen test code.
button in the window to test the followingSet report name rScreenReportSize
Send to screen (Do not wait for user) No Size Parameters
Print report
Send to screen (Do not wait for user) Instance A /25/50/800/600
Print report
Send to screen (Do not wait for user,Hide until complete) Instance B /50/75/800/600
Print report
Quit method kTrue
There are two different ways you can control the title which appears in screen reports.
Set report name rScreenReportSize
Send to screen (Do not wait for user) Report Title/25/50/800/600
Print report
Quit method kTrue
Do $prefs.$windowprefs.$assign('Notation Report Title /25/50/800/600')
If 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)
@SAMPLECODE:1Ask yourself the following questions:
There is 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 each report instance using notation. Omnis Studio can add your standard page header fields to a report instance in the blink of an eye! The beauty of adding report page header fields on-the-fly is that if you want to make a change to the page header in your standard reports, you only have to change the code in one place and presto, all of your standard reports will immediately reflect the change.
As with anything in Omnis Studio there are many ways to accomplish the above. For this solution we are going to structure the code as follows:
The sequence of event for this solution is as follows:
To make it easy for you to edit the fields for your standard page header we will create a page header template report class.
The report tools object class contains the code which adds the template fields to the report instance.
; $constructPageHeader (method)
; Figure out the page report width.
If pfrReportInst.$orientation=kOrientPortrait
Calculate Width as (pfrReportInst.$paperwidth-pfrReportInst.$leftmargin-pfrReportInst.$rightmargin)*100/pfrReportInst.$scale
Else
Calculate Width as (pfrReportInst.$paperlength-pfrReportInst.$leftmargin-pfrReportInst.$rightmargin)*100/pfrReportInst.$scale
End If
; Find the page header template report class.
Do $clib.$classes.$findname('rPageHeader_template') Returns irTemplateRpt
If irTemplateRpt
; Print Info
Calculate FieldName as 'PrintInfo'
Do method addTemplateField (pfrReportInst,FieldName) Returns rField
If not(isnull(rField))
Do rField.$left.$assign(0)
; Page Count
Calculate FieldName as 'PageCount'
Do method addTemplateField (pfrReportInst,FieldName) Returns rField
If not(isnull(rField))
Do rField.$left.$assign(Width-rField.$width)
; Company Name
Calculate FieldName as 'CompanyName'
Do method addTemplateField (pfrReportInst,FieldName) Returns rField
If not(isnull(rField))
Do rField.$left.$assign(0)
Do rField.$width.$assign(Width)
; Title
Calculate FieldName as 'Title'
Do method addTemplateField (pfrReportInst,FieldName) Returns rField
If not(isnull(rField))
Do rField.$left.$assign(0)
Do rField.$width.$assign(Width)
; SubTitle
Calculate FieldName as 'SubTitle'
Do method addTemplateField (pfrReportInst,FieldName) Returns rField
If not(isnull(rField))
Do rField.$left.$assign(0)
Do rField.$width.$assign(Width)
; Page header notes
Calculate FieldName as 'PageHeaderNotes'
Do method addTemplateField (pfrReportInst,FieldName) Returns rField
If not(isnull(rField))
Do rField.$left.$assign(0)
Do rField.$width.$assign(Width)
Calculate FlagOK as kTrue
End If
End If
End If
End If
End If
End If
End If
Quit method FlagOK
; addTemplateField (private method)
If len(pLineMarkerName_opt)=0
Calculate pLineMarkerName_opt as con(pFieldName,'_linemarker')
End If
; Find the linemarker
Do pfrReportInst.$objs.$findname(pLineMarkerName_opt) Returns rMarker
If rMarker
; Find the template object.
Do irTemplateRpt.$objs.$findname(pFieldName) Returns rSourceField
If rSourceField
; Add the field to the report.
; $add(type[,cComponentLibrary,cComponentControl],iTop,iLeft,iHeight,iWidth) inserts a new object and returns an item reference to it
If rSourceField.$objtype=kComponent
Calculate Lib as rSourceField.$componentlib
Calculate Control as rSourceField.$componentctrl
Do pfrReportInst.$objs.$add(kComponent,Lib,Control) Returns rField
If rField
Do rField.$name.$assign(rSourceField.$name)
Do rField.$fieldstyle.$assign(rSourceField.$fieldstyle)
Do rField.$lineno.$assign(rMarker.$lineno)
Do rField.$left.$assign(rSourceField.$left)
Do rField.$width.$assign(rSourceField.$width)
Do rField.$height.$assign(rSourceField.$height)
Do rField.$align.$assign(rSourceField.$height)
End If
Else
Do pfrReportInst.$objs.$add(kEntry) Returns rField
If rField
; Copy all of the source field attributes to the target added field.
Calculate rField as rSourceField
Do rField.$fieldstyle.$assign(rSourceField.$fieldstyle)
Do rField.$lineno.$assign(rMarker.$lineno)
End If
End If
End If
End If
Quit method rField
Click the oReportTools report class. Free free to copy the object class from StudioTips to your library.
button in the to see theThe oReportTools object class in StudioTips includes a $setHorzLines method which can be called to dynamically position and stretch the horizontal lines across the report paper width.
Each standard report class will need to include the page header lines and appropriate linemarker fields for each standard page header field you want to include in the report page header.
; Construct the standard page header.
Do ioReportTools.$constructPageHeader($cinst) Returns FlagOK