POI API 的事件模型是否在 3.15 版本中不适用(出现编译错误)?

Is Event model of POI API not applicable(getting compilation error) in version 3.15?

我已经实现了一个程序,我尝试使用 SAX 和 XSSF(POI API) 以及 jar 版本 4.1 读取 excel 文件 (.xlsx),它工作正常。 但是它在 POI 3.15 版本中给出了编译错误。

代码看起来像这样(在 4.10 中运行良好):

默认处理程序实现(SAXExcelSheetHandler.java):

import org.apache.poi.xssf.model.SharedStringsTable;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXExcelSheetHandler extends DefaultHandler {
    private SharedStringsTable sst;
    private String lastContents;
    private boolean nextIsString;

    public SAXExcelSheetHandler(SharedStringsTable sst) {
        this.sst = sst;
    }

    public void startElement(String uri, String localName, String name,
                             Attributes attributes) throws SAXException {
        // c => cell
        if(name.equals("c")) {
            // Print the cell reference
            System.out.print(attributes.getValue("r") + " - ");
            // Figure out if the value is an index in the SST
            String cellType = attributes.getValue("t");
            if(cellType != null && cellType.equals("s")) {
                nextIsString = true;
            } else {
                nextIsString = false;
            }
        }
        // Clear contents cache
        lastContents = "";
    }

    public void endElement(String uri, String localName, String name)
            throws SAXException {
        // Process the last contents as required.
        // Do now, as characters() may be called more than once
        if(nextIsString) {
            int idx = Integer.parseInt(lastContents);
            lastContents = sst.getItemAt(idx).getString();
            nextIsString = false;
        }

        // v => contents of a cell
        // Output after we've seen the string contents
        if(name.equals("v")) {
            System.out.println(lastContents);
        }
    }

    public void characters(char[] ch, int start, int length) {
        lastContents += new String(ch, start, length);
    }
}

实际驱动程序 Class(POISaxXaafV2.java):

import java.io.File;
import java.io.InputStream;
import java.util.Iterator;
import org.apache.poi.ooxml.util.SAXHelper;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class POISaxXaafV2 {

    public static void main(String[] args) throws Exception {   
        String fullFilePath = "E:\Downloads\6038_Open_AR.XLSX";       
        File file = new File(fullFilePath);

        OPCPackage opcPackage = OPCPackage.open(file);
        XSSFReader xssfReader = new XSSFReader(opcPackage);
        SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();

        XMLReader xmlParser = SAXHelper.newXMLReader();
        ContentHandler contentHandler = new SAXExcelSheetHandler(sharedStringsTable);
        xmlParser.setContentHandler(contentHandler);

        Iterator<InputStream> sheetsIterator = xssfReader.getSheetsData();
        while(sheetsIterator.hasNext()) {
            System.out.println("Processing new sheet:\n");
            InputStream sheet = sheetsIterator.next();
            InputSource sheetSource = new InputSource(sheet);
            xmlParser.parse(sheetSource);
            sheet.close();
            System.out.println("");
        }       
    }
}

目前一切顺利,运行良好。

现在我尝试在我的工作场所实施此操作,他们使用的是 3.15 版本的 POI 而不是 4.1.0。唉,我遇到了编译错误

第一次编译错误:

在默认处理程序实现中 class:SAXExcelSheetHandler.java

第 39 行:

lastContents = sst.getItemAt(idx).getString();

它说

The method getItemAt(int) is undefined for the type SharedStringsTable

第二次编译错误

这在驱动程序中 class : POISaxXaafV2.java

在第 4 行:

import org.apache.poi.ooxml.util.SAXHelper

它说:

The import org.apache.poi.ooxml cannot be resolved

由于上述错误,最终我在第 22 行再次出现编译错误:

XMLReader xmlParser = SAXHelper.newXMLReader();

因为导入失败:

SAXHelper cannot be resolved

对于 3.15 版,这是否需要与我在 4.10 中编写的不同?

请帮忙。

正如评论中所说,请不要坚持使用过时的软件版本。这样做不是我们在软件开发方面取得进步的方式。

当然,XSSF and SAX (Event API) 版本 3.15 也存在。

但是在这个旧版本SharedStringsTable中没有方法getItemAt。它只有 getEntryAt 个 return 个 org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst。因此 class SAXExcelSheetHandler 中的代码必须更改为:

...
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
...

...
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        // Process the last contents as required.
        // Do now, as characters() may be called more than once
        if(nextIsString) {
            int idx = Integer.parseInt(lastContents);
            //lastContents = sst.getItemAt(idx).getString();
            lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
            nextIsString = false;
        }

        // v => contents of a cell
        // Output after we've seen the string contents
        if(name.equals("v")) {
            System.out.println(lastContents);
        }
    }

...

还没有SAXHelper。因此 class POISaxXaafV2 的代码必须更改为:

...
import java.io.File;
import java.io.InputStream;
import java.util.Iterator;
//import org.apache.poi.ooxml.util.SAXHelper;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
...

...
        OPCPackage opcPackage = OPCPackage.open(file);
        XSSFReader xssfReader = new XSSFReader(opcPackage);
        SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();

        //XMLReader xmlParser = SAXHelper.newXMLReader();
        SAXParserFactory parserFactory = SAXParserFactory.newInstance();
        SAXParser parser = parserFactory.newSAXParser();
        XMLReader xmlParser = parser.getXMLReader();
        ContentHandler contentHandler = new SAXExcelSheetHandler(sharedStringsTable);
        xmlParser.setContentHandler(contentHandler);
...