Вы находитесь на странице: 1из 16

Personalized Reporting with Oracle Developer

Release 6i
An Oracle Technical White Paper

April 2000
Personalized Reporting with Oracle Developer
Release 6i

INTRODUCTION
One of the powerful new features in Oracle Developer Release 6i is the ability to change the appearance and
content of a report at runtime. This feature empowers end users by letting them choose how a report will
look when they run it. It also makes it possible for report developers to create a single report definition file
(.RDF file) that serves multiple audiences. For example, you could build a report that, based upon user input,
could fetch and format additional data, and alter the formatting characteristics of all of the data.
In Release 6i, Oracle Developer can merge report definitions built from XML tags with existing .RDF files at
runtime and then execute the combination of the two.1 Thus, you can personalize a report by allowing users
to choose which XML report definitions to apply to the base .RDF file at runtime.

1
It should be noted here that you can also use XML report definitions for other things as well. For example, you can
build a complete report definition in XML that can be run by itself, without an existing .RDF file. Another possible
usage is to make batch modifications using XML report definitions with RWCON60.

Personalized Reporting with Reports Developer Release 6i 1


April 2000
When to use this feature
The Oracle Developer personalization feature is most useful in the following situations:
• You are a report developer who wants to allow your users to make numerous, minor personalizations
(e.g., hiding columns, changing labels, and changing format masks) to a report, but you do not want to
have to create a different report for each of these small personalizations. In this case, the personalization
feature lets you minimize the number of reports you must build and distribute to your users. You build a
single report and apply different XML report definitions based upon user input to make the appropriate
changes at runtime.
• You are a report developer who provides a suite of reports to a number of sites and you want to enable
each site to make their own customizations to the reports. In this case, you can ship base reports and
then build XML report definitions for each site that are applied to the base reports at runtime. This is
particularly advantageous when you later need to update and redistribute the base reports. The various
sites can replace the base reports without having to lose their customizations because their
customizations exist outside the base reports in XML.
• You are a report developer who wants to make updates to a large number of reports at once. By coding
the changes in XML, you can apply them to any number of reports in a batch operation.
• You are a programmer who wants to link to reports using XML like a programming interface.

Note: The XML for the personalization feature can be coded by the report developer and stored in files or
generated from some meta data source (e.g., a database). In all cases, the XML should be built by the report
developer, not the end user.

BUILDING A PERSONALIZED REPORT—AN OVERVIEW


If you are building a complex, personalized report with many options for your users, you should code the
XML report personalizations in PL/SQL. In PL/SQL, you can conditionally control which personalizations to
apply to the base report, depending upon parameter values in the Runtime Parameter Form. This method
allows each user to choose their desired personalizations in the Runtime Parameter Form and, based on their
choices, the report will dynamically create and apply the necessary XML. The steps below provide an
overview of how to build this type of personalized report:
1. Based on feedback from your users, determine which aspects of your report you want to enable users to
personalize at runtime. Bear in mind that, in Release 6i, the main functionality is adding data and
formatting it, and modifying formatting characteristics.
2. Build a base .RDF file in Report Builder. The base report should contain those elements that you expect all
users to want to see in some form (i.e., if there is some data that not all users will need or want to see,
you should exclude that and add it through a personalization choice).
3. Create parameters that will enable a user to choose their desired personalizations. In some cases, the
parameter values will be yes or no (e.g., yes, add this data, or no, do not add this data). In other cases,
the parameter values will be a list of several choices (e.g., highlight values greater than the specified
value).
4. In the After Parameter Form trigger, use the SRW.ADD_DEFINITION and SRW.APPLY_DEFINITION
built-ins to conditionally create the necessary personalizations.
5. Test and debug the report to ensure that all personalizations work as expected.
6. Publish the report to your users.

Personalized Reporting with Reports Developer Release 6i 2


April 2000
PLANNING THE PERSONALIZATIONS
Before you begin building your report, you first need to understand what characteristics your users want to
be able to personalize at runtime. For the purposes of this white paper, let's suppose that you are building a
report that shows video sales data for a chain of stores by city, state, and quarter. Furthermore, you have
received the following feedback:
• Users at the corporate headquarters have told you that they want to see a summary at the beginning of
the report that rolls up the data for all of the cities, states, and quarters. They also want to be able to drill
down from this summary to the more detailed information.
• Regional employees have told you that they find a summary too distracting because they want to focus
solely on the more detailed data pertaining to the cities in their regions.
• Both regional and corporate users have told you that they want to be able to highlight values based upon
conditions that they enter at runtime and change the format mask for dollar values.

CREATING THE BASE REPORT


Given that not all of your users want to see the summary section, your base report should look something like
the following:

The personalizations that you need to enable for this base report are:
• Adding a summary to the beginning of the report that contains hyperlinks to the more detailed sections
of the base report.

Personalized Reporting with Reports Developer Release 6i 3


April 2000
• Choosing the formatting for monetary values.

• Highlighting values above a specified amount.

CREATING PARAMETERS AND THE PARAMETER FORM


Given the personalizations that you want to create, you need the following parameters:
• SHOW_SUMMARY is a parameter with Yes or No as its possible values. If this parameter is set to Yes,
the data model and layout for the summary section is added to the report.
• MONEY_FORMAT is the format mask to apply to monetary values in the report.

• HILITE_COSTS, HILITE_PROFITS, and HILITE_SALES are the values above which data should be
highlighted.
• WRITE_TO_FILE is a parameter with Yes or No as its possible values. If this parameter is set to Yes,
the XML used to personalize the report is written to a file. The files generated in this way can be a
valuable testing tool to ensure that the XML is being created properly.
The Runtime Parameter Form for this report would look something like the following:

Personalized Reporting with Reports Developer Release 6i 4


April 2000
CREATING THE AFTER PARAMETER FORM TRIGGER
Once you have defined the parameters and parameter form, you can begin to build up the personalizations in
the After Parameter Form trigger of the report. There are two methods that you can use for building
personalizations in PL/SQL:
• Build the personalization in the document buffer (i.e., memory) using SRW.ADD_DEFINITION and
then apply it using SRW.APPLY_DEFINITION. This method is useful because it does not rely on an
XML file in the file system. It requires no file input/output in order to work.
• Build the personalization in a file using the Text_IO package and then apply the file using
SRW.APPLY_DEFINITION. This method is useful for debugging purposes because you can more
easily identify problems in the XML.
For the purposes of this report, you will combine these two methods and give the user the option at runtime
to write the personalizations to files.

Setting up file variables and opening files for writing.


Since you plan to write the personalizations to a file, you need to begin your PL/SQL function by declaring the
necessary Text_IO variables. For the sake of clarity, each of the personalizations will be written to its own
file. Therefore, you need one Text_IO variable for each of your planned personalizations.
custom_summary Text_IO.File_Type;
custom_mask Text_IO.File_Type;
custom_hilite_costs Text_IO.File_Type;
custom_hilite_sales Text_IO.File_Type;
custom_hilite_profits Text_IO.File_Type;

Tip: To control the location of the personalization files, you could also declare a variable in which to place the
desired path information.
ora_dir_var VARCHAR2(20);

Before you begin adding lines to the personalization file, you need to check whether the user wants the
personalizations to be written to a file and, if they do, open it for writing.
Tool_Env.Getvar('ORACLE_HOME', ora_dir_var);
:file_directory := ora_dir_var || '\';
IF :WRITE_TO_FILE='Yes' THEN
custom_summary := Text_IO.Fopen(:file_directory ||
'vid_summ_per.xml','w');
END IF;

Whenever you need to write a line, you call the AddaLine procedure as follows:
AddaLine('<report name="video_custom" author="Generated"
DTDVersion="1.0">', custom_summary);

The AddaLine procedure will be described in the following section.

Adding lines to the personalization


After you have declared the necessary variables and, if necessary, opened a file for writing them, you can
begin to add lines to your personalization. In this case, you want to write the lines to the document buffer
and, optionally, to a file. To simplify the process of writing lines to both places, it makes sense to create a

Personalized Reporting with Reports Developer Release 6i 5


April 2000
procedure. The following procedure takes two arguments and writes the input line of XML to both the
document buffer and a file, if the user has requested to write the XML to a file.
PROCEDURE AddaLine (newline VARCHAR, outfile Text_IO.File_Type) IS
BEGIN
SRW.ADD_DEFINITION(newline);
IF :WRITE_TO_FILE='Yes' THEN
Text_IO.Put_Line(outfile, newline);
END IF;
END;

Building the data model for the summary section


Now that you have the AddaLine procedure, you can use it to build up the personalizations based upon the
user's input at runtime. The PL/SQL that follows builds up the data model of the summary section of the
report, if the user has requested that the summary personalization be added to the base report. First check to
see if the user wants to see and executive summary. If so, add the summary to the base report.
IF :SHOW_SUMMARY='Yes' THEN
AddaLine(' <data>', custom_summary);
AddaLine(' <dataSource name="Q_1">', custom_summary);
AddaLine(' <select>', custom_summary);
AddaLine(' SELECT ALL VIDEO_CATEGORY_BY_QTR.QUARTER quarter1,
VIDEO_CATEGORY_BY_QTR.CITY city1, ',custom_summary);
AddaLine(' VIDEO_CATEGORY_BY_QTR.PRODUCT_CATEGORY
product_category1, VIDEO_CATEGORY_BY_QTR.TOTAL_PROFIT
total_profit1,',custom_summary);
AddaLine(' VIDEO_CATEGORY_BY_QTR.TOTAL_SALES total_sales1,
VIDEO_CATEGORY_BY_QTR.TOTAL_COST total_cost1',custom_summary);
AddaLine(' FROM VIDEO_CATEGORY_BY_QTR',custom_summary);
AddaLine(' WHERE
VIDEO_CATEGORY_BY_QTR.SALES_REGION=''West''',custom_summary);
AddaLine(' </select> ',custom_summary);
AddaLine(' </dataSource>',custom_summary);

Note the only name and source are specified for the summary data when writing the output. It is best to let
the defaulting mechanism within Reports choose any additional values for the summary data (such as reset)
based on the location of the fields in the report layout.
AddaLine(' <summary name="SumTOTAL_SALESPerCITY1"
source="total_sales1"/> ', custom_summary);
AddaLine(' <summary name="SumTOTAL_COSTPerCITY1"
source="total_cost1"/> ', custom_summary);
AddaLine(' <summary name="SumTOTAL_PROFITPerCITY1"
source="total_profit1"/> ', custom_summary);

This last line is a counter which is used to alternate the shading of the records. This shading occurs in the
F_shadingFormatTrigger which is shown later in this paper. This counter does not appear in the report
output.
AddaLine(' <summary name="CS_Count1" source="city1" function="count"
reset="Report"/>', custom_summary);
AddaLine(' </data> ', custom_summary);

Personalized Reporting with Reports Developer Release 6i 6


April 2000
Building the layout for the summary section
Once you have built up the data model, you need to create a layout for the data. The following PL/SQL adds
the necessary layout objects and defines their hierarchy. The layout for the report is group above and a
template (video_custom.tdf) is specified. Note that this code is also contained inside the IF condition above
and will only be added if the user has requested the summary.
AddaLine(' <layout>', custom_summary);
AddaLine(' <section name="header">', custom_summary);
AddaLine(' <groupAbove name="M_video_sales_summary"
template="video_custom.tdf">', custom_summary);
AddaLine(' <group>', custom_summary);
AddaLine(' <field name="f_quarter1" source="quarter1"
label="Quarter:" ', custom_summary);
AddaLine(' font="Arial" fontSize="9"
fillColor="#6699CC"', custom_summary);
AddaLine(' textColor="white" alignment="center"',
custom_summary);
AddaLine(' formatTrigger="F_quarter1FormatTrigger">',
custom_summary);
AddaLine(' <labelAttribute font="Arial" fontSize="10"
fillColor="#6699CC"', custom_summary);
AddaLine(' textColor="white"
alignment="center"/>', custom_summary);
AddaLine(' </field>', custom_summary);
AddaLine(' </group>', custom_summary);
AddaLine(' <group>', custom_summary);
AddaLine(' <field name="f_city1" source="city1" label="City" ',
custom_summary);
AddaLine(' font="Arial" fontSize="9"', custom_summary);
AddaLine(' formatTrigger="F_city1FormatTrigger">',
custom_summary);
AddaLine(' <labelAttribute font="Arial" fontSize="10"
textColor="white"/>', custom_summary);
AddaLine(' </field>', custom_summary);
AddaLine(' <field name="f_SumTOTAL_SALESPerCITY1"
source="SumTOTAL_SALESPerCITY1"', custom_summary);
AddaLine(' label="Sales" font="Arial" fontSize="9"
alignment="right"', custom_summary);
AddaLine(' formatTrigger="F_shadingFormatTrigger"',
custom_summary);

The format for the monetary values parameter is interrogated and the correct format mask applied based on
the user selection.

IF :MONEY_FORMAT='$NNNN' THEN
AddaLine(' formatMask="LNNNNNNNNNNN0">',
custom_summary);
ELSIF :MONEY_FORMAT='$NNNN.00' THEN
AddaLine(' formatMask="LNNNNNNNNNNN0D00">',
custom_summary);
ELSE
AddaLine(' formatMask="LNNNGNNNGNNNGNN0D00">',
custom_summary);
END IF;

Personalized Reporting with Reports Developer Release 6i 7


April 2000
AddaLine(' <labelAttribute font="Arial" fontSize="10"
textColor="white"', custom_summary);
AddaLine(' alignment="right"/>',
custom_summary);
AddaLine(' </field>', custom_summary);
AddaLine(' <field name="f_SumTOTAL_COSTPerCITY1"
source="SumTOTAL_COSTPerCITY1"', custom_summary);
AddaLine(' label="Costs" font="Arial" fontSize="9"
alignment="right"', custom_summary);
AddaLine(' formatTrigger="F_shadingFormatTrigger"',
custom_summary);
IF :MONEY_FORMAT='$NNNN' THEN
AddaLine(' formatMask="LNNNNNNNNNNN0">',
custom_summary);
ELSIF :MONEY_FORMAT='$NNNN.00' THEN
AddaLine(' formatMask="LNNNNNNNNNNN0D00">',
custom_summary);
ELSE
AddaLine(' formatMask="LNNNGNNNGNNNGNN0D00">',
custom_summary);
END IF;
AddaLine(' <labelAttribute font="Arial" fontSize="10"
textColor="white"', custom_summary);
AddaLine(' alignment="right"/>',
custom_summary);
AddaLine(' </field>', custom_summary);
AddaLine(' <field name="f_SumTOTAL_PROFITPerCITY1"
source="SumTOTAL_PROFITPerCITY1"', custom_summary);
AddaLine(' label="Profits" font="Arial" fontSize="9"
alignment="right"', custom_summary);
AddaLine(' formatTrigger="F_shadingFormatTrigger"',
custom_summary);
IF :MONEY_FORMAT='$NNNN' THEN
AddaLine(' formatMask="LNNNNNNNNNNN0">',
custom_summary);
ELSIF :MONEY_FORMAT='$NNNN.00' THEN
AddaLine(' formatMask="LNNNNNNNNNNN0D00">',
custom_summary);
ELSE
AddaLine(' formatMask="LNNNGNNNGNNNGNN0D00">',
custom_summary);
END IF;
AddaLine(' <labelAttribute font="Arial" fontSize="10"
textColor="white"', custom_summary);
AddaLine(' alignment="right"/>',
custom_summary);
AddaLine(' </field>', custom_summary);

The following field definition is for the CS_Count1 summary. The F_CS_Count1FormatTrigger is used to
hide this field from the report output.
AddaLine(' <field name="f_CS_Count1" source="CS_Count1"',
custom_summary);
AddaLine(' label="" font="Arial" fontSize="9"',
custom_summary);
AddaLine(' formatTrigger="F_CS_Count1FormatTrigger">',
custom_summary);

Personalized Reporting with Reports Developer Release 6i 8


April 2000
AddaLine(' <labelAttribute font="Arial" fontSize="10"
textColor="#6699CC"/>', custom_summary);
AddaLine(' </field>', custom_summary);
AddaLine(' </group> ', custom_summary);
AddaLine(' </groupAbove>', custom_summary);
AddaLine(' </section>', custom_summary);
AddaLine(' </layout>', custom_summary);

Building program units for the summary section


In order to create hyperlinks and shade alternating rows in the summary, you need to create some program
units within the report. The program units are referenced from the format triggers of the layout objects. The
F_quarter1FormatTrigger adds a hyperlink to the field F_quarter1. This hyperlink is used to drill down for
more detailed information for the quarter. The use of the bind variable (:quarter1) gives each quarter a unique
target. The SRW.LINKTAG in the format trigger for the field named F_quarter in the main section of the
report defines the target for this link.
Note: the use of <![CDATA[]]> tag is used to prevent the XML parser from parsing this PL/SQL as though it
were XML.
AddaLine(' <programUnits> ', custom_summary);
AddaLine(' <function name="F_quarter1FormatTrigger"> ',
custom_summary);
AddaLine(' <![CDATA[', custom_summary);
AddaLine(' function F_quarter1FormatTrigger return boolean is',
custom_summary);
AddaLine(' begin', custom_summary);
AddaLine(' SRW.SET_HYPERLINK(''#QUARTER_DETAILS_&<'' ||
LTRIM(:quarter1) || ''>'');', custom_summary);
AddaLine(' return (TRUE);', custom_summary);
AddaLine(' end;', custom_summary);
AddaLine(' ]]>', custom_summary);
AddaLine(' </function> ', custom_summary);
AddaLine(' <function name="F_city1FormatTrigger"> ',
custom_summary);
AddaLine(' <![CDATA[', custom_summary);
AddaLine(' function F_city1FormatTrigger return boolean is',
custom_summary);
AddaLine(' begin', custom_summary);
AddaLine(' SRW.SET_HYPERLINK(''#QTR_CITY_DETAILS_&<'' ||
LTRIM(:quarter1) || LTRIM(:city1) || ''>'');', custom_summary);
AddaLine(' if (:CS_Count1 mod 2 = ''1'') then',
custom_summary);
AddaLine(' srw.set_foreground_fill_color(''lightgrey'');',
custom_summary);
AddaLine(' srw.set_fill_pattern(''solid'');',
custom_summary);
AddaLine(' end if;', custom_summary);
AddaLine(' return (TRUE);', custom_summary);
AddaLine(' end;', custom_summary);
AddaLine(' ]]>', custom_summary);
AddaLine(' </function>', custom_summary);
AddaLine(' <function name="F_shadingFormatTrigger">',
custom_summary);
AddaLine(' <![CDATA[', custom_summary);
AddaLine(' function F_shadingFormatTrigger return boolean is',

Personalized Reporting with Reports Developer Release 6i 9


April 2000
custom_summary);
AddaLine(' begin', custom_summary);
AddaLine(' if (:CS_Count1 mod 2 = ''1'') then',
custom_summary);
AddaLine(' srw.set_foreground_fill_color(''lightgrey'');',
custom_summary);
AddaLine(' srw.set_fill_pattern(''solid'');',
custom_summary);
AddaLine(' end if;', custom_summary);
AddaLine(' return (TRUE);', custom_summary);
AddaLine(' end;', custom_summary);
AddaLine(' ]]>', custom_summary);
AddaLine(' </function>', custom_summary);
AddaLine(' <function name="F_CS_Count1FormatTrigger">',
custom_summary);
AddaLine(' <![CDATA[ ', custom_summary);
AddaLine(' function F_CS_Count1FormatTrigger return boolean is',
custom_summary);
AddaLine(' begin', custom_summary);
AddaLine(' if (:CS_Count1 mod 2 = ''1'') then',
custom_summary);
AddaLine(' srw.set_foreground_fill_color(''lightgrey'');',
custom_summary);
AddaLine(' srw.set_text_color(''lightgrey'');',
custom_summary);
AddaLine(' srw.set_fill_pattern(''solid'');',
custom_summary);
AddaLine(' else', custom_summary);
AddaLine(' srw.set_text_color(''white'');',
custom_summary);
AddaLine(' end if;', custom_summary);
AddaLine(' return (TRUE);', custom_summary);
AddaLine(' end;', custom_summary);
AddaLine(' ]]>', custom_summary);
AddaLine(' </function>', custom_summary);
AddaLine(' </programUnits>', custom_summary);

Specifying the section title


In the template used to default the header section, there is a boilerplate text object for the section title. The
following PL/SQL provides meaningful text for the text object so that the section will have a descriptive title.
If you did not do this, the section title would not be pertinent to this report. Notice that every customization
must end with a </report> tag.
AddaLine('<customize>', custom_summary);
AddaLine(' <object name="B_4_SEC1" type="REP_GRAPHIC_TEXT">',
custom_summary);
AddaLine(' <properties>', custom_summary);
AddaLine(' <property name="textSegment">Video Sales
Summary</property>', custom_summary);
AddaLine(' </properties>', custom_summary);
AddaLine(' </object>', custom_summary);
AddaLine('</customize>', custom_summary);
END IF;
AddaLine('</report>', custom_summary);

Personalized Reporting with Reports Developer Release 6i 10


April 2000
Closing the file and applying the personalization
After the summary section is completed, you need to close the file, if the user asked to write the XML to a
file, and apply the XML to the base report. Note that in this case, you are applying the XML stored in the
document buffer. If you were applying the XML stored in a file, you would need to specify a file name and
location.
IF :WRITE_TO_FILE='Yes' THEN
Text_IO.Fclose (custom_summary);
END IF;
SRW.APPLY_DEFINITION;

Applying the format mask to existing fields


You now must apply the format mask chosen by the user to the monetary values in the body section of the
report. Note how you can change the format mask of a column without affecting any of its other formatting
characteristics. If you do not specify a value in the XML for an existing column, it will default to what was
specified in the base report.
IF :WRITE_TO_FILE='Yes' THEN
custom_mask := Text_IO.Fopen(:file_directory || 'vid_mask_per.xml',
'w');
END IF;
AddaLine('<report name="video_custom" author="Generated"
DTDVersion="1.0">', custom_mask);
IF :MONEY_FORMAT='$NNNN.00' THEN
AddaLine(' <layout>', custom_mask);
AddaLine(' <section name="main">', custom_mask);
AddaLine(' <field name="F_TOTAL_PROFIT" source="TOTAL_PROFIT"
formatMask="LNNNNNNNNNNN0D00" alignment="end"/>', custom_mask);
AddaLine(' <field name="F_TOTAL_SALES" source="TOTAL_SALES"
formatMask="LNNNNNNNNNNN0D00" alignment="end"/>', custom_mask);
AddaLine(' <field name="F_TOTAL_COST" source="TOTAL_COST"
formatMask="LNNNNNNNNNNN0D00" alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_PROFITPerCITY"
source="SumTOTAL_PROFITPerCITY" formatMask="LNNNNNNNNNNN0D00"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_SALESPerCITY"
source="SumTOTAL_SALESPerCITY" formatMask="LNNNNNNNNNNN0D00"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_COSTPerCITY"
source="SumTOTAL_COSTPerCITY" formatMask="LNNNNNNNNNNN0D00"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_PROFITPerQUARTER"
source="SumTOTAL_PROFITPerQUARTER" formatMask="LNNNNNNNNNNN0D00"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_SALESPerQUARTER"
source="SumTOTAL_SALESPerQUARTER" formatMask="LNNNNNNNNNNN0D00"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_COSTPerQUARTER"
source="SumTOTAL_COSTPerQUARTER"
formatMask="LNNNNNNNNNNN0D00"alignment="end"/>', custom_mask);
AddaLine(' </section>', custom_mask);
AddaLine(' </layout>', custom_mask);
ELSIF :MONEY_FORMAT='$NNNN' THEN
AddaLine(' <layout>', custom_mask);
AddaLine(' <section name="main">', custom_mask);

Personalized Reporting with Reports Developer Release 6i 11


April 2000
AddaLine(' <field name="F_TOTAL_PROFIT" source="TOTAL_PROFIT"
formatMask="LNNNNNNNNNNN0" alignment="end"/>', custom_mask);
AddaLine(' <field name="F_TOTAL_SALES" source="TOTAL_SALES"
formatMask="LNNNNNNNNNNN0" alignment="end"/>', custom_mask);
AddaLine(' <field name="F_TOTAL_COST" source="TOTAL_COST"
formatMask="LNNNNNNNNNNN0" alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_PROFITPerCITY"
source="SumTOTAL_PROFITPerCITY" formatMask="LNNNNNNNNNNN0"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_SALESPerCITY"
source="SumTOTAL_SALESPerCITY" formatMask="LNNNNNNNNNNN0"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_COSTPerCITY"
source="SumTOTAL_COSTPerCITY" formatMask="LNNNNNNNNNNN0"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_PROFITPerQUARTER"
source="SumTOTAL_PROFITPerQUARTER" formatMask="LNNNNNNNNNNN0"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_SALESPerQUARTER"
source="SumTOTAL_SALESPerQUARTER" formatMask="LNNNNNNNNNNN0"
alignment="end"/>', custom_mask);
AddaLine(' <field name="F_SumTOTAL_COSTPerQUARTER"
source="SumTOTAL_COSTPerQUARTER" formatMask="LNNNNNNNNNNN0"
alignment="end"/>', custom_mask);
AddaLine(' </section>', custom_mask);
AddaLine(' </layout>', custom_mask);
END IF;
AddaLine('</report>', custom_mask);
IF :WRITE_TO_FILE='Yes' THEN
Text_IO.Fclose (custom_mask);
END IF;
SRW.APPLY_DEFINITION;

Applying the highlighting


You now must highlight the values over the amount chosen by the user at runtime.
IF :WRITE_TO_FILE='Yes' THEN
custom_hilite_profits := Text_IO.Fopen(:file_directory ||
'vid_hilite_profits_per.xml', 'w');
END IF;
AddaLine('<report name="video_custom" author="Generated"
DTDVersion="1.0">', custom_hilite_profits);
IF :HILITE_PROFITS <> 'None' THEN
AddaLine(' <layout>', custom_hilite_profits);
AddaLine(' <section name="main">', custom_hilite_profits);
AddaLine(' <field name="F_TOTAL_PROFIT" source="TOTAL_PROFIT"
alignment="end">', custom_hilite_profits);
AddaLine(' <exception textColor="red">', custom_hilite_profits);
AddaLine(' <condition source="TOTAL_PROFIT" operator="gt"
operand1=":hilite_profits"/>', custom_hilite_profits);
AddaLine(' </exception>', custom_hilite_profits);
AddaLine(' </field>', custom_hilite_profits);
AddaLine(' </section>', custom_hilite_profits);
AddaLine(' </layout>', custom_hilite_profits);
END IF;
AddaLine('</report>', custom_hilite_profits);

Personalized Reporting with Reports Developer Release 6i 12


April 2000
IF :WRITE_TO_FILE='Yes' THEN
Text_IO.Fclose (custom_hilite_profits);
END IF;
SRW.APPLY_DEFINITION;
IF :WRITE_TO_FILE='Yes' THEN
custom_hilite_costs := Text_IO.Fopen(:file_directory ||
'vid_hilite_costs_per.xml', 'w');
END IF;
AddaLine('<report name="video_custom" author="Generated"
DTDVersion="1.0">', custom_hilite_costs);
IF :HILITE_COSTS <> 'None' THEN
AddaLine(' <layout>', custom_hilite_costs);
AddaLine(' <section name="main">', custom_hilite_costs);
AddaLine(' <field name="F_TOTAL_COST" source="TOTAL_COST"
alignment="end">', custom_hilite_costs);
AddaLine(' <exception textColor="red">', custom_hilite_costs);

AddaLine(' <condition source="TOTAL_COST" operator="gt"


operand1=":hilite_costs"/>', custom_hilite_costs);
AddaLine(' </exception>', custom_hilite_costs);
AddaLine(' </field>', custom_hilite_costs);
AddaLine(' </section>', custom_hilite_costs);
AddaLine(' </layout>', custom_hilite_costs);
END IF;
AddaLine('</report>', custom_hilite_costs);
IF :WRITE_TO_FILE='Yes' THEN
Text_IO.Fclose (custom_hilite_costs);
END IF;
SRW.APPLY_DEFINITION;
IF :WRITE_TO_FILE='Yes' THEN
custom_hilite_sales := Text_IO.Fopen(:file_directory ||
'vid_hilite_sales_per.xml', 'w');
END IF;
AddaLine('<report name="video_custom" author="Generated"
DTDVersion="1.0">', custom_hilite_sales);
IF :HILITE_SALES <> 'None' THEN
AddaLine(' <layout>', custom_hilite_sales);
AddaLine(' <section name="main">', custom_hilite_sales);
AddaLine(' <field name="F_TOTAL_SALES" source="TOTAL_SALES"
alignment="end">', custom_hilite_sales);
AddaLine(' <exception textColor="red">', custom_hilite_sales);
AddaLine(' <condition source="TOTAL_SALES" operator="gt"
operand1=":hilite_sales"/>', custom_hilite_sales);
AddaLine(' </exception>', custom_hilite_sales);
AddaLine(' </field>', custom_hilite_sales);
AddaLine(' </section>', custom_hilite_sales);
AddaLine(' </layout>', custom_hilite_sales);
END IF;
AddaLine('</report>', custom_hilite_sales);
IF :WRITE_TO_FILE='Yes' THEN
Text_IO.Fclose (custom_hilite_sales);
END IF;
SRW.APPLY_DEFINITION;
return (TRUE);
end;

Personalized Reporting with Reports Developer Release 6i 13


April 2000
TESTING AND DEBUGGING THE REPORT
Once you have built your base report and the personalizations that you will allow users, you need to carefully
test both. By writing the XML to a file, you can quickly tell whether your code is working correctly.
Obviously, if no lines are being written to the file, you know that your PL/SQL is incorrect in some way. If
the file is being written, you can visually check each of the personalizations for any obvious errors such as a
missing </report> tag. Furthermore, the XML files that you generate can be applied to the base report at
runtime using the CUSTOMIZE command line argument. If you cannot successfully apply the XML files you
generate from your PL/SQL to the base report, then you will get an error that describes the problem in the
XML.

PUBLISHING THE REPORT


Once you have tested your report, you are ready to begin releasing it to your users for their usage. The best
way to publish your reports is through the Reports Server. The Reports Server enables a large number of
users to run your report from the Web. For more information, refer to the Publishing Reports manual.

SUMMARY
To give your users more freedom to control report output, you can code report personalizations in XML.
Users can then choose which of these XML personalizations they want to use at runtime. The best way to
implement complex personalizations is through PL/SQL where you have conditional control.
All of the examples in this paper can be viewed and testing using the video_custom.rdf report which is
contained on the Oracle Forms and Reports demo cd release 6i.

RELATED DOCUMENTATION
Publishing Reports, Part No. A73072
Oracle Forms and Reports Demos, Part No. A84469-01
For other white papers and examples about Oracle Developer, please visit the Reports Developer page on the
Oracle Technology Network Web site (http://technet.oracle.com/products/reports/).

Personalized Reporting with Reports Developer Release 6i 14


April 2000
Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065
U.S.A.

Worldwide Inquiries:
+1.415.506.7000
Fax +1.415.506.7200
http://www.oracle.com/

Copyright © Oracle Corporation 1997


All Rights Reserved

This document is provided for informational purposes


only, and the information herein is subject to change
without notice. Please report any errors herein to
Oracle Corporation. Oracle Corporation does not
provide any warranties covering and specifically
disclaims any liability in connection with this
document.

Oracle is a registered trademark and Enabling the


Information Age, Oracle7, Oracle8, PL/SQL,
Designer/2000, Developer/2000, Oracle Forms, Oracle
Applications, Oracle General Ledger, Oracle Order
Entry, Oracle Payables, and Oracle Purchasing are
trademarks of Oracle Corporation.

All other company and product names mentioned are


used for identification purposes only and may be
trademarks of their respective owners.

Personalized Reporting with Reports Developer Release 6i 15


April 2000

Вам также может понравиться