Monday, February 20, 2023

Peoplecode to zip/archive files

Following is a way to archive, compress or zip up files via peoplecode. Alternative would be to use command line calls to products like winzip, 7-zip etc. For this test I am running PT 8.59.x. The same should also be possible in slightly older Peopletools releases too, like PT 8.56.x

Oracle provides java classes that can be used for this task. This method will create a new archive file and add files to the root location of the archive or zip file. 

The solution uses the following three java classes that are delivered with PeopleTools

1. java.io.FileOutputStream

2. java.util.zip.ZipOutputStream

3. java.util.zip.ZipEntry


/* initialize Java Obejct &myArchive */
Local JavaObject &myArchive = CreateJavaObject("java.util.zip.ZipOutputStream", CreateJavaObject("java.io.FileOutputStream", &zipFileName, True));

In the above line of code &zipFileName is the complete path of the archive file that we will create.

&fileNametoAdd - will have the complete path to the file that we will be adding to the archive. 

In order to get the filename value from the file path do the following.

&FilePath = Split(&fileNametoAdd, "\");
&fname = &FilePath [&FilePath.Len];

Local JavaObject &ArchiveEntry = CreateJavaObject("java.util.zip.ZipEntry", &fname);

/* Add Archive entry to OutputStream */
&myArchive.putNextEntry(&ArchiveEntry);

/* now add the file to the archive */
/* Read source file into input stream */
Local JavaObject &in = CreateJavaObject("java.io.FileInputStream", &fileNametoAdd);

/* Java Array that will read bytes from input file */
Local JavaObject &filebuffer = CreateJavaArray("byte[]", 1024);
Local number &byteCount = &in.read(&filebuffer);
   
/* Read bytes from input file and load it byte array  - Do until all bytes are read*/
While &byteCount > 0
      /* Write Bytes of Data to corresponding Archive Output Stream */
      &myArchive.write(&filebuffer, 0, &byteCount);
      &byteCount = &in.read(&filebuffer);
End-While;
   
/* Close input stream */
&in.close();

/* Close archive */
&myArchive.close();

Friday, February 17, 2023

Securing PDF

Following is a way to secure pdf files generated via non-BI Publisher technology like SQR. For this test I am running PT 8.59.x. Should be available in slightly older Peopletools releases too, like PT 8.56.x

Oracle provides java classes that can be used for securing a pdf file. This method will add a password to the pdf file, so that a password is prompted to the user while opening the pdf as well as adds a digital signature to the pdf. This class does both so if the requirement is to only password protect a pdf file, we still have to add a signature but make it small or invisible. 

This method also requires a digital certificate signed by one of the approved adobe certificate authorities called as AATL. The certificate has to be pfx format (can be converted using tools like openssl). If a self-signed certificate is used, the process still works but the end user will receive a warning banner in adobe reader once the document is opened and will have to manually trust the certificate by adding it to the adbobe trust store. 

The solution uses two java classes that are delivered with PeopleTools

1. java.util.Properties

2. oracle.xdo.common.pdf.signature.PDFSignature


Local JavaObject &jProp = CreateJavaObject("java.util.Properties");

&jProp.setProperty("signature-enable", "True");
&jProp.setProperty("pdf-security", "True");
&jProp.setProperty("pdf-open-password", &EncryptPswd);
&jProp.setProperty("pdf-permissions-password", &EncryptPswd);
&jProp.setProperty("pdf-changes-allowed", "0");

&EncryptPswd is the password that will be used to open the pdf file. 

&inFile is the complete path to the source pdf file and &outFile is the complete path of the secured pdf file. 

Local JavaObject &pdfSignature = CreateJavaObject("oracle.xdo.common.pdf.signature.PDFSignature", &inFile, &outFile);
   
&pdfSignature.setConfig(&jProp);
&pdfSignature.setLocale("en");

&digPswd is the password of the pfx digitial certificate file and &digSign is the complete path to the pfx file. Make sure the paths use "//" insread of "/" or "\\" instead of "\".

&pdfSignature.init(&digPswd, &digSign);

Following plots the signature in the pdf file. If a signature is not needed then make it small or invisible. Adjust the values as required. 
&xCord = 0;
&yCord = 0;
&width = 0;
&height = 0;
&pageIndex = 1;
&sReason can be some text or blank if none is required.
      
Local JavaObject &jFloatArray = CreateJavaObject("float[]", &xCord, &yCord, &width, &height);
&pdfSignature.addSignatureField(&pageIndex, &jFloatArray, "PSoftSign");
&pdfSignature.sign("PSoftSign", &sReason);
&pdfSignature.cleanup();

clean-up memory once done.
&jProp = Null;
&pdfSignature = Null;
&jFloatArray = Null;

/* delete the un-encrypted file */
Local object &delFile = CreateJavaObject("java.io.File", &inFile);
&delFile.delete();


Friday, February 3, 2023

PS Query - Employee Photo

There are couple of options to include images in query output. In this example I am displaying employee pictures which are stored in the database (under the identification data component). I am running PT 8.59.x on HCM 9.2.

The simplest method is to include the table EMPL_PHOTO in the query and join the EMPLID field and display the EMPLOYEE_PHOTO field. On the query properties select "Image Data" that way the image is displayed in the output.

The EMPL_PHOTO table has a field called as PHOTO_SIZENAME and stores each image in 4 different sizes, CARD, LIST, ORCH and PAGE. Hence it is advisble to add a condition/filter to select the appropriate size. In my case I am filtering based on LIST.

The other option is to use drilling URL expression type. 

In this scenario we have to build two queries. The first query will query data from EMPL_PHOTO table and the query properties have to set to "Image Huperlink".

The second query will include EMPL_PHOTO and other tables. Add an expression of type "Drilling URL" and select "Image URL"


In the next dialog box, provide the details of the first query and verify the two key fields EMPLID and PHOTO_SIZENAME are peopulated correctly. The field PHOTO_SIZENAME has to be in the "field list" so will be displayed in the result. So while defining the Image URL you can map the result to this field. This way the crypting URL (expression) need not be displayed as a field in the result but the values in the PHOTO_SIZENAME column will appear hyperlinked. Clicking on this field will display the image.   





Sunday, February 6, 2022

Displaying/exporting PeopleSoft image/picture files

There isn't a good way to display/export images or picture files deliverd by PeopleSoft. Some smaller images can be viewed via Application Designer but not the ones that are used on fluid tiles. So wrote this small routine to view the images online as well as create a file with the same information which can be shared with the team.

For this POC running PT 8.58.x, HCM 9.2

Created a SQL object N_IMAGES_SQL, selecting image name and version from the PSCONTDEFN table. Selecting only SVG files as those are the ones generally used on fluid tiles. 











Created a page and added a long field of the type HTML Area to the page. 

N_TEST_WRK.HTMLAREA in the code below is that field.

So displaying the images returned by the SQL on the online page along with the image name. When this happens the images are also written to the web server cache folder. So created another string with path to the physical files in the web server cache folder and created an html file. Via a browser opened this html file and saved it as a pdf which can now be shared with the team.   

Complete peoplecode below




Output




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