Wednesday, October 20, 2021

Generating excel output with multiple sheets using RTF Template

So as the title suggests, in this exercise I am testing PeopleSoft's BI Publisher reporting engine to output an excel file, while using a RTF template. In addition to producing the output in excel format, I have to split the result into multiple sheets within the same excel workbook. So lets get started.

For this POC I am using Oracle BI Publisher Desktop 12.2.1.4.0. 

I am displaying a simple table with two columns on each sheet within the workbook. In order to name the sheet within the workbook I am using the following form field tag

<?spreadsheet-sheet-name: {.//N_SHEET_NAME}?> where N_SHEET_NAME is a data element in my XML data source.

My XML data source is structured as shown below.




 












In my RTF template, I have the following two tables separated by a page break. So the first table is on page 1 of the RTF file and the second table is on page 2.





Table 1 form field definitions have been defined as below.

F = <?for-each:N_PERSON_DATA?> 

E = <?end for-each?>

Below the table I have defined the following tags.

<?for-each-group:N_PERSON;./N_SHEET_NAME?>

<?spreadsheet-sheet-name: {.//N_SHEET_NAME}?>

<?end for-each-group?>

After this there is page-break which was created by Ctrl + Enter.

Table 2 follows a similar construct as explained below.

F = <?for-each:N_ADDRESS_DATA?>

E = <?end for-each-group?>

<?for-each-group:N_ADDRESS;./N_SHEET_NAME?>

<?spreadsheet-sheet-name: {.//N_SHEET_NAME}?>

<?end for-each-group?>

Excel output below.

Sheet 1






Sheet 2







Saturday, April 17, 2021

Composite Query

Composite Query enables us to combine data from existing queries and then apply filters, aggregates, and so on before presenting the report results, which show the combined data set. Composite Query retrieves multiple levels of related information on existing queries and presents the combined data as a single and flattened query result. There is good amount of info on how these work, limitation etc so I am not going to cover those here. I found them pretty useful to create inline SQL or query which isn't  possible via the regular PS Query (Query Manager) or even via Connected query feature in PeopleSoft.

So for this POC I am running PT 8.58.05 on HCM 9.2 (PUM 35). The SQL or output that I am trying to re-produce is as follows. 

I am listing employees from PS_JOB but I want to list their min ORIG_HIRE_DT value regardless of their current relationship in the orignatization. 

So I created two simple queries in Query Manager as follows.

Parent_Query

SELECT A.EMPLID, A.EMPL_RCD, (CONVERT(CHAR(10),A.EFFDT,121)), A.EFFSEQ,  (CONVERT(CHAR(10),A.LAST_HIRE_DT,121))
  FROM PS_JOB A, PS_EMPLMT_SRCH_QRY A1
  WHERE ( A.EMPLID = A1.EMPLID
    AND A.EMPL_RCD = A1.EMPL_RCD
    AND A1.OPRID = 'PS'
    AND ( A.EFFDT =
        (SELECT MAX(A_ED.EFFDT) FROM PS_JOB A_ED
        WHERE A.EMPLID = A_ED.EMPLID
          AND A.EMPL_RCD = A_ED.EMPL_RCD
          AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10))
    AND A.EFFSEQ =
        (SELECT MAX(A_ES.EFFSEQ) FROM PS_JOB A_ES
        WHERE A.EMPLID = A_ES.EMPLID
          AND A.EMPL_RCD = A_ES.EMPL_RCD
          AND A.EFFDT = A_ES.EFFDT) ))


Inline_Query 

SELECT A.EMPLID, A.ORG_INSTANCE_ERN, MIN( (CONVERT(CHAR(10),A.ORIG_HIRE_DT,121)))
  FROM PS_PER_ORG_INST A, PS_PERS_SRCH_QRY A1
  WHERE ( A.EMPLID = A1.EMPLID
    AND A1.OPRID = 'PS')
  GROUP BY  A.EMPLID,  A.ORG_INSTANCE_ERN

Navigated to Reporting Tools > Composite Query > Composite Query Manager and stepped through the wizard.

1. Gave a name to the composite query

2. Provided the Query 1 and Query values. So in my case Query 1 = Parent_Query and Query 2 = Inline_Query. Unfortunately we cannot have more than one inline SQLs, so this looks like a limitation.




3.   Sepcified Query Joins as shown below.


4. On the Output fields page I made the selections as shown below.



5.  On the final page set the status as active and saved the page.



Hovering over the gear icon next to the SQL button presents the option to Run/Preview the data or ouput.




Saturday, April 3, 2021

Application Engine Plug-ins

PeopleTools provides a feature where in we can alter the SQL or PeopleCode actions of any Application Engine program, without customizing the delivered AE program. The configured plug-in action is executed at runtime. This effectively allows us to modify the code without actually customizing or re-designing the Application Engine program.

Configure the selected SQL or PeopleCode action of the Application Engine program by adding new SQL, PeopleCode, or both and/or by replacing the existing SQL or PeopleCode action through PIA in the AE Action Plugin page (PeopleTools, Application Engine).

Note: You can add or replace only SQL and PeopleCode actions in the Application Engine program. Only sections with steps having SQL or PeopleCode actions of the Application Engine program, which you plan to configure, will be displayed in PIA. This feature is not designed to add new sections or steps to an existing Application Engine program.

Actions belonging to the same step of the same section of the Application Engine program can have multiple plug-in actions defined. The plug-in action type does not have to match the action type that is selected for configuration. You can re-use the same SQL or PeopleCode plug-in action multiple times for different Application Engine programs.

The Application Engine action that is being configured cannot be used as a plug-in to configure another Application Engine program. Also, you cannot define a plug-in for the Application Engine action that is already been used as a plug-in.

For example, if Application Engine program A action Y is configured to use Application Engine program B action X as a plug-in, then Application Engine program A action Y cannot be used as a plug-in for any other Application Engine program. Also, you cannot configure a plug-in for Application Engine program B action X.

For the following test I am running PT 8.58.05, HCM 9.2 on PUM 35.

So AEMINITEST is my delivered program and then I created another standard AE program called as N_PLUGIN. My custom AE just has one step with action as peoplecode under MAIN. I have enbled disable restart under object properties of my custom AE.


In my custom peoplecode action I have the following code.



The delivered AE AEMINITEST has 2 steps under MAIN, first one is a SQL and then second one is peoplecode. I added a line of text to the peoplecode to understand the flow (obvisously this is not necessary).


Next logged into PIA and navigated to PeopleTools > Application Engine > AE Action Plugin and pulled up AEMINITEST.

I tried the following 4 tests.

1. Run my peoplecode action after AEMINITEST's peoplecode 


Value of variable TEST in AEMINITEST is 2 (0,0)

Value of variable TEST in N_PLUGIN is 20 (0,0)
Application Engine program AEMINITEST ended normally

Here I tried if I can display the value of the variable in my N_PLUGIN prgram which is set in the parent AEMINITEST program. This would work only if the variable is declared as global or component, not as local or if its auto declared. Similarly values from AET records could possibly be shared.   


2. Run my peoplecode action before AEMINITEST's peoplecode


Value of variable TEST in N_PLUGIN is 20 (0,0)

Value of variable TEST in AEMINITEST is 2 (0,0)
Application Engine program AEMINITEST ended normally


3. Run my peoplecode action replacing AEMINITEST's peoplecode


Value of variable TEST in N_PLUGIN is 20 (0,0)
Application Engine program AEMINITEST ended normally


4. Replace AEMINITEST's SQL with my peoplecode action



Value of variable TEST in N_PLUGIN is 20 (0,0)

Value of variable TEST in AEMINITEST is 2 (0,0)
Application Engine program AEMINITEST ended normally


So this is a great feature and will definitely assist when customizing Application Engine programs.


Saturday, January 16, 2021

XMLP BI Publisher sub-templates

Recently was presented with this challenge which turned out to be good enough exercise and hence warranted this post. Request was to display appropriate logo in the report header based on data available in the source XML file. 

For this exercise I am running PT 8.58.05 and BI Publisher 12.2.1.4.0 and rtf templates. My main report is called parent.rtf, sub-template is called headers.rtf and data source xml file is data.xml. The goal is to print or display the appropriate logo in the final report based on the data value provided in the XML file. 

In the main report, under MS Word's heading section added the following code. This is in regular text and not in any form field. Instead of choose (which works like peoplecode evaluate) I could have also used "If - Then - Else", but I wanted to try how "choose" works in XMLP.

<?import:file:C:///temp/headers.rtf?>
<?choose:?>
<?when:logo='Oracle'?>
    <?call:Oracle?>
<?end when?>
<?when:logo='Microsoft'?>
    <?call:Microsoft?>
<?end when?>
<?when:logo='Apple'?>
    <?call:Apple?>
<?end when?>
<?otherwise:?>
    <?call:Default?>
<?end otherwise?>
<?end choose:?>  

While testing this rtf locally or via Template Viewer the following import command will work, provided the headers.rtf file is available under c:\temp folder.

<?import:file:C:///temp/headers.rtf?>

But once we are ready to deploy and run this in the PIA environment, the line has to be changed as shown below. Here "STDHEADER" is the name provided while creating/uploading the headers rtf template in PIA under content library.
 
<?import:psxmlp://STDHEADER?>

In the headers.rtf I have defined the various headers as shown below. The XML tags are in regular text and not form fields.

<?template:Oracle?>
Oracle image was added here.
<?end template?>

<?template:Microsoft?>
Microsoft image was added here.
<?end template?>

<?template:Apple?>
Apple image was added here.
<?end template?>

<?template:Default?>
A default image was added here.
<?end template?>

My data source data.xml has the following structure where in I have the value for the logo to be used.

<?xml version="1.0" encoding="UTF-8"?>
<Start>
   <Heading>
      <logo>Apple</logo>
   </Heading>
   <ReportData>
      ...
   </ReportData>
</Start>

If you are receiving errors while testing this solution locally then the following has to be done. Under your local workstation install of the BI Publisher plugin you will have to modify the xdo.cfg file and add the following line under the properties section.
if no xdo.cfg file exists then make a copy of xdo example.cfg as xdo.cfg and add the line. This property is available in Template Viewer, so you can just set it there if testing via template viewer.

<property name="xdk-secure-io-mode">false</property>

That's it works like a charm.