Hello All
Hope you all are doing well :)
This post is about exporting view object data in a pdf file directly from af:table , export to excel is built in feature of ADF but exporting data in PDF requires little bit of extra effort
So here for this requirement I am using Apache PDFBox library , previously I have posted about using this API to create PDF file from text data
I know many of you will not visit that link ;) So a quick overview
The Apache PDFBox library is an open source Java tool for working with PDF documents. This project allows creation of new PDF documents, manipulation of existing documents and the ability to extract content from documents. Apache PDFBox also includes several command line utilities.
Let's implement this
All Done :) Now run and check application
Sample ADF Application (Jdeveloper 12.1.3)- Download
Cheers :) Happy Learning
Hope you all are doing well :)
This post is about exporting view object data in a pdf file directly from af:table , export to excel is built in feature of ADF but exporting data in PDF requires little bit of extra effort
So here for this requirement I am using Apache PDFBox library , previously I have posted about using this API to create PDF file from text data
I know many of you will not visit that link ;) So a quick overview
What is Apache PDFBox
The Apache PDFBox library is an open source Java tool for working with PDF documents. This project allows creation of new PDF documents, manipulation of existing documents and the ability to extract content from documents. Apache PDFBox also includes several command line utilities.
Let's implement this
- Create a Fusion Web Application and prepare model using Departments table of HR Schema
- Add PDFBox jar to view controller project
- Drop Departments view object as table on page and add two buttons to Export All Rows and Export Selected Row
- Now see the managed bean code that exports viewObject data to PDF file , Idea is to add viewObject data in a multi dimensional array and then iterate over array to draw a table in pdf Go through the comments to understand code part
Packages and Helper method-
import java.io.IOException; import javax.faces.event.ActionEvent; import oracle.adf.model.BindingContext; import oracle.adf.model.binding.DCIteratorBinding; import oracle.binding.BindingContainer; import oracle.jbo.Row; import oracle.jbo.RowSetIterator; import oracle.jbo.ViewObject; import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType1Font;
/** * Generic Method to call operation binding**/ public BindingContainer getBindingsCont() { return BindingContext.getCurrent().getCurrentBindingsEntry(); }
Method to Export All Rows of ViewObject to PDF-
/**Method to export all rows of viewObject to PDF * @param actionEvent * @throws IOException */ public void exportAllRowsToPdfAction(ActionEvent actionEvent) throws IOException { //Create new PDF Document PDDocument document = new PDDocument(); PDPage page = new PDPage(); document.addPage(page); PDPageContentStream contentStream = new PDPageContentStream(document, page); //Get the iterator of af:table on page DCIteratorBinding iter = (DCIteratorBinding) getBindingsCont().get("DepartmentsVO1Iterator"); //No of total rows+ 1 for array sizing int totRows = ((int) iter.getEstimatedRowCount()) + 1; //Here 4 is the number of columns String[][] content = new String[totRows][4]; int column = 4; //Set header text in first row of table in PDF content[0][0] = "Department Id"; content[0][1] = "Department Name"; content[0][2] = "Manager Id"; content[0][3] = "Location Id"; //Get viewObject from iterator and Iterate over it to add all data in array ViewObject vo = iter.getViewObject(); RowSetIterator rsi = vo.createRowSetIterator(null); int i = 1; while (rsi.hasNext()) { Row nextRow = rsi.next(); for (int j = 0; j < column; j++) { System.out.println(i + "" + j); if (j == 0 && nextRow.getAttribute("DepartmentId") != null) { content[i][j] = nextRow.getAttribute("DepartmentId").toString(); } if (j == 1 && nextRow.getAttribute("DepartmentName") != null) { content[i][j] = nextRow.getAttribute("DepartmentName").toString(); } if (j == 2 && nextRow.getAttribute("ManagerId") != null) { content[i][j] = nextRow.getAttribute("ManagerId").toString(); } if (j == 3 && nextRow.getAttribute("LocationId") != null) { content[i][j] = nextRow.getAttribute("LocationId").toString(); } } i++; } rsi.closeRowSetIterator(); //Write data to PDF writeToPdf(contentStream, content); contentStream.close(); try { //Save generated pdf document in a drive document.save("D:\\Departments.pdf"); } catch (COSVisitorException e) { } }
Method to Export Selected Row of ViewObject to PDF-
/**Method to export selected row to PDF * @param actionEvent * @throws IOException */ public void exportCurRowToPdfAction(ActionEvent actionEvent) throws IOException { //Create new PDF Document PDDocument document = new PDDocument(); PDPage page = new PDPage(); document.addPage(page); PDPageContentStream contentStream = new PDPageContentStream(document, page); //Get the iterator of af:table on page DCIteratorBinding iter = (DCIteratorBinding) getBindingsCont().get("DepartmentsVO1Iterator"); //Define the array for two rows only String[][] data = new String[2][4]; //Set header text in first row of table in PDF data[0][0] = "Department Id"; data[0][1] = "Department Name"; data[0][2] = "Manager Id"; data[0][3] = "Location Id"; //Get current row of Iterator and insert data in array Row row = iter.getCurrentRow(); if (row.getAttribute("DepartmentId") != null) { data[1][0] = row.getAttribute("DepartmentId").toString(); } if (row.getAttribute("DepartmentName") != null) { data[1][1] = row.getAttribute("DepartmentName").toString(); } if (row.getAttribute("ManagerId") != null) { data[1][2] = row.getAttribute("ManagerId").toString(); } if (row.getAttribute("LocationId") != null) { data[1][3] = row.getAttribute("LocationId").toString(); } //Write data to PDF writeToPdf(contentStream, data); contentStream.close(); try { //Save generated pdf document in a drive document.save("D:\\Departments.pdf"); } catch (COSVisitorException e) { } }
Method to draw table in PDF -
/**Method to draw table on pdf using array of data * @param page * @param contentStream * @param y * @param margin * @param content * @throws IOException */ public static void writeToPdf(PDPageContentStream contentStream, String[][] data) throws IOException { final int rows = data.length; final int cols = data[0].length; //Height for each row final float rowHeight = 20f; //Width of table drawn final float tableWidth = 550; //Total table height final float tableHeight = rowHeight * rows; //Width of each column final float colWidth = tableWidth / (float) cols; final float cellMargin = 5f; //Margin from left float margin = 20; //Margin from top (Increase value to decrease margin) float y = 750; //draw the rows float anoy = y; for (int i = 0; i <= rows; i++) { contentStream.drawLine(margin, anoy, margin + tableWidth, anoy); anoy -= rowHeight; } //Draw the columns float anox = margin; for (int i = 0; i <= cols; i++) { contentStream.drawLine(anox, y, anox, y - tableHeight); anox += colWidth; } //Setting for font and size contentStream.setFont(PDType1Font.COURIER_BOLD, 10); float textx = margin + cellMargin; float texty = y - 15; for (int i = 0; i < data.length; i++) { for (int j = 0; j < data[i].length; j++) { if (data[i][j] != null) { String text = data[i][j]; contentStream.beginText(); contentStream.moveTextPositionByAmount(textx, texty); contentStream.drawString(text); contentStream.endText(); textx += colWidth; } } texty -= rowHeight; textx = margin + cellMargin; } }
All Done :) Now run and check application
Sample ADF Application (Jdeveloper 12.1.3)- Download
Cheers :) Happy Learning
This is terribly inefficient. It will take a very long time to create detailed pdf which includes multiple view objects with and without master-child relationships. Instead of this, I strongly recommend using Oracle Bi Desktop Publisher libraries instead of pdfbox, creating java class to convert view objects to xml, and pass that xml to the Publisher libraries. Then all you need to do is draw .rtf template in word and pass it as input to Publisher as well. I can provide example if you want.
ReplyDeleteThis is for a single viewObject , If you need to create detailed report then you can use any report tool like jasper and call that in application using integration libraries or the way you suggested above :)
DeleteThanks a lot....Without your posting definitely face problems in our development.
ReplyDelete