我正在使用 Primefaces 12,并且我知道在版本 12 中,dataExporter 存在一个问题,即在尝试下载文件时不包含表头。 这就是问题
我已经编写了一个后处理器来将它们包含在“xls”文件中,但我也需要帮助才能将它们应用于“pdf”文件。由于某些问题,我无法升级到 primefaces 13。
遇到此问题的用户可以尝试以下方法:
在 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>
我希望这有帮助!
致以诚挚的问候