How to override PrimeFaces p:dataExporter wrongly

2019-02-24 11:42发布

问题:

The PrimeFace p:dataExporter tag exports numeric data as text by default, which results in a cell with a green triangle in the upper left corner. This can be seen in the PrimeFaces showcase example as well, if you click the Excel export under the cars table.

How can I override this default to make sure my numeric columns are not exported as text? I tried using the postProcessor attribute pointing to my method that sets the Excel format for all the data cells using POI API but that did not take effect (did not change anything):

public void formatExcel(Object doc) {
    HSSFWorkbook book = (HSSFWorkbook)doc;
    HSSFSheet sheet = book.getSheetAt(0); 

    HSSFRow header = sheet.getRow(0);
    int colCount = header.getPhysicalNumberOfCells();
    int rowCount = sheet.getPhysicalNumberOfRows();

    HSSFCellStyle numStyle = book.createCellStyle();
    numStyle.setDataFormat((short)1);

    for(int rowInd = 1; rowInd < rowCount; rowInd++) {
        HSSFRow row = sheet.getRow(rowInd);
        for(int cellInd = 1; cellInd < colCount; cellInd++) {
            HSSFCell cell = row.getCell(cellInd);
            String val = cell.getStringCellValue();

            cell.setCellStyle(numStyle);

        }
    }
}

I also tried

cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);

but that gives me

java.lang.IllegalStateException: Cannot get a numeric value from a text cell

So that means that all data is indiscriminately exported as text and then you can't even change it afterwards.

回答1:

This is what ended up working for me. It is far from elegant but it works:

HSSFCellStyle intStyle = book.createCellStyle();
intStyle.setDataFormat((short)1);

HSSFCellStyle decStyle = book.createCellStyle();
decStyle.setDataFormat((short)2);

HSSFCellStyle dollarStyle = book.createCellStyle();
dollarStyle.setDataFormat((short)5);


for(int rowInd = 1; rowInd < rowCount; rowInd++) {
    HSSFRow row = sheet.getRow(rowInd);
    for(int cellInd = 1; cellInd < colCount; cellInd++) {
        HSSFCell cell = row.getCell(cellInd);

        //This is sortof a hack to counter PF exporting all data as text
        //We capture the existing value as string, convert to int, 
        //then format the cell to be numeric and reset the value to be int
        String strVal = cell.getStringCellValue();

        //this has to be done to temporarily blank out the cell value
        //because setting the type to numeric directly will cause 
        //an IllegalStateException because POI stupidly thinks
        //the cell is text because it was exported as such by PF...
        cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
        cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);

        strVal = strVal.replace(",", StringUtils.EMPTY);

        if(strVal.indexOf('.') == -1) {
            //integer
            //numStyle.setDataFormat((short)1);
            int intVal = Integer.valueOf(strVal);

            cell.setCellStyle(intStyle);
            cell.setCellValue(intVal);
        } else {
            //double
            if(strVal.startsWith("$")) {
                strVal = strVal.replace("$", StringUtils.EMPTY);
                //numStyle.setDataFormat((short)5);
                cell.setCellStyle(dollarStyle);
            } else {
                //numStyle.setDataFormat((short)2);
                cell.setCellStyle(decStyle);
            }

            double dblVal = Double.valueOf(strVal);
            cell.setCellValue(dblVal);
        }
    }
}


回答2:

In your postProcessor, you nowhere set the value of the cell to an integer. You set the type, but not the value. Setting the type is not enough. You have to convert value to a number and set it again