Primefaces 12 中的 DataExporter 不导出 PDF 中的表标题

问题描述 投票:0回答:1

我正在使用 Primefaces 12,并且我知道在版本 12 中,dataExporter 存在一个问题,即在尝试下载文件时不包含表头。 这就是问题

我已经编写了一个后处理器来将它们包含在“xls”文件中,但我也需要帮助才能将它们应用于“pdf”文件。由于某些问题,我无法升级到 primefaces 13。

jsf primefaces primefaces-dataexporter
1个回答
0
投票

遇到此问题的用户可以尝试以下方法:

在 faces-config.xml 中添加以下内容(将 xxx 替换为类所在的包名称):

<managed-bean>
    <managed-bean-name>customExcelExporter</managed-bean-name>
    <managed-bean-class>xxx.xxx.xxx.CustomExcelExporter</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

<managed-bean>
    <managed-bean-name>customPDFExporter</managed-bean-name>
    <managed-bean-class>xxx.xxx.xxx.CustomPDFExporter</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

在 pom.xml 中添加 iText 依赖项:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.2</version> <!-- Ensure compatibility with your project -->
</dependency>

创建两个类,CustomPDFExporter 和 CustomExcelExporter:

自定义PDF导出器:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.invoke.MethodHandles;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.primefaces.component.api.UIColumn;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.component.export.ExportConfiguration;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class CustomPDFExporter extends org.primefaces.component.datatable.export.DataTableExporter {
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    @Override
    protected void exportCells(DataTable table, Object document) {
        PdfPTable pdfTable = (PdfPTable) document;
        FacesContext context = FacesContext.getCurrentInstance();

        // Exportar las filas visibles de la tabla
        for (int i = 0; i < table.getRowCount(); i++) {
            table.setRowIndex(i);

            if (!table.isRowAvailable()) {
                continue;
            }

            // Recorrer todas las columnas visibles y exportables de la tabla
            for (UIColumn column : table.getColumns()) {
                if (column.isRendered() && column.isExportable()) {
                    List<UIComponent> components = column.getChildren();
                    StringBuilder exportedValue = new StringBuilder();

                    // Exportar el valor de la columna utilizando el método exportColumn
                    exportColumn(context, table, column, components, true, exportedValue::append);

                    // Se pone texto vacio si sale el texto "null"
                    String exprtdValue = exportedValue.toString();
                    if ("null".equals(exportedValue.toString())) {
                        exprtdValue = "";
                    }

                    // Añadir el valor de la celda al contenido PDF
                    PdfPCell cell = new PdfPCell(new Phrase(exprtdValue, FontFactory.getFont(FontFactory.HELVETICA, 10)));
                    pdfTable.addCell(cell);
                }
            }
        }

        // Restablecer el índice de fila después de la exportación
        table.setRowIndex(-1);
    }

    @Override
    protected void doExport(FacesContext facesContext, DataTable table, ExportConfiguration exportConfiguration,
                            int index) throws IOException {
        LOGGER.debug("Empezando la exportacion de PDF...");

        // Crear el documento PDF
        Document document = new Document(PageSize.A4);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            PdfWriter.getInstance(document, baos);
            document.open();

            // Crear tabla PDF con el número de columnas de la tabla de datos
            int columnCount = table.getColumns().stream().filter(UIColumn::isExportable).toArray().length;
            PdfPTable pdfTable = new PdfPTable(columnCount);
            pdfTable.setWidthPercentage(100);
            pdfTable.setSpacingBefore(10f);
            pdfTable.setSpacingAfter(10f);

            // Añadir las cabeceras antes de los datos
            addColumnHeaders(table, pdfTable);

            // Exportar los datos de la tabla
            exportCells(table, pdfTable);

            // Añadir la tabla al documento
            document.add(pdfTable);
        } catch (DocumentException e) {
            throw new IOException(e);
        } finally {
            document.close();
        }

        // Convertir el contenido a un StreamedContent
        InputStream bais = new ByteArrayInputStream(baos.toByteArray());
        StreamedContent pdfFile = DefaultStreamedContent.builder()
                .stream(() -> bais)
                .contentType("application/pdf")
                .name("export.pdf")
                .build();

        InputStream inputStream = pdfFile.getStream().get();
        OutputStream outputStream = facesContext.getExternalContext().getResponseOutputStream();

        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }

        inputStream.close();
        outputStream.flush();

        LOGGER.debug("Exportacion de PDF finalizada!");
    }

    @Override
    public String getContentType() {
        return "application/pdf";
    }

    @Override
    public String getFileExtension() {
        return ".pdf";
    }

    // Método para añadir las cabeceras de columna visibles a la tabla PDF
    private void addColumnHeaders(DataTable table, PdfPTable pdfTable) {
        Font headerFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12);
        for (UIColumn column : table.getColumns()) {
            if (column.isRendered() && column.isExportable()) {
                String headerText = column.getHeaderText();

                if (headerText == null || headerText.isEmpty()) {
                    UIComponent facet = column.getFacet("header");
                    if (facet != null) {
                        headerText = facet.toString();
                    }
                }

                PdfPCell headerCell = new PdfPCell(new Phrase(headerText, headerFont));
                headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                pdfTable.addCell(headerCell);
            }
        }
    }
}

自定义Excel导出器:

import java.io.IOException;
import java.io.OutputStream;
import java.lang.invoke.MethodHandles;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.primefaces.component.api.UIColumn;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.component.export.ExportConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomExcelExporter extends org.primefaces.component.datatable.export.DataTableExporter {
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
    
    @Override
    protected void exportCells(DataTable table, Object document) {
        Sheet sheet = (Sheet) document;
        FacesContext context = FacesContext.getCurrentInstance();
        int rowIndex = sheet.getLastRowNum() + 1;

        // Recorre todas las filas visibles de la tabla
        for (int i = 0; i < table.getRowCount(); i++) {
            table.setRowIndex(i);

            // Verifica si la fila está disponible
            if (!table.isRowAvailable()) {
                continue;
            }

            // Crea una nueva fila en la hoja de Excel
            Row row = sheet.createRow(rowIndex++);
            int cellIndex = 0;

            // Recorre todas las columnas visibles y exportables de la tabla
            for (UIColumn column : table.getColumns()) {
                if (column.isRendered() && column.isExportable()) {
                    Cell cell = row.createCell(cellIndex++);
                    List<UIComponent> components = column.getChildren();

                    // Obtiene el valor exportado de la columna
                    StringBuilder exportedValue = new StringBuilder();

                    exportColumn(context, table, column, components, true, exportedValue::append);

                    // Se pone texto vacio si sale el texto "null"
                    String exprtdValue = exportedValue.toString();
                    if ("null".equals(exportedValue.toString())) {
                        exprtdValue = "";
                    }

                    // Establece el valor de la celda en la hoja de Excel
                    cell.setCellValue(exprtdValue);
                }
            }
        }
        // Restablece el índice de fila de la tabla después de la exportación
        table.setRowIndex(-1);
    }

    @Override
    protected void doExport(FacesContext facesContext, DataTable table, ExportConfiguration exportConfiguration,
                            int index) throws IOException {
        LOGGER.debug("Empezando la exportacion de XLS...");

        // Uso de try-with-resources para asegurar el cierre del Workbook
        try (Workbook workbook = new HSSFWorkbook()) {
            String sheetName = exportConfiguration.getOutputFileName();

            // Crea una nueva hoja en el Workbook
            Sheet sheet = workbook.createSheet(sheetName);

            // Añade las cabeceras antes de los datos
            addColumnHeaders(table, sheet);

            // Exporta las celdas de la tabla
            exportCells(table, sheet);

            // Escribe el contenido del Workbook en el flujo de salida
            OutputStream outputStream = facesContext.getExternalContext().getResponseOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        }

        LOGGER.debug("Exportacion de XLS finalizada!");
    }

    @Override
    public String getContentType() {
        return "application/vnd.ms-excel";
    }

    @Override
    public String getFileExtension() {
        return ".xls";
    }

    private void addColumnHeaders(DataTable table, Sheet sheet) {
        int rowIndex = 0;
        Row headerRow = sheet.createRow(rowIndex);
        int cellIndex = 0;

        // Recorre todas las columnas visibles y exportables de la tabla para añadir las cabeceras
        for (UIColumn column : table.getColumns()) {
            if (column.isRendered() && column.isExportable()) {
                Cell cell = headerRow.createCell(cellIndex++);
                String headerText = column.getHeaderText();
                cell.setCellValue(headerText);
            }
        }
    }
}

要使用它,您应该在 xhtml 中调用此 customExporter:

<p:commandButton id="exporterXls" value="XLS" styleClass="mr-2 mb-2" ajax="false" icon="pi pi-file-excel">
    <p:dataExporter type="xls" target="datatableId" fileName="example" exporter="#{customExcelExporter}" />
</p:commandButton>
<p:commandButton id="exporterPDF" value="PDF" styleClass="mr-2 mb-2" ajax="false"  icon="pi pi-file-pdf">
    <p:dataExporter type="pdf" target="datatableId" encoding="ISO-8859-2" exporter="#{customPDFExporter}" fileName="example"/>
</p:commandButton>

我希望这有帮助!

致以诚挚的问候

© www.soinside.com 2019 - 2024. All rights reserved.