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
相关产品推荐
相关产品推荐

