JavaPOI读取Excel的两种模式

Posted remo0x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaPOI读取Excel的两种模式相关的知识,希望对你有一定的参考价值。

用户模式

基本使用

usermodel相关包,对用户友好,在ss包下有统一的接口,但它是把整个文件读取到内存中,对于大量数据很容易内存溢出,所以只能用来处理小量数据

示例代码

public static List<Map<String, String>> readWorkbook(Workbook workbook) 
    if (workbook == null || workbook.getNumberOfSheets() == 0) 
        return null;
    
    List<Map<String, String>> result = Lists.newLinkedList();
    Map<String, String> map;
    Sheet sheet;
    Cell cell;
    Row head, row;
    for (int i = 0; i < workbook.getNumberOfSheets(); i++) 
        sheet = workbook.getSheetAt(i);
        if (sheet == null || sheet.getPhysicalNumberOfRows() == 0) 
            continue;
        
        head = sheet.getRow(0);
        if (head == null || head.getPhysicalNumberOfCells() == 0) 
            continue;
        
        int rows = sheet.getPhysicalNumberOfRows(), cols = head.getPhysicalNumberOfCells();
        for (int j = 1; j < rows; j++) 
            row = sheet.getRow(j);
            map = Maps.newLinkedHashMap();
            for (int k = 0; k < cols; k++) 
                cell = row.getCell(k);
                if (cell.getCellTypeEnum().equals(CellType.BOOLEAN)) 
                    map.put(head.getCell(k).getStringCellValue(), Boolean.valueOf(cell.getBooleanCellValue()).toString());
                 else if (cell.getCellTypeEnum().equals(CellType.NUMERIC)) 
                    map.put(head.getCell(k).getStringCellValue(), Double.valueOf(cell.getNumericCellValue()).toString());
                 else if (cell.getCellTypeEnum().equals(CellType.STRING)) 
                    map.put(head.getCell(k).getStringCellValue(), cell.getStringCellValue());
                 else 
                    map.put(head.getCell(k).getStringCellValue(), StringUtils.EMPTY);
                
            
            result.add(map);
        
    
    return result;

继承关系

Workbook

事件模式

基本使用

eventusermodel相关包,使用比较复杂,但是它处理速度快,占用内存少,可以用来处理海量数据

示例代码

public static List<Map<String, String>> readLargeExcel(InputStream is, Map<String, String> replaceHead) throws Exception 
    // Excel Reader
    OPCPackage opcPackage = OPCPackage.open(is);
    XSSFReader xssfReader = new XSSFReader(opcPackage);
    SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();
    // Sheet Parser
    XMLReader xmlReader = new SAXParser();
    SheetHandler sheetHandler = new SheetHandler(sharedStringsTable, replaceHead);
    xmlReader.setContentHandler(sheetHandler);
    // Sheet
    InputStream sheet = xssfReader.getSheet("rId1");
    InputSource sheetSource = new InputSource(sheet);
    // Read Sheet
    xmlReader.parse(sheetSource);
    return sheetHandler.getData();


private static class SheetHandler extends DefaultHandler 
    private SharedStringsTable sharedStringsTable;
    private boolean nextIsString;
    private int rowNumber = 1; // current row,base 1
    private int cellRowNumber; // current cell's row number
    private String cellColumnTag; // current cell's row tag, such as A-Z
    private String cellString;
    private HashMap<String, String> head = new HashMap<>();
    private Map<String, String> replaceHead;
    private LinkedHashMap<String, String> row;
    private List<Map<String, String>> data = new LinkedList<>();

    public SheetHandler(SharedStringsTable sharedStringsTable, Map<String, String> replaceHead) 
        this.sharedStringsTable = sharedStringsTable;
        this.replaceHead = replaceHead;
    

    public List<Map<String, String>> getData() 
        return data;
    

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) 
        if (qName.equals("c")) 
            String cellPosition = attributes.getValue("r"); // A1,B1,AA1,AB1...
            cellRowNumber = Integer.parseInt(cellPosition.replaceAll("\\\\D", ""));
            cellColumnTag = cellPosition.replaceAll("\\\\d", "");
            String cellType = attributes.getValue("t");
            nextIsString = cellType != null && cellType.equals("s");
        
        cellString = StringUtils.EMPTY;
    

    @Override
    public void endElement(String uri, String localName, String qName) 
        if (nextIsString) 
            cellString = new XSSFRichTextString(sharedStringsTable.getEntryAt(Integer.parseInt(cellString))).toString();
            nextIsString = false;
        
        if (qName.equals("v")) 
            // initializing the head
            if (rowNumber == 1 && rowNumber == cellRowNumber) 
                if (replaceHead == null || replaceHead.size() == 0) 
                    head.put(cellColumnTag, cellString);
                 else if (replaceHead.containsKey(cellString)) 
                    head.put(cellColumnTag, replaceHead.get(cellString));
                
                return;
            
            // next row and isn't the first, adding to the data list
            if (rowNumber != cellRowNumber) 
                row = new LinkedHashMap<>();
                data.add(row);
                rowNumber = cellRowNumber;
            
            // don't read the column if head not exist the tag
            if (head.containsKey(cellColumnTag)) 
                row.put(head.get(cellColumnTag), cellString);
            
        
    

    @Override
    public void characters(char[] ch, int start, int length) 
        cellString += new String(ch, start, length);
    

继承关系

OPCPackage

XSSFReader

XmlReader

以上是关于JavaPOI读取Excel的两种模式的主要内容,如果未能解决你的问题,请参考以下文章

用javaPOI包的方法获取excel中的行列号

用javaPOI包的方法获取excel中的行列号

java读取excel文件的两种方式

javapoi数据导出成excel如何才能指定文件输出路径 现在是知道E盘路径 怎么弄成弹框选择路径

java利用poi读取excel异常问题

java poi 写入Excel后读取公式值问题