POI sax 从单元格获取日期

POI sax get Date from Cell

我正在使用 sax 阅读 excel 文件,一切正常,预计日期。日期读起来像“41751”,这是从 1900 年开始的天数。应该有一些 formatString,我可以用它来格式化,但它是空的。

开始元素()

this.nextDataType = xssfDataType.NUMBER;
        this.formatIndex = -1;
        this.formatString = null;
        String cellType = attributes.getValue("t");
        String cellStyleStr = attributes.getValue("s");
        if ("b".equals(cellType))
            nextDataType = xssfDataType.BOOL;
        else if ("e".equals(cellType))
            nextDataType = xssfDataType.ERROR;
        else if ("inlineStr".equals(cellType))
            nextDataType = xssfDataType.INLINESTR;
        else if ("s".equals(cellType))
            nextDataType = xssfDataType.SSTINDEX;
        else if ("str".equals(cellType))
            nextDataType = xssfDataType.FORMULA;
        else if (cellType == null) {
            maybeNull=true;
        } else if (cellStyleStr != null) {
            // It's a number, but almost certainly one
            //  with a special style or format
            int styleIndex = Integer.parseInt(cellStyleStr);
            XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
            this.formatIndex = style.getDataFormat();
            this.formatString = style.getDataFormatString();
            if (this.formatString == null)
                this.formatString = BuiltinFormats.getBuiltinFormat(this.formatIndex);
        }

EndElement()

case NUMBER:
                    String n = value.toString();
                    if (this.formatString != null) {
                        thisStr = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, this.formatString);
                        try {
                            int intV = Integer.valueOf(thisStr);
                            cv.set(CellTypes.INT, intV);
                        } catch (NumberFormatException ignored) {}
                        if (cv.getType() == null) {
                            try {
                                Double doubleV = Double.valueOf(thisStr);
                                cv.set(CellTypes.DOUBLE, doubleV);
                            } catch (NumberFormatException e) {
                                cv.set(CellTypes.STRING, thisStr);
                            }
                        }
                    }

如何获取该日期或如何找到该单元格包含日期而不是某个整数。完整的处理程序代码在这里 http://pastebin.com/GveeMf4n 谢谢

如果您查看 Apache POI Example for converting a .xlsx file to .csv with SAX event parsing,您就会知道需要做什么

基本上,当你读取单元格时,不仅需要捕获类型和内容,还需要捕获 s 样式索引属性,然后从你的 StylesTable 中查找以类似 DOM 的方式加载(它很小),例如

public void startElement(String uri, String localName, String name,
                             Attributes attributes) throws SAXException {
   this.formatIndex = -1;
   this.formatString = null;
   String cellStyleStr = attributes.getValue("s");
   if (cellStyleStr != null) {
       // It's a number, but almost certainly one
       //  with a special style or format 
       XSSFCellStyle style = null;
       if (cellStyleStr != null) {
           int styleIndex = Integer.parseInt(cellStyleStr);
           style = stylesTable.getStyleAt(styleIndex);
       } else if (stylesTable.getNumCellStyles() > 0) {
           style = stylesTable.getStyleAt(0);
       }
       if (style != null) {
           this.formatIndex = style.getDataFormat();
           this.formatString = style.getDataFormatString();
           if (this.formatString == null)
               this.formatString = BuiltinFormats.getBuiltinFormat(this.formatIndex);
       }
    }

    // Rest of start element logic here

然后,当您到达单元格的结束标记时,您可以使用 DataFormatter 根据您找到的样式格式化单元格的数字内容(日期、% 或类似内容)早些时候,例如

public void endElement(String uri, String localName, String name)
            throws SAXException {
        String thisStr = null;

    // v => contents of a cell
    if ("v".equals(name)) {
        // Process the value contents as required.
        // Do now, as characters() may be called more than once
        switch (nextDataType) {
                case NUMBER:
                    String n = value.toString();
                    if (this.formatString != null)
                        thisStr = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, this.formatString);
                    else
                        thisStr = n;
                    break;

但基本上,技巧是读取 StylesTable,在开始读取单元格时捕获格式字符串,然后在您有单元格内容时使用它通过 DataFormatter 格式化数字字符串。

查看 source code to the XLSX2CSV example 的工作实施