Search code examples
primefacespdf-generationprimefaces-dataexporter

Primefaces DataExporter Set Table Columns Width


I have a Primefaces DataGrid that I export whith Primefaces DataExporter but I can't figure out how to resize the columns.

I added a preporcessor

<p:dataExporter type="pdf" target="tbl" fileName="cars" preProcessor="#{customizedDocumentsView.preProcessPDF}" />

And this is the code in my bean

public void preProcessPDF(Object document) {
        Document pdf = (Document) document;
        pdf.open();
        pdf.setPageSize(PageSize.A4);

        //I need to do something like that
        //PdfPTable table = new PdfPTable(4);
        //float[] columnWidths = new float[] {10f, 20f, 30f, 10f};
        //table.setWidths(columnWidths);
    } 

Is there any way to do this ?


Solution

  • Recently I inherited project with many already existing exporters with already set options tags so I needed to find solution that will keep all of them intact.

    I got an idea from this accepted answer.

    My solution sets column widths via options tag of p:dataExporter so there is no need for pre/post processing. I tested it using Primefaces ver 4.x and up.

    Step by step procedure:

    1. Create new package org.primefaces.component.export inside your project.

    2. From Primefaces git repository fully copy following classes ExporterOptions ,PDFOptions, Exportedfactory and PDFExporter into newly created package.

    3. In ExporterOptions add public float[] getColumnWidths();

    4. In PDFOptions add float[] columnWidths; and add getter and setter.

    5. In ExporterFactory modify line exporter = new PdfExporter(); to exporter = new CustomPdfExporter();

    6. Rename PDFExporter class to CustomPDFExporter and keep just following export method fully

      public void export(FacesContext context, DataTable table, String filename, boolean pageOnly, boolean selectionOnly, String encodingType,MethodExpression preProcessor, MethodExpression postProcessor, ExporterOptions options) throws IOException
      

    Delete code from other export methods but keep declarations.

    1. Inside CustomPDFExporter add 2 lines in ExportPdfTable method

      protected PdfPTable exportPDFTable(FacesContext context, DataTable table, boolean pageOnly, boolean selectionOnly, String encoding) throws DocumentException {
         int columnsCount = getColumnsCount(table);
         PdfPTable pdfTable = new PdfPTable(columnsCount);
         this.cellFont = FontFactory.getFont(FontFactory.TIMES, encoding);
         this.facetFont = FontFactory.getFont(FontFactory.TIMES, encoding, Font.DEFAULTSIZE, Font.BOLD);
      
          if (this.expOptions != null) {
              applyFacetOptions(this.expOptions);
              applyCellOptions(this.expOptions);
              //line 1
              //sets columns column relative widths to iText PdfTable object
              pdfTable.setWidths(this.expOptions.getColumnWidths());
              //line 2
              //decreases page margins comparing to original 'Primefaces' layout
              pdfTable.setWidthPercentage(100);
          }
      
          //....
      

      }

    2. Now you are ready to go managed bean and add pdf option. For example

      pdfOpt = new PDFOptions(); //add getter and setter too
      pdfOpt.setFacetBgColor("#F88017");
      ...
      //if, for example, your PDF table has 4 columns
      //1st column will occupy 10% of table's horizontal width,...3rd - 20%, 4th - 60% 
      float[] columnWidths = new float[]{0.1f, 0.1f, 0.2f, 0.6f};
      pdfOpt.setColumnWidths(columnWidths);
      ...
      
    3. Finally your p:dataExporter component should look like this

      <p:dataExporter type="pdf" target="tbl" fileName="cars" options="#{customizedDocumentsView.pdfOpt}"/>
      

    This solution using PF showcase produces following result enter image description here

    Suggestion for extending this solution:

    Primefaces exporter uses iText ver 2.1.7. with old but still powerful API. For example, in ExporterOptions in step 1. you can add

    public int[] getColumnWidths();
    

    to set absolute column widths or you can set any other option driven by your project requirements.