1

Report trigger order of execution
The order of events when a report is executed is as follows: 1 2 3 4 5 6 7 8 Before Parameter Form trigger is fired. Runtime Parameter Form appears (if not suppressed). After Parameter Form trigger is fired (unless the user cancels from the Runtime Parameter Form). Report is "compiled." Queries are parsed. Before Report trigger is fired. SET TRANSACTION READONLY is executed (if specified via the READONLY argument or setting). The report is executed and the Between Pages trigger fires for each page except for the very first page. (Note that data can be fetched at any time while the report is being formatted.) COMMITs can occur during this time due to any of the following--user exit with DDL, SRW.DO_SQL with DDL, or if ONFAILURE=COMMIT, and the report fails. COMMIT is executed (if READONLY is specified) to end the transaction. After Report trigger is fired. COMMIT/ROLLBACK/NOACTION is executed based on what was specified via the ONSUCCESS argument or setting.

9 10 11

Cautions • In steps 4 through 9, avoid DDL statements that would modify the tables on which the report is based. Step 3 takes a snapshot of the tables and the snapshot must remain valid throughout the execution of the report. In steps 7 through 9, avoid DML statements that would modify the contents of the tables on which the report is based. Queries may be executed in any order, which makes DML statements unreliable (unless performed on tables not used by the report). If you specify READONLY, you should avoid DDL altogether. When you execute a DDL statement (e.g., via SRW.DO_SQL or a user exit), a COMMIT is automatically issued. If you are using READONLY, this will prematurely end the transaction begun by SET TRANSACTION READONLY.

Which report trigger to use
As a general rule, • Any processing that will affect the data retrieved by the report should be performed in the Before Parameter Form or After Parameter Form triggers. (These are the two report triggers that fire before anything is parsed or fetched.) Any processing that will not affect the data retrieved by the report can be performed in the other triggers.

2 Report Builder has five global report triggers. You cannot create new global report triggers. The trigger names indicate at what point the trigger fires: 1. Before Report • Fires before the report is executed but after queries are parsed.

2. After Report • • • • Fires after you exit the Previewer, Or after report output is sent to a specified destination, such as a file, a printer, or an Oracle Office userid. This trigger can be used to clean up any initial processing that was done, such as deleting tables. Note, however, that this trigger always fires, whether or not your report completed successfully.

3. Between Pages • • • Fires before each page of the report is formatted except the very first page. This trigger can be used for customized page formatting. In the Previewer, this trigger only fires the first time that you go to a page. If you subsequently return to the page, the trigger does not fire again.

4. Before Parameter Form Fires before the Runtime Parameter Form is displayed. From this trigger, you can access and change the values of parameters, PL/SQL global variables, and report-level columns. • If the Runtime Parameter Form is suppressed, this trigger still fires. Consequently, you can use this trigger for validation of command line parameters. 5. After Parameter Form • • • • • Fires after the Runtime Parameter Form is displayed. From this trigger, you can access parameters and check their values. This trigger can also be used to change parameter values or, if an error occurs, return to the Runtime Parameter Form. Columns from the data model are not accessible from this trigger. If the Runtime Parameter Form is suppressed, the After Parameter Form trigger still fires. Consequently, you can use this trigger for validation of command line parameters or other data. • •

Validation trigger
• Validation triggers are PL/SQL functions that are executed when parameter values are specified on the command line and when you accept the Runtime Parameter Form. (Notice that this means each validation trigger may fire twice when you execute the report.) Validation triggers are also used to validate the Initial Value property of the parameter. The function must return a boolean value (TRUE or FALSE). Depending on whether the function returns TRUE or FALSE, the user is returned to the Runtime Parameter Form.

• •

3 • On Failure The user is returned to the parameter value in the Runtime Parameter Form where they can either change it or cancel the Runtime Parameter Form.

Validation trigger example
/* This function prevents the runtime user from ** sending report output anywhere except a printer. ** The user will be returned to the Runtime Parameter ** Form unless PRINTER is specified as the destination ** type (DESTYPE). */ function DESTYPEValidTrigger return boolean is begin IF UPPER(:DESTYPE) = 'PRINTER' THEN RETURN(TRUE); ELSE RETURN(FALSE); END IF; end;

Validation trigger restrictions
• • The PL/SQL in a validation trigger can be a maximum of 32K characters. The upward limit may vary between operating systems. In a validation trigger, you can read and assign values to Report Builder parameters. You cannot read or assign values to columns. For example, you can use the value of a parameter called COUNT1 in a condition (e.g., IF :COUNT1 = 10) and you can directly set its value in an assignment statement (e.g., :COUNT1 = 15). In some cases, though, the Validation Trigger may fire more than once for the same parameter. As a result, it is usually best to assign parameter values in the After Parameter Form trigger. Note also that the use of PL/SQL global variables to indirectly set the values of columns is not supported. If you do this, you may get unpredictable results. You should not use DDL in Validation triggers. For reports that are spawned processes of other reports (e.g., run with BACKGROUND=YES), you should commit database changes you make in the Before Parameter Form, After Parameter Form, and Validation triggers before the report runs. Spawned processes use their parent process' database connection for the Before Parameter Form, After Parameter Form, and Validation triggers. When the spawned process runs the report, though, it establishes its own database connection. Any database changes not committed by the time the child report runs will therefore be lost.

• • • •

Format triggers
A format trigger is a PL/SQL function executed before an object is formatted. A trigger can be used to dynamically change the formatting attributes of the object. Example: Suppressing Labels

4 /* Suppose that you are building a master/detail report and, if no detail records are retrieved for a master record, you do not want the boilerplate labels to appear. To do this, you first create a summary column called MYCOUNT with a Function of Count in the source group of the master repeating frame. In the format trigger for the group frame that surrounds the detail repeating frame and its labels, you enter the following: */ function my_formtrig return BOOLEAN is begin if :mycount = 0 then return (false); else return (true); end if; end; Example: Suppressing Values /* Suppose that you are building a salary report and you only want to see salaries above $2500. In the report summary of all salaries, however, you want all salaries to be included. To do this, you create a data model for the report without restricting the records retrieved. Then, you enter the following format trigger for the repeating frame. The report output will only show salaries greater than $2500, but the summary that calculates the sum of all salaries will include all the salaries retrieved from the database. */ function my_formtrig return BOOLEAN is begin if :sal > 2500 then return (true); else return (false); end if; end; Effect on Performance by Format Triggers Place PL/SQL in the format trigger of the object with the lowest frequency possible. For example, PL/SQL in the format trigger of a frame instead of a field typically makes the report run faster. Rationale: The PL/SQL in format trigger is executed for each instance of its object. The lower the frequency of the object, the fewer times the PL/SQL will be executed and the faster the report will run. Usage Notes:Because you cannot be sure how many times a format trigger will fire for a particular object, you should not perform calculations or use DML in a format trigger.

Formula columns
A formula column performs a user-defined computation on another column(s) data, including placeholder columns. Formulas are PL/SQL functions that populate formula , including placeholder columns. Note: Formula Columns should not be used to set the values of other columns

5 Restrictions • In a formula, you can read and assign values to the column itself, placeholder columns, and parameters of the correct frequency (look at the rule below). For example, you can use the value of a column called COMP in a condition (e.g., IF :COMP = 10) and you can directly set its value in an assignment statement (e.g., :COMP := 15). A formula can only make reference to columns that are in the same or a higher group in the group hierarchy. For example, a formula for a report-level column can only reference other report-level columns. • Formulas are calculated such that any column referenced in the formula will be calculated first. To do so, Report Builder builds a dependency list, to guarantee proper ordering of calculations. Note that circular dependencies, in which a column references another column which in turn references the first column, either directly or indirectly, are not allowed. A user exit may only change the value of a placeholder column. When using SRW.DO_SQL, we recommend that you do not read database values that are updated or inserted in the same report. There is no guarantee of the exact time Report Builder will fetch records from the database for formatting the output. Report Builder does internal "data look-ahead" to optimize performance. Thus, a particular record might already have been accessed before an update is issued to the same record. Report Builder builds internal dependency lists which guarantee that events, such as invocation of user exits, calculation of summaries, etc., happen in the correct order. However, Report Builder cannot guarantee these events will be synchronized with its internal data access or with the formatting of data.

• •

Summary column Summary column performs a computation on another column's data. you can create the following summaries: sum, average, count, minimum, maximum, % total. first, last, standard deviation, variance. Suppose that you have a report that looks like the one below: Deptno 10 Dname ACCOUNTING Ename ----------- MILLER CLARK KING Sal --------1300.00 2450.00 5000.00 %Dept -----14.86% 28.00% 57.14% %Total -----6.62% 12.48% 25.48%

Deptno 20 Dname RESEARCH Ename ----------SMITH ADAMS JONES SCOTT FORD Sal ---------800.00 1100.00 2975.00 3000.00 3000.00 %Dept -----7.36% 10.11% 27.36% 27.59% 27.59% %Total -----4.08% 5.61% 15.16% 15.29% 15.29%

6 The parent group, G_DEPT, contains the DEPTNO and DNAME columns. G_EMP, contains the ENAME and SAL columns. The child group,

To get a summary that calculates each employee's salary as a percentage of total department salaries (Pct_Dept), you create a summary column in G_EMP with the following settings: Function Reset At Compute At % of Total G_EMP G_DEPT In this case, Reset At indicates that the summary should be reset to null for each employee. This is because you want a separate percentage for each individual employee. Compute At indicates that the total of salaries for the department is the whole (100%) across which to compute the percentages. It should also be noted that this summary is placed in the G_EMP group because you want the percentage to appear for each employee. To get a summary that calculates each employee's salary as a percentage of total salaries for the entire report (Pct_Total), you create a summary column in G_EMP with the following settings: Function % of Total Reset At G_EMP Compute At Report

In this case, Compute At indicates that the total of salaries for the entire report is the whole (100%) across which to compute the percentages. As with the Pct_Dept summary above, Reset At indicates that the summary should be reset to null for each employee and the summary is placed in the G_EMP group because you want the percentage to appear for each employee. Compute At property The Compute At property is the group over which a % of Total summary column is computed. Compute At is used only for columns with a Function of % of Total. When you calculate a percentage, you divide a value by a total (e.g., SMITH's salary/total department salaries). Compute At defines the total for a percentage calculation. Using this field, Report Builder determines the total of which each source column value is a percentage. For matrix reports, Compute At can be multiple groups. Values Page Is used to calculate the source column as a percentage of the total values on a page. Report Is used to calculate the source column as a percentage of the total values in the report. <names> Is used to calculate the source column as a percentage of the total values in the group(s). Applies to summary columns Required/Optional required, for summary columns with a Function of % of Total. Default The parent group of the summary column's group Reset At property The Reset At property is the group at which the summary column value resets to zero (if Function is Count), null (if Function is not Count), or Value If Null (if the column has one). Reset At has a list of values containing valid reset groups. Reset At determines if the summary is a running summary or a periodic (e.g., group-level) summary. Values

7 Page Is used for page-level summaries. The summary is reset between pages. Report Is used for summaries that apply to the entire report, such as grand totals. The summary is reset after the report (i.e., it is never reset). <names> Is a valid group name. The summary is reset after each record of the group. Applies to summary columns Required/Optional required, for columns of Type Summary. Usage Notes The reset group of a summary column may be its group or any group above its group, including Report and Page. To ensure that page summaries behave in a predictable way, make sure each record fits on a single page, or if that is not feasible, force each new record to print on a new page. Placeholder column A placeholder is a column for which you set the datatype and value in PL/SQL that you define. You can set the value of a placeholder column in the following places: • • • The Before Report Trigger, if the placeholder is a report-level column A report-level formula column, if the placeholder is a report-level column

A formula in the placeholder's group or a group below it (the value is set once for each record of the group) Example Suppose that you wanted to create a master/detail report that would list the highest paid employee(s) for each department. The output below shows a sample of what you would get:

8 To get the names of the highest paid employee(s), you create a placeholder column named HIGHEST_PAID_EMP of Data type Character. The value of HIGHEST_PAID_EMP is set by a formula column named SET_HIGHEST_PAID_EMP of Data type Character. SET_HIGHEST_PAID_EMP contains the following PL/SQL function in Formula: (R_COUNT is a summary column with a Function of Count) Function set_plch_high_emp return character is Begin /* Check if we are at first record in child, if so, then reset placeholder */ If (:r_count <= 1) then :highest_paid_emp := ' '; End if; /* Does this child record compare to the max sal for the dept ? If yes, and placeholder already Set (i.e. we have more than one max sal) set the placeholder to the concatenated string. Else Set the placeholder to the employee's name */ If (:sal = :max_dept_sal) then If (:highest_paid_emp <> ' ') then :highest_paid_emp := :highest_paid_emp||' and ' ||:ename; Else :highest_paid_emp := :ename; End if; End if; Return (:highest_paid_emp); End;

Lexical Parameters
Lexical references are placeholders for text that you embed in a SELECT statement. You can use lexical references to replace the clauses appearing after SELECT, FROM, WHERE, GROUP BY, ORDER BY, HAVING, CONNECT BY, and START WITH. You cannot make lexical references in a PL/SQL statement. You can, however, use a bind reference in PL/SQL to set the value of a parameter that is then referenced lexically in SQL. Look at the example below. You create a lexical reference by entering an ampersand (&) followed immediately by the column or parameter name. A default definition is not provided for lexical references. Therefore, you must do the following: • Before you create your query, define a column or parameter in the data model for each lexical reference in the query. For columns, you must enter Value if Null, and, for parameters, you must enter Initial Value. Report Builder uses these values to validate a query with a lexical reference. Create your query containing lexical references.

Restrictions • You cannot make lexical references in a PL/SQL statement.

• •

9 If a column or parameter is used as a lexical reference in a query, its Datatype must be Character. If you want to use lexical references in your SELECT clause, you should create a separate lexical reference for each column you will substitute. In addition, you should assign an alias to each lexical reference. This enables you to use the same layout field and boilerplate label for whatever value you enter for the lexical reference on the Runtime Parameter Form. If you use lexical references in your SELECT clause, you must specify the same number of items at runtime as were specified in the report's data model. Each value you specify for your lexical references at runtime must have the same datatype as its Initial Value. If you use lexical references in your SELECT clause, the width of the column is derived from the Initial Value of the parameter. Consequently, you should ensure that the Initial Value of the parameter corresponds to the widest column that you intend to use. A Report Builder link should not depend upon a lexical reference. That is, neither the child column of a link or its table name should be determined by a lexical reference. To achieve this functionality, you need to create a link with no columns specified and then enter the SQL clause (e.g., WHERE) for the link directly in the query. For example, your parent and child queries might be written as follows: Parent Query: SELECT DEPTNO FROM EMP Child Query: SELECT &PARM_1 COL_1, &PARM2 COL_2 FROM EMP WHERE &PARM_1 = :DEPTNO Note how the WHERE clause makes a bind reference to DEPTNO, which was selected in the parent query. Also, this example assumes that you have created a link between the queries in the Data Model editor with no columns specified.

A lexical reference cannot be used to create additional bind variables after the After Form trigger fires. For example, suppose you have a query like the following (note that the WHERE clause is replaced by a lexical reference): SELECT ENAME, SAL FROM EMP &where_clause If the value of the WHERE_CLAUSE parameter contains a reference to a bind variable, you must specify the value in the After Form trigger or earlier. You would get an error if you supplied the following value for the parameter in the Before Report trigger: WHERE SAL = :new_bind

• If you supplied this same value in the After Form trigger, the report would run. Examples SELECT Clause SELECT &P_ENAME NAME, &P_EMPNO ENO, &P_JOB ROLE FROM EMP P_ENAME, P_EMPNO, and P_JOB can be used to change the columns selected at runtime. For example, you could enter DEPTNO as the value for P_EMPNO on the Runtime Parameter Form. Note that in this case, you should use aliases for your columns. Otherwise, if you

10 change the columns selected at runtime, the column names in the SELECT list will not match the Report Builder columns and the report will not run. • FROM Clause SELECT ORDID, TOTAL FROM &ATABLE ATABLE can be used to change the table from which columns are selected at runtime. For example, you could enter ORD for ATABLE at runtime. If you dynamically change the table name in this way, you may also want to use lexical references for the SELECT clause (look at the previous example) in case the column names differ between tables. • WHERE Clause SELECT ORDID, TOTAL FROM ORD WHERE &CUST CUST can be used to restrict records retrieved from ORD. Any form of the WHERE clause can be specified at run-time. • GROUP BY Clause SELECT NVL(COMMPLAN, DFLTCOMM) CPLAN, SUM(TOTAL) TOTAL FROM ORD GROUP BY &NEWCOMM The value of NEWCOMM can be used to define the GROUP BY clause. • HAVING Clause SELECT CUSTID, SUM(TOTAL) TOTAL FROM ORD GROUP BY CUSTID HAVING &MINTOTAL The value of MINTOTAL could, for example, be used to select customers with a minimum total of orders. • ORDER BY Clause SELECT ORDID, SHIPDATE, ORDERDATE, TOTAL FROM ORD ORDER BY &SORT The value of SORT can be used to select SHIPDATE, ORDERDATE, ORDID, or any combination as the sort criterion. It could also be used to add on to the query, for example to add a CONNECT BY and START WITH clause. • CONNECT BY and START WITH Clauses Parameters in CONNECT BY and START WITH clauses are used in the same way as they are in the WHERE and HAVING clauses. Multiple Clauses • SELECT &COLSTABLE COLSTABLE could be used to change both the SELECT and FROM clauses at runtime. For example, you could enter DNAME ENAME, LOC SAL FROM DEPT for COLSTABLE at runtime.

11 SELECT * FROM EMP &WHEREORD WHEREORD could be used to change both the WHERE and ORDER BY clauses at runtime. For example, you could enter WHERE SAL > 1000 ORDER BY DEPTNO for &WHEREORD at runtime. • PL/SQL and SQL SELECT &BREAK_COL C1, MAX(SAL) FROM EMP GROUP BY &BREAK_COL BREAK_COL is used to change both the SELECT list and the GROUP BY clause at runtime. The Initial Value of the parameter &BREAK_COL is JOB. At runtime, the user of the report can provide a value for a parameter called GROUP_BY_COLUMN (of Datatype Character). In the Validation Trigger for GROUP_BY_COLUMN, you call the following PL/SQL procedure and pass it the value of GROUP_BY_COLUMN: procedure conv_param (in_var IN char) is begin if upper(in_var) in ('DEPTNO','EMPNO','HIREDATE') then :break_col := 'to_char('||in_var||')' ; else :break_col := in_var; end if; end; This PL/SQL ensures that, if necessary, a TO_CHAR is placed around the break column the user chooses. Notice how in SQL, you make a lexical reference to BREAK_COL. In PL/SQL, you must make a bind reference to BREAK_COL because lexical references are not allowed in PL/SQL.

Bind Parameters
• • • Bind references (or bind variables) are used to replace a single value in SQL or PL/SQL, such as a character string, number, or date. Specifically, bind references may be used to replace expressions in SELECT, WHERE, GROUP BY, ORDER BY, HAVING, CONNECT BY, and START WITH clauses of queries. Bind references may not be referenced in FROM clauses or in place of reserved words or clauses. You create a bind reference by entering a colon (:) followed immediately by the column or parameter name. If you do not create a column or parameter before making a bind reference to it in a SELECT statement, Report Builder will create a parameter for you by default. Restrictions • Bind references must not be the same name as any reserved SQL keywords. For more information, see the Oracle8 Server SQL Language Reference Manual.

Examples

12 • SELECT Clause SELECT CUSTID, NVL(COMMPLAN, :DFLTCOMM) COMMPLAN FROM ORD The value of DFLTCOMM replaces null values of COMMPLAN in the rows selected. • WHERE Clause SELECT ORDID, TOTAL FROM ORD WHERE CUSTID = :CUST The value of CUST is used to select a single customer. • GROUP BY Clause SELECT NVL(COMMPLAN, :DFLTCOMM) COMMPLAN, SUM(TOTAL) TOTAL FROM ORD GROUP BY NVL(COMMPLAN, :DFLTCOMM) All non-aggregate expressions such as NVL(COMMPLAN, :DFLTCOMM) in the SELECT clause must be replicated in the GROUP BY clause. • HAVING Clause SELECT CUSTID, SUM(TOTAL) TOTAL FROM ORD GROUP BY CUSTID HAVING SUM(TOTAL) > :MINTOTAL The value of MINTOTAL is used to select customers with a minimum total of orders. • ORDER BY Clause SELECT ORDID, SHIPDATE, ORDERDATE, TOTAL DECODE(:SORT, 1, SHIPDATE, 2, ORDERDATE) FROM ORD ORDER BY

The value of SORT is used to select either SHIPDATE or ORDERDATE as the sort criterion. Note that this is not the same as ORDER BY 1 because :SORT is used as a value rather than to identify the position of an expression in the SELECT list. Note that DECODE is required in this example. You cannot use a bind variable in an ORDER BY clause unless it is with DECODE. • CONNECT BY and START WITH Clauses References in CONNECT BY and START WITH clauses are used in the same way as they are in the WHERE and HAVING clauses. • PL/SQL procedure double is begin; :my_param := :my_param*2; end; The value of myparam is multiplied by two and assigned to myparam.

User Exits

13 A user exit is a program that you write and then link into the Report Builder executable or user exit DLL files. You build user exits when you want to pass control from Report Builder to a program you have written, which performs some function, and then returns control to Report Builder. You can write the following types of user exits: • • • ORACLE Precompiler user exits OCI (ORACLE Call Interface) user exits non-ORACLE user exits

You can also write a user exit that combines both the ORACLE Precompiler interface and the OCI. • • • • • • User exits can perform the following tasks: perform complex data manipulation pass data to Report Builder from operating system text files manipulate LONG RAW data support PL/SQL blocks control real time devices, such as a printer or a robot

You can use user exits for other tasks, such as mathematical processing. However, Oracle Corporation recommends that you perform such tasks with PL/SQL within Report Builder. Usage Notes • • Not all types of user exits can perform all of the described tasks. You can accomplish most of these tasks only with ORACLE Precompiler user exits. Some details of implementing user exits are specific to each operating system.

User Exits Used in Oracle Reports
The user exits available in Oracle Reports are: • • • FND SRWINIT and FND SRWEXIT FND FLEXIDVAL and FND FLEXSQL FND FORMAT_CURRENCY

FND SRWINIT / FND SRWEXIT

14 • FND SRWINIT sets your profile option values and allows AOL user exits to detect that they have been called by an Oracle Reports program. FND SRWINIT also allows your report to use the correct organization automatically. FND SRWEXIT ensures that all the memory allocated for Oracle Application Object Library user exits has been freed up properly.

FND FLEXIDVAL / FND FLEXSQL These user exits allow you to use flex fields in your reports. They are documented in the Oracle Applications Flex fields Guide.

Using Dynamic Currency in Oracle Reports
A flexible, consistent method to format a numeric value according to its associated currency. • • • • The currency value appears with the correct thousands separator and radix character (decimal point) of the user’s country. The value appears with positive and negative indicators of the user’s choice. Displayed currency values are never rounded or truncated except when explicitly specified to be scaled. If the formatted value (which includes the thousands separator) does not fit in the output field, then the currency value without the thousands separator is used. If this value is still too large for the output field, then asterisk characters (***) are displayed in the field to alert you of an overflow condition.

You use the same methodology to add support for report regions with one currency type (for example, US dollar amounts) and for report regions with mixed currency types (for example, US dollar and Japanese yen amounts). However, when reporting on mixed currency amounts you include a special argument to indicate that you wish to align all different currency types at a standard point (usually the precision of the currency with the greatest precision). This precision is defined by a profile option or set by the user of the report at execution time. Currency Formatting Requirements A report based on a single currency type should display currency amounts aligned along the radix character as illustrated in the following example

If the user chooses a negative or a positive indicator such as parentheses that appears at the right of the currency amount, then values are not flushed with the right margin but are shifted to the left to accommodate the indicator. A mixed currency report should display currency amounts aligned along the radix character (or implied radix for currencies with no precision like JPY).

15

Call the FND FORMAT_CURRENCY user exit to format the Currency Value column. In this mixed currency report, the minimum precision (specified in the MINIMUM_PRECISION token in the user exit) is set to 3. FND FORMAT_CURRENCY User Exit This user exit formats the currency amount dynamically depending upon • The precision of the actual currency value, • The standard precision, • Whether the value is in a mixed currency region, • The user’s positive and negative format profile options, • And the location (country) of the site. The location of the site determines the thousands separator and radix to use when displaying currency values. An additional profile determines whether the thousands separator is displayed.
Note: Use the Currencies window to set the standard, extended, and minimum precision of a currency. Method

1) You obtain the currency value from the database into an Oracle Reports column. 2) Define another Oracle Reports column, a formula column of type CHAR, which executes the FORMAT_CURRENCY user exit to format the currency value. 3) A displayed field has this formula column as its source so that the formatted value is automatically copied into the field for display. Syntax: FND FORMAT_CURRENCY
CODE=”: column containing currency code” DISPLAY_WIDTH=”field width for display” AMOUNT=”: source column name” DISPLAY=”: display column name” [MINIMUM_PRECISION=”: P_MIN_PRECISION”] [PRECISION=”{STANDARD|EXTENDED}”] [DISPLAY_SCALING_FACTOR=””: P_SCALING_FACTOR”]

16

Mixed

Currency Reports Every report with a mixed currency region should allow the user to override the default setting of the mixed currency precision profile option at submission time. Define a report argument that accepts this value. The default value of this argument should be the profile option CURRENCY: MIXED_PRECISION (Currency: Mixed Currency Precision) so the user does not always have to set a value explicitly. Example Output

17 The following graphic illustrates various input values and the currency amounts displayed using the user exit (negative amounts are surrounded by parentheses) assuming the report was run in the United States.

If the precision of the input number is less than the precision of the currency then the number is padded with 0’s to match the precision of the currency. If the precision of the input number is greater than the precision of the currency then the radix of that number might get misaligned from other currency amounts in the column. If there is one space allocated on the right for displaying the positive or negative format character (for example the profile option for displaying negative number is set to ”()” or ”<>”) and the current number does not use that space (if the number is positive) then that space is used. If This is not sufficient, then the number is left shifted to display the full precision. If the formatted number does not fit within the DISPLAY_WIDTH then the user exit strips off all thousands separators so as to fit the number in the allowable DISPLAY_WIDTH. The amount may

18 again be misaligned. If it still does not fit then asterisks are printed in that field to indicate an overflow condition. Currency values are never rounded or truncated on display by default. However, the values can be scaled DISPLAY_SCALING_FACTOR token. by a number if explicitly specified by the

The tokens MINIMUM_PRECISION=”:P_MIN_PRECISION” (where the lexical argument was designated as 3) and DISPLAY_WIDTH=”15” apply to all items. Items 1 through 5 show how various currencies display in a mixed currency region with a MINIMUM_PRECISION of 3. All values align along the radix character. Items 6 through 20 depict how positive and negative values are displayed as both amounts progressively increase in magnitude (DISPLAY_WIDTH is a constant 15). When the formatted value exceeds DISPLAY_WIDTH the thousands separators are removed as in items 13, 15, 16, and 18. When the unformatted value exceeds DISPLAY_WIDTH asterisks are displayed indicating an overflow as in items 17, 19, and 20. Notice also that the positive value shifts right into the space normally reserved for the negative indicator. Items 21 through 23 show the effects when displaying a value which exceeds the MINIMUM_PRECISION. Since the negative indicator uses a space on the right, a positive value must exceed MINIMUM_ PRECISION+1 before it shifts to the left.

Example Report Using FND FORMAT_CURRENCY
The following report illustrates how various currencies are formatted using the FND FORMAT_CURRENCY user exit for a report, which displays mixed currency values. This document explains how you develop such a report. • • Information about the radix character and thousands separator are determined from the location of the user. The special display for negative and positive currency values is specified by two profile options.

Hence, a report can appear differently depending upon the location of the user and the profile options values set. The following reports, one run by a user in United States and the other by a user in Germany, depict this difference. In Germany the radix character and thousand separator are switched from the US counterpart. In these reports, both Manama and Seattle had a loss and the negative numbers display in parentheses () or angle brackets <> depending upon the user’s preference.

19

Procedure

20

21

22

USER EXITS for Flex Fields

Oracle Reports 6.0 Flex field Support API
Using Oracle Applications flex fields routines with Oracle Reports, you can build reports that display flex fields data easily and in a number of ways: •Display any individual segment value, prompt, or description. •Display segment values, prompts, or descriptions from multiple flex field structures (or contexts) in the same report. •Display segment values, prompts, or descriptions from different flex fields in the same report. •Display two or more flex field segment values, prompts, or descriptions, concatenated with delimiters, in the correct order. This includes description information for dependent, independent, and table validated segments. •Restrict output based upon a flex field range (low and high values). •Prevent reporting on flex field segments and values that users do not have access to (flex field value security). •Specify order by, group by, and where constraints using one or more, or all segment columns. General Methodology

23 You use a two step method to report on flexfield values. • • The first step creates the appropriate SQL statement dynamically based upon the user’s flexfield. The output of the first step is used as input to the second step. The second step formats this raw data for display.

Step 1 (Construction): The first step requires you to include one or more lexical parameters (Oracle Reports variables that can be changed at runtime) in your SQL statement. You call the user exit FND FLEXSQL with different arguments to specify that part of the query you would like to build. The user exit retrieves the appropriate column names (SQL fragment) and inserts it into the lexical parameter at runtime before the SQL query is executed. The query then returns site– and runtime–specific flexfield information. For example, suppose you have the following query: SELECT &LEXICAL1 alias, column FROM table WHERE &LEXICAL2 The preliminary calls to FND FLEXSQL replace values of LEXICAL1 and LEXICAL2 at execution time with the SQL fragments. For example, LEXICAL1 becomes ”SEGMENT1||’\n’||SEGMENT2” and LEXICAL2 becomes ”SEGMENT1 < 2” (assuming the user’s flexfield is made up of two segments and the user requested that the segment value of SEGMENT1 be less than 2). The actual executed SQL query might be: SELECT SEGMENT1||’\n’||SEGMENT2 alias, column FROM table WHERE SEGMENT1 < 2 The SQL statement for a user with a different flexfield structure might be: SELECT SEGMENT5||’\n’||SEGMENT3||’\n’||SEGMENT8 alias, column FROM table WHERE SEGMENT3 < 2 With this step you can alter the SELECT, ORDER BY, GROUP BY, or WHERE clause. You use this step to retrieve all the concatenated flexfield segment values to use as input to the user exit FND FLEXIDVAL in step 2 (described below). You call this user exit once for each lexical parameter you use, and you always call it at least once to get all segments. This raw flexfield information is in an internal format and should never be displayed (especially if the segment uses a ”hidden ID” value set). Step 2 (Display): The second step requires you to call another user exit, FND FLEXIDVAL, on a ”post–record” basis. You create a new formula column to contain the flexfield information and include the user exit call in this column.

24 This user exit determines the exact information required for display and populates the column appropriately. By using the flexfield routines the user exit can access any flexfield information. Use this step for getting descriptions, prompts, or values. This step derives the flexfield information from the already selected concatenated values and populates the formula column on a row by row basis. You call FND FLEXIDVAL once for each record of flexfield segments. The flexfield user exits for Oracle Reports are similar to their Oracle Application Object Library (using SQL*Forms) counterparts LOADID(R) or LOADDESC and POPID(R) or POPDESC; one to construct or load the values (FLEXSQL), the other to display them (FLEXIDVAL). The token names and meanings are similar. FND FLEXSQL Call this user exit to create a SQL fragment usable by your report to tailor your SELECT statement that retrieves flexfield values. This fragment allows you to SELECT flexfield values or to create a WHERE, ORDER BY, GROUP BY, or HAVING clause to limit or sort the flexfield values returned by your SELECT statement. You call this user exit once for each fragment you need for your select statement. You define all flexfield columns in your report as type CHARACTER even though your table may use NUMBER or DATE or some other datatype. Syntax: FND FLEXSQL CODE=”flexfield code” APPL_SHORT_NAME=”application short name” OUTPUT=”:output lexical parameter name” MODE=”{ SELECT | WHERE | HAVING | ORDER BY}” [DISPLAY=”{ALL | flexfield qualifier | segment number}”] [SHOWDEPSEG=”{Y | N}”] [NUM=”:structure defining lexical” | MULTINUM=”{Y | N}”] [TABLEALIAS=”code combination table alias”] [OPERATOR=”{ = | < | > | <= | >= | != | ”||” | BETWEEN | QBE}”] [OPERAND1=”:input parameter or value”] [OPERAND2=”:input parameter or value”]
Options:
CODE

Specify the flexfield code for this report (for example, GL#). You call FLEXSQL multiple times to set up SQL fragments when reporting on multiple flexfields in one report. APPL_SHORT_NAME Specify the short name of the application that owns this flexfield (for example, SQLGL). OUTPUT Specify the name of the lexical parameter to store the SQL fragment. You use this lexical later in your report when defining the SQL statement that selects your flexfield values. The datatype of this parameter should be character.

25 MODE Specify the mode to use to generate the SQL fragment. Valid modes are: SELECT Retrieves all segments values in an internal (non–displayable) format. If you SELECT a flexfield qualifier, and that flexfield segment is a dependent segment, then flexfields automatically selects both the parent segment and the dependent segment. For example, if the qualifier references the Subaccount segment, then both the Account (the parent) and the Subaccount segment columns are retrieved. Note: You reuse the lexicals you use in the SELECT clause in the GROUP BY clause. WHERE Restrict the query by specifying constraints on flexfield columns. The fragment returned includes the correct decode statement if you specify MULTINUM. You should also specify an OPERATOR and OPERANDS. You can prepend a table alias to the column names using the TABLEALIAS token. HAVING Same calling procedure and functionality as WHERE. ORDER BY Order queried information by flexfield columns. The fragment orders your flexfield columns and separates them with a comma. The fragment returned includes the correct decode statement if you specify MULTINUM. You use the MODE token with the DISPLAY token. The DISPLAY token specifies which segments are included in your SQL fragment in your lexical parameter. For example, if your MODE is SELECT, and you specify DISPLAY=”ALL”, then your SELECT statement includes all segments of the flexfield. Similarly, if your MODE is WHERE, and you specify DISPLAY=”ALL”, then your WHERE clause includes all segments. Frequently you would not want all segments in your WHERE clause, since the condition you specify for the WHERE clause in your actual query would then apply to all your segments (for example, if your condition is ” = 3”, then SEGMENT1, SEGMENT2, ... , SEGMENTn would each have to be equal to 3). DISPLAY You use the DISPLAY token with the MODE token. The DISPLAY parameter allows you to specify which segments you want to use. You can specify segments that represent specified flexfield qualifiers or specified segment numbers, where segment numbers are the order in that the segments appear in the flexfield window, not the segment number specified in the Define Key Segments form. Application developers normally use only flexfield qualifiers in the DISPLAY token, whereas users may customize the report and use a DISPLAY token that references a segment number once the flexfield is set up. The default is ALL, which displays all segments. Alternatively, you can specify a flexfield qualifier name or a segment number. If you specify a non–unique flexfield qualifier, then the routine returns the first segment with this qualifier that appears in the user’s window, not all segments with this qualifier. Only unique segment qualifiers are supported for the WHERE clause. You can use these parameters as toggle switches by specifying them more than once. For example, if you want to use all but the account segment, you specify: DISPLAY=”ALL” DISPLAY=”GL_ACCOUNT”

26 Or, if you want to use all but the first two segments, you specify: DISPLAY=”ALL” DISPLAY=”1” DISPLAY=”2” Note that the order in that flexfield column values are used depends on the order in which they appear in the user’s window, not the order in which you specify them in the report, nor the order in that they appear in the database table. SHOWDEPSEG SHOWDEPSEG=”N” disables automatic addition of depended upon segments to the order criteria. The default value is ”Y”. This token is valid only for MODE=”ORDER BY” in FLEXSQL. NUM or MULTINUM Specify the name of the lexical or source column that contains the flexfield structure information. If your flexfield uses just one structure, specify NUM only and use a lexical parameter to hold the value. If your flexfield uses multiple structures, specify MULTINUM only and use a source column to hold the value. In this case the user exit builds a decode statement to handle the possible changing of structures mid–report. The default is NUM=”101”. TABLEALIAS Specify the table alias you would like prepended to the column names. You use TABLEALIAS if your SELECT joins to other flexfield tables or uses a self–join. OPERATOR Specify an operator to use in the WHERE clause. The operators ”= | < | > | <= | >= | != | QBE | BETWEEN” perform lexical comparisons, not numeric comparisons. With QBE (Query By Example) and BETWEEN operators, the user can specify partial flexfield values to match for one or more segments. For example, if OPERAND1 is ”01––CA%–” (assuming a four–segment flexfield with a delimiter of ’–’), the first segment must match 01 and the third segment is like ’CA%’. The resulting SQL fragment is: SEGMENT1=’01’ AND SEGMENT3 LIKE ’CA%’ For the BETWEEN operator, if OPERAND1 is ”01––CA–” and OPERAND2 is ”05––MA–” then the resulting SQL fragment is: (SEGMENT1 BETWEEN ’01’ AND ’05’) AND (SEGMENT3 BETWEEN ’CA’ AND ’MA’) OPERAND1 Specify an operand to use in the WHERE clause. OPERAND2 Specify a second operand to use with OPERATOR=”BETWEEN”. FND FLEXIDVAL

27 Call this user exit to populate fields for display. You pass the key flexfields data retrieved by the query into this exit from the formula column. With this exit you display values, descriptions and prompts by passing appropriate token (any one of VALUE, DESCRIPTION, APROMPT or LPROMPT). Syntax: FND FLEXIDVAL CODE=”flexfield code” APPL_SHORT_NAME=”application short name” DATA=”:source column name” [NUM=”:structure defining source column/lexical”] [DISPLAY=”{ALL|flexfield qualifier|segment number}”] [IDISPLAY=”{ALL|flexfield qualifier|segment number}”] [SHOWDEPSEG=”{Y | N}”] [VALUE=”:output column name”] [DESCRIPTION=”:output column name”] [APROMPT=”:output column name”] [LPROMPT=”:output column name”] [PADDED_VALUE=”:output column name”] [SECURITY=”:column name”] Options: CODE Specify the flexfield code for this report (for example, GL#). You call FLEXIDVAL multiple times, using a different CODE, to display information for multiple flexfields in one report. APPL_SHORT_NAME Specify the short name of the application that owns this flexfield (for example, SQLGL). DATA Specify the name of the field that contains the concatenated flexfield segment values retrieved by your query. NUM Specify the name of the source column or parameter that contains the flexfield structure information. DISPLAY The DISPLAY parameter allows you to display segments that represent specified flexfield qualifiers or specified segment numbers, where segment numbers are the order in that the segments appear in the flexfield window, not the segment number specified in the Define Key Segments form. The default is ALL, which displays all segments. Alternatively, you can specify a flexfield qualifier name or a segment number. You can use these parameters as toggle switches by specifying them more than once. For example, if you to display all but the first segment, you would specify: DISPLAY=”ALL” DISPLAY=”1”

28 IDISPLAY You use this parameter to tell FLEXIDVAL what segments you used in your SELECT clause in the corresponding FLEXSQL call. FLEXIDVAL needs this information to determine the format of raw data retrieved by FLEXSQL. You set IDISPLAY to the same value as your DISPLAY parameter in your FLEXSQL call. The default value is ALL, so if you used DISPLAY=”ALL” in FLEXSQL, you do not need to use IDISPLAY here. SHOWDEPSEG SHOWDEPSEG=”N” disables automatic display of depended upon segments. The default value is Y. VALUE Specify the name of the column in which you want to display flexfield values. DESCRIPTION Specify the name of the column in which you want to display flexfield descriptions. APROMPT Specify the name of the column in which you want to display flexfield above prompts. LPROMPT Specify the name of the column in which you want to display flexfield left prompts. PADDED_VALUE Specify the name of the column in which you want to display padded flexfield values. The segment values are padded to the segment size with blanks. SECURITY Specify the name of the column into which flag ”S” will be placed if the segment values are secured. You then write logic to hide or display values based on this flag. This token is applicable only for segment values and does not apply to description, left prompt or above prompt. Note: The datatype of the column as specified by VALUE, DESCRIPTION, APROMPT and LPROMPT is CHARACTER. Oracle Reports and Flexfields Report–Writing Steps These are the basic steps you use every time you write an Oracle Reports report that accesses flexfields data. This section assumes you already have a thorough knowledge of Oracle Reports. Though these examples contain only the Accounting Flexfield, you can use these methods for any key flexfield. Step 1 Define your Before Report Trigger (this step is always the same) You always call FND SRWINIT from the Before Report Trigger: SRW.USER_EXIT(’FND SRWINIT’); This user exit sets up information for use by flexfields, user profiles, the concurrent manager, and other Oracle Applications features. You must include this step if you use any Oracle Application Object Library features in your report (such as concurrent processing). Step 2

29 Define your After Report Trigger (this step is always the same) You always call FND SRWEXIT from the After Report Trigger: SRW.USER_EXIT(’FND SRWEXIT’); This user exit frees all the memory allocation done in other Oracle Applications user exits. You must include this step if you use any Oracle Application Object Library features in your report (such as concurrent processing). Step 3 Define your required parameters You define the parameters your report needs by using the Data Model Painter. You use these parameters in the user exit calls and SQL statements. The following table lists lexical parameters:

You must always create the P_CONC_REQUEST_ID lexical parameter. ”FND SRWINIT” uses this parameter to retrieve information about the concurrent request that started this report. The P_FLEXDATA parameter holds the SELECT fragment of the SQL query. The initial value is used to check the validity of a query containing this parameter and to determine the width of the column as specified by the column alias. Its initial value is some string that contains columns with a cumulative width more than the expected width required to hold the data. Make sure the width of this column is sufficient. If there are total 30 segments in the table then the safest initial value will be: (SEGMENT1||’\n’||SEGMENT2||’\n’||SEGMENT3 ...SEGMENT30) You determine the width by determining the length of that string. That length is roughly the number of characters in the table alias plus the length of the column name, times the number of segments your code combinations table contains, times the number of structures you expect, plus more for delimiter characters as shown in the string above. Step 4 Define your other parameters You define the rest of the parameters your report needs by using the Data Model Painter. You use these parameters in the user exit calls and SQL statements. You can use the following table to guide you in listing your lexical parameters and their requirements:

30 Step 5 Call FND FLEXSQL from your Before Report Trigger to populate P_FLEXDATA Next, given that you want to display flexfield information like concatenated values and descriptions, and arrange them in order, you make one call to FND FLEXSQL from the Before Report Trigger specifying the lexical parameters. This call changes the value of the lexical parameter P_FLEXDATA at runtime to the SQL fragment that selects all flexfields value data. For example, the parameter changes to (SEGMENT1||’\n’||SEGMENT2||’\n’||SEGMENT3||’\n’||SEGM ENT4). When you incorporate this lexical parameter into the SELECT clause of a query, it enables the query to return the concatenated segment values that are needed as input to other AOL user exits. These exits then retrieve the actual flexfield information for display purposes. Here is an example FND FLEXSQL call. Notice that the arguments are very similar to other flexfield routine calls; CODE= and NUM= designate the key flexfield and its structure, respectively. For a report on a different key flexfield (such as the System Items flexfield), you would use a different CODE and NUM. SRW.REFERENCE(:P_STRUCT_NUM); SRW.USER_EXIT(’FND FLEXSQL CODE=”GL#” NUM=”:P_STRUCT_NUM” APPL_SHORT_NAME=”SQLGL” OUTPUT=”:P_FLEXDATA” MODE=”SELECT” DISPLAY=”ALL”’); You should always reference any source column/parameter that is used as a source for data retrieval in the user exit. This guarantees that this column/parameter will contain the latest value and is achieved by ”SRW.REFERENCE” call as shown above. Step 6 Call FND FLEXSQL from your Before Report Trigger to populate other parameters You call FND FLEXSQL once for every lexical parameter such as P_WHERE or P_ORDERBY. Step 7 Define your report query or queries Define your report query Q_1: SELECT &P_FLEXDATA C_FLEXDATA FROM CODE_COMBINATIONS_TABLE WHERE CODE_COMBINATIONS_TABLE.STRUCTURE_DEFINING_COLUMN = &P_STRUCT_NUM The query fetches the data required to be used as input for the FLEXIDVAL user exit later. Note: Always provide a column alias (C_FLEXDATA in this example) in the SELECT clause that is the name of column. This name of the column is required in FND FLEXIDVAL. When the report runs, the call to FND FLEXSQL fills in the lexical parameters. As a result the second query would look something like:

31 SELECT (SEGMENT1||’–’||SEGMENT2||’–’||SEGMENT3||’–’|| SEGMENT4) C_FLEXDATA FROM CODE_COMBINATIONS_TABLE WHERE CODE_COMBINATIONS_TABLE.STRUCTURE_DEFINING_COLUMN = 101 Step 8 . Create formula columns Now create columns C_FLEXFIELD and C_DESC_ALL (and any others your report uses) corresponding to the values and descriptions displayed in the report. They all are in group G_1. Be sure to adjust the column width as appropriate for the value the column holds (such as a prompt, which might be as long as 30 characters). Attention: Use word–wrapping for flexfield columns if necessary to avoid possible truncation of your values. Do this by setting Sizing to Expand. Step 9 Populate segment values formula column To retrieve the concatenated flexfield segment values and description, you incorporate the flexfields user exits in these columns. In the column definition of C_FLEXFIELD, you incorporate the FND FLEXIDVAL user exit call in the formula field. You pass the concatenated segments along with other information to the user exit, and the user exit populates the concatenated values in this column as specified by the VALUE token. A typical call to populate segment values in this column looks as follows: SRW.REFERENCE(:P_STRUCT_NUM); SRW.REFERENCE(:C_FLEXDATA); SRW.USER_EXIT(’FND FLEXIDVAL CODE=”GL#” NUM=”:P_STRUCT_NUM” APPL_SHORT_NAME=”SQLGL” DATA=”:C_FLEXDATA” VALUE=”:C_FLEXFIELD” DISPLAY=”ALL”’); RETURN(:C_FLEXFIELD); Step 10 Populate segment descriptions To populate the segment description use DESCRIPTION=”C_DESC_ALL” VALUE=”C_FLEXFIELD” as in the previous call. The user exit call becomes: SRW.REFERENCE(:P_STRUCT_NUM); SRW.REFERENCE(:C_FLEXDATA); SRW.USER_EXIT(’FND FLEXIDVAL CODE=”GL#” NUM=”:P_STRUCT_NUM” APPL_SHORT_NAME=”SQLGL” DATA=”:C_FLEXDATA” DESCRIPTION=”:C_DESC_ALL” instead of

32 DISPLAY=”ALL”’); RETURN(:C_DESC_ALL); You have created parameters and columns that are containers of all the values to be displayed. Now, in the following steps, you create the layout to display these values on the report. Step 11 Create your default report layout Use the Report Wizard to generate the default layout. Deselect C_FLEXDATA. Specify a ”Label” and a reasonable ”Width” for the columns you want to display. The following table lists the default layout column settings:

Oracle Reports takes you to the layout painter. Generate and run the report. Step 12 Finish your report Adjust your report layout as needed. Flexfield Report Examples This section demonstrates how to include flexfield data in your report and how to build different types of reports on flexfields using Oracle Application Object Library (AOL) user exits. The following sample reports demonstrate the methodology involved in constructing five types of reports. •Report 1: Simple Tabular Report: •Report 2: Simple Tabular Report With Multiple Flexfield Structures: •Report 3: Tabular Report: •Report 4: Master–Detail Report: page •Report 5: Master–detail Report On Multiple Structures: page

The first two examples display elementary steps involved in building reports with flexfield support. The next two examples report on a single flexfield structure and show additional features of flexfield support. The fifth report demonstrates how to use these features with multiple flexfield structures. Report 1: Simple Tabular Report

33 This is a sample report that selects Accounting Flexfield values for a single structure for a single company. This report uses a simple WHERE clause and does not use an ORDER BY clause.

This report contains a list of Accounting Flexfield combinations and a description for each based on their segment values. Note: Line numbers listed above are for explanation purposes only and do not appear in report output. Report Writing Steps Step 1 Define your Before Report Trigger SRW.USER_EXIT(’FND SRWINIT’); Step 2 Define your After Report Trigger SRW.USER_EXIT(’FND SRWEXIT’); Step 3 Define your parameters Define the parameters in the following table using the Data Model Painter. You use these parameters in the user exit calls and SQL statements.

34

Step 4 Call FND FLEXSQL from your Before Report Trigger to populate P_FLEXDATA SRW.REFERENCE(:P_STRUCT_NUM); SRW.USER_EXIT(’FND FLEXSQL CODE=”GL#” NUM=”:P_STRUCT_NUM” APPL_SHORT_NAME=”SQLGL” OUTPUT=”:P_FLEXDATA” MODE=”SELECT” DISPLAY=”ALL”’); Step 5 Define your report query Define your report query Q_1: SELECT &P_FLEXDATA C_FLEXDATA FROM CODE_COMBINATIONS_TABLE WHERE CODE_COMBINATIONS_TABLE.STRUCTURE_DEFINING_COLUMN = &P_STRUCT_NUM When the report runs, the call to FND FLEXSQL fills in the lexical parameters. As a result the second query would look something like: SELECT (SEGMENT1||’–’||SEGMENT2||’–’||SEGMENT3||’–’|| SEGMENT4) C_FLEXDATA FROM CODE_COMBINATIONS_TABLE WHERE CODE_COMBINATIONS_TABLE.STRUCTURE_DEFINING_COLUMN = 101 Step 6 Create formula columns Now create columns C_FLEXFIELD and C_DESC_ALL (and any others your report uses) corresponding to the values and descriptions displayed in the report. They all are in group G_1. Be sure to adjust the column width as appropriate for the value the column holds (such as a prompt, which might be as long as 30 characters). Step 7

35 Populate segment values formula column To retrieve the concatenated flexfield segment values and descriptions, you incorporate the AOL user exits in these columns. In the column definition of C_FLEXFIELD, you incorporate the FND FLEXIDVAL user exit call in the formula field. SRW.REFERENCE(:P_STRUCT_NUM); SRW.REFERENCE(:C_FLEXDATA); SRW.USER_EXIT(’FND FLEXIDVAL CODE=”GL#” NUM=”:P_STRUCT_NUM” APPL_SHORT_NAME=”SQLGL” DATA=”:C_FLEXDATA” VALUE=”:C_FLEXFIELD” DISPLAY=”ALL”’); RETURN(:C_FLEXFIELD); Step 8 Populate segment descriptions To populate the concatenated segment descriptions use DESCRIPTION=”C_DESC_ALL” instead of VALUE=”C_FLEXFIELD” as in the previous step. The user exit call becomes: SRW.REFERENCE(:P_STRUCT_NUM); SRW.REFERENCE(:C_FLEXDATA); SRW.USER_EXIT(’FND FLEXIDVAL CODE=”GL#” NUM=”:P_STRUCT_NUM” APPL_SHORT_NAME=”SQLGL” DATA=”:C_FLEXDATA” DESCRIPTION=”:C_DESC_ALL” DISPLAY=”ALL”’); RETURN(:C_DESC_ALL); You have created parameters and columns that are containers of all the values to be displayed. Now, in the following steps, you create the layout to display these values on the report. Step 9 Create your default report layout Use the Report Wizard to generate the default layout. Deselect C_FLEXDATA. Specify a ”Label” and a reasonable ”Width” for the columns you want to display. The table below lists the default layout column settings:

Oracle Reports takes you to the layout painter. Generate and run the report.

36 Note: For remaining Report Examples refer Oracle Applications Flexfields Guide SRW Packages SRW.BREAK Description This procedure temporarily stops report execution at the place at which SRW.BREAK was encountered, and displays (read-only) the current values of all columns and parameters. Report execution resumes when the read-only screen is accepted. Syntax SRW.BREAK; Restrictions This procedure is not meaningful in a Before Form or After Form trigger, because data for the report is not fetched until the Before Report trigger (which fires after the After Form trigger). n All column and parameter values are displayed in the read-only screen. No PL/SQL variables, or any other object values are displayed. SRW.CONTEXT_FAILURE Description This exception stops the report execution and raises the following error message: REP-1426: Running <construct_name> from incorrect context. Syntax SRW.CONTEXT_FAILURE; Usage Notes Report Builder raises this exception when a Report Builder packaged function or procedure is called in the wrong context (see the chart below). In this chart, NO means that the function or procedure cannot be called in that context; YES means it can.
Name srw.break Parameter Form Data Model NO YES Format Trigger YES Report Trigger NO

Example /* Suppose you want your own error message raised, Instead of the default error message. You could handle this exception in the following way: */ EXCEPTION When SRW.CONTEXT_FAILURE then Srw.message (4000, 'Contact the Application Development group regarding SRW.CONTEXT_FAILURE.'); Raise srw.program_abort;

37 SRW.DO_SQL Description This procedure executes the specified SQL statement from within Report Builder. The SQL statement can be DDL (statements that define data), or DML (statements that manipulate data). DML statements are usually faster when they are in PL/SQL, instead of in SRW.DO_SQL. Since you cannot perform DDL statements in PL/SQL, the SRW.DO_SQL packaged procedure is especially useful for performing them within Report Builder, instead of via a user exit. Syntax SRW.DO_SQL (sql_statement CHAR); Parameters sql_statement Is any valid SQL statement. Remember to precede any Report Builder object names with a colon (:). Example /* Suppose you want your report to create a table named CHECK just before the Runtime Parameter Form is displayed. Because CREATE TABLE is a SQL DDL statement (and PL/SQL cannot perform DDL statements), you need to use SRW.DO_SQL. Therefore, your PL/SQL could look like this in the Before Form trigger: Additional Information: If you use a table created in this way for your report output, the table must exist before you create your query in the data model. Otherwise, Report Builder would not be able to parse your query.*/ FUNCTION CREATETAB RETURN BOOLEAN IS BEGIN SRW.DO_SQL('CREATE TABLE CHECK (EMPNO NUMBER NOT NULL PRIMARY KEY, SAL NUMBER (10,2)) PCTFREE 5 PCTUSED 75'); RETURN(TRUE); EXCEPTION WHEN SRW.DO_SQL_FAILURE THEN SRW.MESSAGE(100, 'ERROR WHILE CREATING CHECK TABLE.'); SRW.MESSAGE(50, 'REPORT WAS STOPPED BEFORE THE RUNTIME PARAMETER FORM.'); RAISE SRW.PROGRAM_ABORT; END; /* Suppose you want to create a "table of contents" by getting the first character of a column's value, and page number on which its field fires to print. Assume that you want to put the "table of contents" into a table named SHIP. You could write the following construct:*/ DECLARE PAGE_NO NUMBER; PAGE_FOR INDEX NUMBER; SORT_CHAR CHAR(1); CMD_LINE CHAR(200); BEGIN SORT_CHAR := :SORT_NAME ; IF :CALLED = 'Y' THEN SRW.GET_PAGE_NUM(PAGE_FOR_INDEX); SRW.USER_EXIT('RWECOP PAGE_FOR_INDEX P_START_PAGENO');

38 SRW.MESSAGE(2,TO_CHAR(:P_START_PAGENO)); END IF; SRW.GET_PAGE_NUM(PAGE_NO); CMD_LINE := 'INSERT INTO SHIP VALUES ('''||SORT_CHAR||''','||TO_CHAR(PAGE_NO)||')'; SRW.MESSAGE(2,CMD_LINE); SRW.DO_SQL(CMD_LINE); COMMIT; EXCEPTION WHEN DUP_VAL_ON_INDEX THEN NULL; WHEN SRW.DO_SQL_FAILURE THEN SRW.MESSAGE(1,'FAILED TO INSERT ROW INTO SHIP TABLE'); WHEN OTHERS THEN COMMIT; END; SRW.DO_SQL_FAILURE Report Builder raises this exception when the SRW.DO_SQL packaged procedure fails (e.g., if the user does not have DDL privileges, yet tries to create a table with SRW.DO_SQL). This exception stops the report execution and raises the following error message: REP-1425: Error running DO_SQL package - REP-msg ORA-msg Where: REP-msg Is a Report Builder message. ORA-msg Is an optional ORACLE message, providing more information on the Report Builder message. Syntax SRW.DO_SQL_FAILURE; SRW.GET_PAGE_NUM This procedure returns the current page number. This is useful when you want to use the page number in the field's Format Trigger property. Syntax SRW.GET_PAGE_NUM (page_num); Parameters page_num Restrictions SRW.GET_PAGE_NUM is only meaningful in a format trigger. It has no effect when entered in other places. Example /* Suppose you want to perform a computation based upon a page number. In the field's Format Trigger, you could use SRW.GET_PAGE_NUM function:*/ Is the variable in which you want to place the current page number.

39 BEGIN DECLARE PAGE_NUM NUMBER; begin srw.get_page_num (page_num); srw.set_field_num (0, page_num + 3); end; END; SRW.MESSAGE Description This procedure displays a message with the message number and text that you specify. The message is displayed in the format below. After the message is raised and you accept it, the report execution will continue. MSG-msg_number: msg_text. Syntax SRW.MESSAGE (msg_number NUMBER, msg_text CHAR); Parameters msg_number Is a number from one to ten digits, to be displayed on the message line. Numbers less than five digits will be padded with zeros out to five digits. For example, if you specify 123, it will be displayed as SRW00123. Is at most 190 minus the msg_number alphanumeric characters to be displayed on the message line.

msg_text Restrictions •

You cannot trap nor change Report Builder error messages.

• SRW.MESSAGE does not terminate the report execution; if you want to terminate a report after raising a message, use SRW.PROGRAM_ABORT. • Any extra spaces in the message string will be displayed in the message; extra spaces are not removed by Report Builder. Example /* Suppose you have a user exit named MYEXIT to which you want to pass the values of the SAL column. Suppose, also, that you want to raise your own error if the user exit is not found (e.g., because it is not linked, compiled, etc.). To do these things, you could write the following PL/SQL in the Format Trigger of the F_SAL field: This trigger will raise your message as follows: MSG-1000: User exit MYEXIT failed. Call Karen Smith x3455. */ FUNCTION FOO RETURN BOOLEAN IS BEGIN Srw.reference (:SAL); Srw.user_exit ('myexit sal'); EXCEPTION When srw.unknown_user_exit then Srw.message (1000, 'User exit MYEXIT failed. Call Karen Smith x3455.'); Raise srw.program_abort; RETURN (TRUE);

40 END; SRW.PROGRAM_ABORT Description This exception stops the report execution and raises the following error SRW.PROGRAM_ABORT stops report execution when you raise it. message: REP-1419: PL/SQL program aborted. Syntax SRW.PROGRAM_ABORT; You must raise the exception from within your PL/SQL. Example /* Suppose you want to put a border around the salary if it is greater than 0. Suppose, also, that if the report fetches a salary less than 0, you want to raise a customized error message (i.e., "FOUND A NEGATIVE SALARY. . ."), then terminate the report execution. To do so, you could write the following format trigger for F_SAL.*/ FUNCTION foo return boolean is BEGIN if :sal >= 0 then srw.attr.mask := SRW.BORDERWIDTH_ATTR; srw.attr.borderwidth := 1; srw.set_attr (0, srw.attr); else Srw.message(100, 'FOUND A NEGATIVE SALARY. CHECK THE EMP TABLE.'); raise srw.program_abort; end if; RETURN (TRUE); END; SRW.REFERENCE Description This is useful when you want to ensure that a column value passed to a user exit is the most recently computed or fetched value, because this procedure causes Report Builder to add the referenced object to the PL/SQL construct's dependency list, thereby causing report Builder to determine the object's value just before firing the PL/SQL construct. Syntax SRW.REFERENCE (:object CHAR|DATE|NUMBER); Parameters :object Is the Report Builder parameter or column whose value needs to be ascertained before the construct fires.

SRW.RUN_REPORT

41 Description This procedure invokes RWRUN60 with the string that you specify. procedure is useful for: • • • • Syntax Parameters command_line Restrictions • If you want parameter values that are entered on the Runtime Parameter Form to be passed in the RWRUN60 string, you must call SRW.RUN_REPORT after the before form trigger. The string that is specified for or passed to this procedure must follow the syntax and case-sensitivity rules for your operating system. No userid should be specified for the SRW.RUN_REPORT procedure. The userid is inherited by the "calling" report. If the parent report that invokes SRW.RUN_REPORT is run in batch, then DESTYPE can only be File, Printer, Sysout, or Mail. Otherwise, DESTYPE can be File, Printer, or Mail. If SRW.RUN_REPORT is used in the PL/SQL for a button, the Runtime Parameter Form will not appear by default when the button is selected. If you want the Runtime Parameter Form to appear, you must specify PARAMFORM=YES in the call to SRW.RUN_REPORT. If you do not specify a path, Report Builder will use its file path search order to find the report. Is a valid RWRUN60 command. running drill-down reports (i.e., calling a report from a button's action trigger) sending parts of a report to different recipients (e.g., to send a report via e-mail to each manager with just his or her group's data) sending parts of a report to different printers (e.g., to send each manager's report to his or her printer) running multiple reports from a single "driver" report SRW.RUN_REPORT (command_line CHAR); This

• • •

Example /* Suppose you have the following two reports: MGR_RUN, which queries manager names, and invokes a second report named MAIL_IT , which queries employee names for the manager that MGR_RUN passes it, and sends the report output to the manager via e-mail. The description of MGR_RUN could be as follows: Query:

42 SELECT ENAME, EMPNO FROM EMP WHERE JOB='MANAGER' Group Filter: */ FUNCTION FOO RETURN BOOLEAN IS BEGIN srw.run_report('report=MAIL_IT desname='||:ename ||' desformat=dflt batch=yes mgr_no='|| TO_CHAR(:empno) ); RETURN (TRUE); EXCEPTION when srw.run_report_failure then srw.message(30, 'Error mailing reports.'); raise srw.program_abort; END; /* This PL/SQL invokes MAIL_IT, specifies that MAIL_IT's output should be sent to the manager via Oracle Mail, and passes the manager number, so that the MAIL_IT report can query only the manager's employees. Note: EMPNO's values must be converted to characters (TO_CHAR in the PL/SQL above), because SRW.RUN_REPORT requires a character string. Layout: None is needed, because this report only fetches data, then passes it to a second report. The description of MAIL_IT could be as follows: Query: SELECT DEPTNO, ENAME, SAL FROM EMP WHERE MGR=:MGR_NO Layout: Master/Detail */ /* Suppose that you have three reports that you almost always run together. The reports are named SALARY, COMMISS, and TAXES. To run these reports with one RWRUN60 command, you create a driver report named PAYROLL. The description of PAYROLL could be as follows: Query: SELECT DEPTNO FROM DEPT Before Report Trigger: */ FUNCTION FOO RETURN BOOLEAN IS BEGIN srw.run_report('batch=yes report=SALARY destype=file desformat=dflt desname=salary.lis'); srw.run_report('batch=yes report=COMMISS destype=file desformat=dflt desname=comiss.lis'); srw.run_report('batch=yes report=TAXES destype=file desformat=dflt desname=comiss.lis'); RETURN (TRUE); END; /* Layout: Tabular

43 When you run PAYROLL from the designer or RWRUN60, the other three reports will all be run. (Note that, in this case, the query and the layout for Payroll could be anything. They are only used here in order to make it possible to run PAYROLL.)*/ Matrix Reports A matrix (crosstab) report contains one row of labels, one column of labels, and information in a grid format that is related to the row and column labels. A distinguishing feature of matrix reports is that the number of columns is not known until the data is fetched from the database. To create a matrix report, you need at least four groups: one group must be a cross-product group, two of the groups must be within the cross-product group to furnish the "labels," and at least one group must provide the information to fill the cells. The groups can belong to a single query or to multiple queries.

Group G_JOB contains the column JOB, G_DEPT contains DEPTNO, G_SAL contains SUMSAL, and G_CROSS is the cross product group. Output look like this Dept Analyst Clerk 2450 2975 2850 Manager 5000 5600 President Salesman

10 1300 20 6000 1900 30 950 Product Order Property

The Product Order property is the order in which groups are evaluated in the cross product for a summary.

44 Product Order also defines the frequency of a summary, formula, or placeholder in a cross product group. That is, the summary, formula, or placeholder has one value for each combination of values of the groups in its Product Order. Product Order is used only for columns owned by cross-product groups. Because a cross product relates multiple groups, the groups in the cross product could be evaluated in any one of many different orders. Therefore, when creating a summary for a cross product, you must use Product Order to specify for Report Builder which group should be evaluated first, which second, and so on. You must also use Product Order to specify the frequency of a summary, formula, or placeholder within the cross product. Values Applies to Required/Optional Example Product Order example (formula) Suppose that you have a matrix report that looks something like the one below and you want to add a formula to it. Dept 10 20 30 Analyst 6000 1900 950 Clerk 1300 2450 2975 2850 Manager 5000 5600 President Salesman A valid group combination. summary, formula, and placeholder columns required, if the column is a summary or formula column belonging to a cross product group.

Group G_JOB contains the column JOB, G_DEPT contains DEPTNO, G_SAL contains SUMSAL, and G_CROSS is the cross product group. To add a formula that calculates the sum of after-tax salaries for each department, you first create a summary column (DEPTSUM) in G_CROSS with the following settings: Function % of Total Reset At G_DEPT Product Order G_DEPT

Next, you create a formula (AFTERTAX) in G_CROSS with the following settings: Formula Product Order :deptsum * .9 G_DEPT Because the formula is in G_CROSS, you must give it a Product Order. In this case, the frequency of the formula is the same as the summary column, DEPTSUM. This would calculate the formula as follows: Dept 10 20 Analyst 6000 1900 Clerk 1300 2975 Manager 2450 President 5000 9788 Salesman Comp 7875

45 30 950 2850 5600 8460

Anchors
Anchors are used to determine the vertical and horizontal positioning of a child object relative to its parent. • Since the size of some layout objects may change when the report runs (and data is actually fetched), you need anchors to define where you want objects to appear relative to one another. An anchor defines the relative position of an object to the object to which it is anchored. Positioning is based on the size of the objects after the data has been fetched rather than on their size in the editor. It should also be noted that the position of the object in the Layout editor effects the final position in the report output. Any physical offset in the layout is incorporated into the percentage position specified in the Anchor property sheet.

• •