Working with graphicreport1
The Graphic Report is extremely flexible in its design. The actual report is separate from the physical representation of its output. The graphicreport1 type contains a graphicreport1form type, which in turn contains a dring of graphicreport1formpage objects. The graphicreport1 type also incorporates the report1 type and is therefore similar to working with report1 as discussed previously. Unlike the quickreport1 type, however, this type is considerably more powerful and therefore also considerably more complex. It uses the printform1 type to provide templates for each area of the report. Each band of the report is defined as a page in the graphicreport1form. See Chapter 24, Using Data-Aware Print Forms in SIMPOL for more information about printform1.
The Graphic Report is a banded report system. That means that the components are broken up into bands, each the width of the page. The bands that are provided include:
Page header
Page footer
Body
Report header
Report footer
Group header
Group footer
None, some or all of these bands may be used (the group bands are for each
group defined). When the report is run, it assembles the page from these bands. At the start
of the report it will output the report header if it has been defined and at the beginning
of each page it outputs the page header if that has been defined. Since it may be messy to
have both on the same page, there is an option to suppress output of the page header on the
first page. Following that, if there are any groups defined and there is a group header for
the group, that will be output, then the body section of the report will be output until a
group change, or the bottom of the page, (allowing for the page footer if it has been
defined). Each page is then assembled as required until the end of the report is reached, at
which point the report footer will be output followed by the page footer (this can also be
suppressed on the last page). Each band is defined as a graphicreport1formpage
that contains a printform1page object. Each of these pages has a specific
naming format so that the engine will recognize them. These are also stored as constants in
an includable SIMPOL source code file called graphicreporthdr.sma
, but the list is as follows:
"pageheader"
"pagefooter"
"body"
"reportheader"
"reportfooter"
"groupheader"
"groupfooter"
In turn, each page can contain any of the following content elements:
graphicreport1arc
graphicreport1ellipse
graphicreport1line
graphicreport1rectangle
graphicreport1triangle
graphicreport1formtext
graphicreport1formbitmap
Each of these contains a printform1 graphic or control of equivalent type. In the case of the graphics, there is little difference between them. The bitmap and text objects are different however, since they can be associated with a column value in the body page. In addition, the text objects can also be associated with an aggregate value in the group and report footers, or defined as a calculation using a system variable in the group header (for the GROUP items below), otherwise any of them can be used anywhere, though page headers and footers would be the most logical choice for most. The supported system variables include:
PAGE – (returns the page number in the report formatted using the minimum characters (pure
.tostr()
callTODAY – (returns the current date formatted using the default date format and date locale information as provided to the report
NOW – (returns the current time formatted using the default time format information as provided to the report
TIMESTAMP – (returns the current date and time formatted using the default datetime format and date locale information as provided to the report
COUNT – (returns either the count of rows in the report or the group, depending on the page)
GROUP – (returns the value of the current group)
GROUPNAME – (returns the name of the column for the current group)
GROUPINFO – (returns the name of the current group, followed by a colon and a space, and then the group's current value
Each item is placed on the page using print coordinates (to the nearest micrometer). Positioning is absolute, so if something is too close to an edge to be printed without being cropped, then it will be cropped.
When creating any of these controls, one of the arguments to each is an appropriate
printform1control or printform1graphic object. In the case of
the two form objects, they can each take a column number (which is based on the order of the
select clause), in the colno
parameter. Furthermore, the text control
can also be assigned an aggregate type, or instead of a column number it can have a
calculation assigned. Both of the form controls can also be assigned static values, a fixed
bitmap or text value. All of this is handled in the
graphicreport1form.addcontrol()
method.
The easiest way to understand how to use the report is to make one:
include "graphicreporthdr.sma" function main() integer e, erridx, stdtexthgt string s, errmsg sbme1 sbmfile sbme1table address graphicreport1 gr wxfont font, font2, font3, font4 report1group group dataform1datasource ds1 graphicreport1formpage page graphicreport1formtext ptxt SBLlocaledateinfo datelocale SBLNumSettings numlocale e = 0 sbmfile =@ sbme1.new("address.sbm", error=e) if sbmfile =@= .nul s = "Error number " + .tostr(e, 10) + " opening \ ""address.sbm""{d}{a}" else address =@ sbmfile.opentable("Address", \ recordidfieldname="recid_ro_internal", error=e) if address =@= .nul s = "Error number " + .tostr(e, 10) + " opening the \ ""Address"" table{d}{a}" else datelocale =@ SBLlocaledateinfo.new(format="dd/mm/yy") numlocale =@ SBLNumSettings.new("£", ",", ".", .false) stdtexthgt = 4900 errmsg = "" erridx = 0 font =@ wxfont.new("Arial Narrow", 10, "n", "n", "", error=e) font2 =@ wxfont.new("Arial Narrow", 10, "n", "b", "",error=e) font4 =@ wxfont.new("Arial Narrow", 13, "n", "b", "",error=e) font3 =@ wxfont.new("Arial", 14, "n", "b", "", error=e) gr =@ graphicreport1.new(paperwidth=210000, \ paperheight=297000, outputtarget=GR_OUTPUTWINDOW, \ title="Address List", datelocale=datelocale, \ numlocale=numlocale, error=e) gr.reportform.wrapkludgevalue = .toval("1.15", .nul, 10) gr.reportform.fontresizekludgevalue = .toval("0.7", .nul, 10) gr.reportform.wrapcharcountkludgevalue = .toval("1", .nul,10) gr.usewrapheight2 = .true gr.setselectclause("AddressID, FirstNames, Surname, City, \ CountryCode", errmsg, erridx) gr.setwhereclause("", errmsg, erridx) gr.setorderclause("City, Surname") ds1 =@ gr.adddatasource(sbmfile, "address.sbm", error=e) gr.addtable(address, ds1, error=e) // Body Page page =@ gr.addpage(210000, 600 + stdtexthgt, 0xffffff, \ name=sGR_BODY, error=e) gr.addcontrol(graphicreport1formtext, printleft=20000, \ printtop=300, printwidth=12000, \ printheight=stdtexthgt, printalignment="right,top", \ font=font, printname="tbAddressID", page=page, \ colno=1, error=e) gr.addcontrol(graphicreport1formtext, printleft=34000, \ printtop=300, printwidth=50000, \ printheight=stdtexthgt, font=font, \ printname="tbFirstNames", page=page, colno=2, error=e) gr.addcontrol(graphicreport1formtext, printleft=86000, \ printtop=300, printwidth=50000, \ printheight=stdtexthgt, font=font, \ printname="tbSurname", page=page, colno=3, error=e) gr.addcontrol(graphicreport1formtext, printleft=138000, \ printtop=300, printwidth=50000, \ printheight=stdtexthgt, font=font, \ printname="tbCity", page=page, colno=4, error=e) gr.addcontrol(graphicreport1formtext, printleft=190000, \ printtop=300, printwidth=12000, \ printheight=stdtexthgt, font=font, \ printname="tbCountryCode", page=page, colno=5, error=e) // Page Header page =@ gr.addpage(210000, 16320 + stdtexthgt, 0xffffff, \ name=sGR_PAGEHEADER, error=e) gr.addcontrol(graphicreport1formtext, printleft=50000, \ printtop=6000, printwidth=110000, printheight=8200, \ printalignment="", text="Address List", font=font3, \ printname="lPageTitle", page=page, error=e) gr.addcontrol(graphicreport1formtext, printleft=20000, \ printtop=16000, printwidth=12000, \ printheight=stdtexthgt, printalignment="right,top", \ text="Addr ID", font=font2, printname="lAddressID", \ page=page, error=e) gr.addcontrol(graphicreport1formtext, printleft=34000, \ printtop=16000, printwidth=50000, \ printheight=stdtexthgt, text="First Names", \ font=font2, printname="lFirstNames", page=page, \ error=e) gr.addcontrol(graphicreport1formtext, printleft=86000, \ printtop=16000, printwidth=50000, \ printheight=stdtexthgt, text="Surname", font=font2, \ printname="lSurname", page=page, error=e) gr.addcontrol(graphicreport1formtext, printleft=138000, \ printtop=16000, printwidth=50000, \ printheight=stdtexthgt, text="City", font=font2, \ printname="lCity", page=page, error=e) gr.addcontrol(graphicreport1formtext, printleft=190000, \ printtop=16000, printwidth=12000, \ printheight=stdtexthgt, text="Ctry", font=font2, \ printname="lCountryCode", page=page, error=e) gr.addgraphic(graphicreport1line, point.new(20000, \ 16300 + stdtexthgt), point.new(202000, 16300 + \ stdtexthgt), width=100, printname="lBorder", page=page, \ error=e) // Page Footer page =@ gr.addpage(210000, 9000 + STDTEXTHGT, 0xffffff, \ name=sGR_PAGEFOOTER, error=e) gr.addgraphic(graphicreport1line, point.new(20000, 1000), \ point.new(190000, 1000), width=100, \ printname="lBorderFooter", page=page, error=e) ptxt =@ gr.addcontrol(graphicreport1formtext, \ printleft=98000, printtop=3000, printwidth=14000, \ printheight=stdtexthgt, printalignment="", text="", \ font=font2, printname="lPageNo", page=page, error=e) if ptxt !@= .nul ptxt.calculation = "PAGE" end if group =@ gr.addgroup("City", 4, string, error=e) if group !@= .nul gr.addaggregate(group, GR_AGG_COUNT, .nul, integer,error=e) end if // Group Header page =@ gr.addpage(210000, 12000, 0xffffff, \ name=sGR_GROUPHEADER, group=group, error=e) if page !@= .nul ptxt =@ gr.addcontrol(graphicreport1formtext, \ printleft=20000, printtop=5000, printwidth=30000, \ printheight=integer.new(stdtexthgt * (135/100)), \ printalignment="left,top", text="", font=font4, \ printname="lGroupname", page=page, error=e) if ptxt !@= .nul ptxt.calculation = "GROUPINFO" end if end if // Group Footer page =@ gr.addpage(210000, 8500, 0xffffff, \ name=sGR_GROUPFOOTER, group=group, error=e) if page !@= .nul ptxt =@ gr.addcontrol(graphicreport1formtext, \ printleft=20000, printtop=2000, printwidth=30000, \ printheight=integer.new(stdtexthgt * (135/100)), \ printalignment="left,top", text="", font=font4, \ printname="lGroupcount", page=page, error=e) if ptxt !@= .nul ptxt.calculation = "COUNT entries" end if end if gr.addaggregate(.nul, GR_AGG_COUNT, .nul, integer, error=e) // savegraphicreport(gr, "addresslist.sxr", error=e) // gr =@ loadgraphicreport("addresslist.sxr", error=e, \\ // errortext=errmsg) gr.startat100percent = .true gr.centeroverdisplay = .true e = 0 gr.run(errmsg, erridx, error=e) if not (errmsg > "" or e != 0) wxprocess(20000000) s = "Success!{d}{a}" else if errmsg > "" s = errmsg + "{d}{a}" else s = "Error number " + .tostr(e, 10) + \ " running report{d}{a}" end if end if end if end if end function s
As can be seen from the preceding code, there is a lot more involved in
creating a Graphic Report than there is for a Quick Report, but the difference is in the
amount of control over the resulting look of the report. Just as with the Quick Report, the
initial stages of creating a Graphic Report consists of opening the data source(s) and
table(s), creating the graphicreport1 object, and setting the select, where,
and order clauses. In addition, the fonts that will be used are created, and there is a set
of properties that are related to the "wrap" functionality that can be set. These
occasionally need tweaking to get the best results. Like with the Quick Report, only add the
"wrap" capability if it is required, since it adds considerable processing
overhead to each time a control that uses it is output. Two of the arguments passed to the
new()
method of the graphicreport1 are the
pagewidth
and the pageheight
parameters. The
ones used in the example are for A4 paper. The US Letter paper size is: 215900 x 279400.
Once the standard tasks have been dealt with, the various page bands are added, each with the controls that are required. Interestingly, just because a column is in the select statement does not mean that it will appear in the report. Unless it is associated with a control in the body page, there will no output for that column. This is useful when it is necessary to retrieve extra column information for use in report or group footers. Also, to do a summarization, it is only necessary to not define the body page.
If the level of control that is available in the basic design is still not enough, at the point of outputting a page chunk onto the final output page, there is an onoutput event for each page that can be used to call the programmer's code. A different function should be assigned for each unique band or graphicreport1formpage object. The various function prototypes for the types of pages are as follows.
Band Type | Function Prototype | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Body band |
graphicreport1formpage page ;printform1page pagechunk ;report1 report ;report1inst reportinst ;array columns ;array currcolvalues ;type(*) reference ; | |||||||||||||||||||||
Page header and footer, report header and footer |
graphicreport1formpage page ;printform1page pagechunk ;report1 report ;report1inst reportinst ;type(*) reference ; | |||||||||||||||||||||
Group header and footer |
graphicreport1formpage page ;printform1page pagechunk ;report1group group ;report1groupinst groupinst ;type(*) reference ; |
At the point where this is called, all of the data and calculations have been done,
and the resulting output can still be manipulated by the programmer. For example, in the
body, if the total of a row is negative, the foreground color could be changed to red. This
change only affects the current output chunk, not the template, so it needn't be reversed
for rows that are positive. The names of the controls on the pagechunk will be the same as
on the template, making it easy to address thae various controls. As was the case with the
Quick Report example, there are two commented lines of code that save and then load the
Graphic Report. The default file extension for SIMPOL Graphic Reports is .sxr
.