You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PrimeFaces 11导出DataTable至Excel时Unicode纯数字列报错

PrimeFaces 11 DataTable导出Excel时Unicode数字引发NumberFormatException

我使用PrimeFaces 11实现DataTable导出Excel功能,当备注列仅包含Unicode数字(如२२२५०)时会抛出NumberFormatException,但在Unicode数字中添加非Unicode数字字符后,导出可正常完成。当前使用Apache POI 5.2.2版本。

XHTML代码

<p:commandButton id="cmdexcel" value="#{text.Excel}"
                icon="fa fa-file-excel-o" ajax="false"
                disabled="#{empty ledgerMB.lstLedger}">
                <p:dataExporter type="xls" target="dataTblLedger" encoding="UTF-8"
                    fileName="Ledger"
                    postProcessor="#{ledgerMB.postProcessXLS}" />
</p:commandButton>

<p:dataTable var="tblLedger" value="#{ledgerMB.lstLedger}"
            id="dataTblLedger" rowIndexVar="rowSn" paginator="true" rows="25"
            scrollable="true" scrollHeight="490" scrollWidth="98%"
            rowStyleClass="#{tblLedger.boldFlag ? 'bold-total':''}"
            paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
            rowsPerPageTemplate="25,50,100,150,200" resizableColumns="true"
            emptyMessage="#{text.NoRecordFound}">
            <p:column headerText="#{text.SNo}" width="50">
                <h:outputText value="#{tblLedger.sno eq 0?' ':tblLedger.sno}"
                    styleClass="np" />
            </p:column>
            <p:column headerText="#{text.Date}" width="100">
                <h:outputText value="#{tblLedger.approvedDateBs}" styleClass="np" />
            </p:column>
            <p:column headerText="#{text.VNo}" width="70">
                <h:outputText value="#{tblLedger.jvNo eq 0 ? '' : tblLedger.jvNo}"
                    styleClass="np" />
            </p:column>
            <p:column headerText="#{text.Remarks}" width="70">
                <h:outputText value="#{tblLedger.remarks}"
                    styleClass="np" />
            </p:column>
</p:dataTable>

托管Bean代码

public void postProcessXLS(Object document) {
    HSSFWorkbook wb = (HSSFWorkbook) document;
    HSSFSheet sheet = wb.getSheetAt(0);
    sheet.shiftRows(0, sheet.getLastRowNum(), 0);

    HSSFCellStyle cellStyle = wb.createCellStyle();
    HSSFFont fontHeader = (HSSFFont) wb.createFont();
    cellStyle.setAlignment(HorizontalAlignment.CENTER);
    fontHeader.setFontName("Magnus Nepali");
    cellStyle.setFont(fontHeader);
    for (Row row : sheet) {
        for (Cell cell : row) {
            cell.setCellStyle(cellStyle);
        }
    }
    try {
        wb.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

错误日志

SEVERE: Servlet.service() for servlet [Faces Servlet] threw exception
java.lang.NumberFormatException: For input string: "?????"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
    at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.lang.Double.parseDouble(Double.java:538)
    at org.primefaces.component.datatable.export.DataTableExcelExporter.updateCell(DataTableExcelExporter.java:344)
    at org.primefaces.component.datatable.export.DataTableExcelExporter.lambda$addColumnValue$0(DataTableExcelExporter.java:232)
    at org.primefaces.component.export.TableExporter.exportColumn(TableExporter.java:79)
    at org.primefaces.component.datatable.export.DataTableExcelExporter.addColumnValue(DataTableExcelExporter.java:232)
    at org.primefaces.component.datatable.export.DataTableExcelExporter.exportCells(DataTableExcelExporter.java:129)
    at org.primefaces.component.datatable.export.DataTableExporter.exportRow(DataTableExporter.java:144)
    at org.primefaces.component.datatable.export.DataTableExporter.exportAll(DataTableExporter.java:129)
    at org.primefaces.component.datatable.export.DataTableExcelExporter.exportTable(DataTableExcelExporter.java:405)
    at org.primefaces.component.datatable.export.DataTableExcelExporter.doExport(DataTableExcelExporter.java:97)
    at org.primefaces.component.datatable.export.DataTableExporter$ExportVisitCallback.visit(DataTableExporter.java:241)
    at org.apache.myfaces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:213)

解决方案

问题出在PrimeFaces的DataTableExcelExporter会自动推断内容类型,当内容是纯Unicode数字时,它尝试用Double.parseDouble解析,但Java的数值解析方法不支持非ASCII数字字符,导致抛出异常。

方法1:强制列导出为文本类型

直接在备注列的<p:column>中添加exportType="text"属性,明确指定该列按文本导出,跳过自动类型推断:

<p:column headerText="#{text.Remarks}" width="70" exportType="text">
    <h:outputText value="#{tblLedger.remarks}" styleClass="np" />
</p:column>

方法2:自定义导出器覆盖类型判断逻辑

如果需要全局处理Unicode数字的导出,可继承DataTableExcelExporter重写updateCell方法,跳过对Unicode数字的数值解析:

public class CustomExcelExporter extends DataTableExcelExporter {
    @Override
    protected void updateCell(Object value, Cell cell, String stringValue, boolean escape) {
        // 判断是否为纯Unicode数字
        boolean isUnicodeNumeric = stringValue.chars().allMatch(Character::isDigit);
        if (isUnicodeNumeric) {
            cell.setCellValue(stringValue);
            return;
        }
        super.updateCell(value, cell, stringValue, escape);
    }
}

然后在XHTML中指定自定义导出器:

<p:dataExporter type="xls" target="dataTblLedger" encoding="UTF-8"
                fileName="Ledger" exporter="#{ledgerMB.customExcelExporter}"
                postProcessor="#{ledgerMB.postProcessXLS}" />

同时在托管Bean中实例化自定义导出器:

private CustomExcelExporter customExcelExporter = new CustomExcelExporter();

public CustomExcelExporter getCustomExcelExporter() {
    return customExcelExporter;
}

额外注意事项

删除postProcessXLS方法中的wb.close()调用,PrimeFaces会自行处理工作簿的关闭流程,手动关闭会导致后续操作异常。

内容的提问来源于stack exchange,提问作者Mani Ratna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 16:22:02