Java poi 读取操作大数据excel 工具类 可根据sheet页名称或id获取工作表;根据行列获取单元格数据

该代码在https://blog.csdn.net/ylforever/article/details/80955595的基础上做了优化,新增根据sheet页名称获取工作表和部分异常处理。

只需三行代码即可获取excel单元格数据

ParseXlsxExcel excel = new ParseXlsxExcel();

excel.readOneSheet("C:\\Users\\**\\Desktop\\Antigua.xlsx","Resdion");//可根据文件路径+sheet页名称或id获取工作表

System.out.println(excel.getDataList().get(0).get("A"));//获取该工作表中第1行第A列数据

以下是工具类源码:

package com.qb.keco.common.utils.excel.largeData;

import java.io.InputStream;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;


/**
 * POI事件驱动读取Excel文件的抽象类。
 * 
 * @author elon
 * @version 2018年7月7日
 */
public abstract class ExcelAbstract extends DefaultHandler {
    private SharedStringsTable sst;
    private String lastContents;
    private boolean nextIsString;

    private int curRow = 0;
    private String curCellName = "";

    
    /**
     * 读取当前行的数据。key是单元格名称如A1,value是单元格中的值。如果单元格式空,则没有数据。
     */
    private Map<String, String> rowValueMap = new HashMap<>();

    /**
     * 处理单行数据的回调方法。
     * 
     * @param curRow 当前行号
     * @param rowValueMap 当前行的值
     * @throws SQLException
     */
    public abstract void optRows(int curRow, Map<String, String> rowValueMap);

    /**
     * 读取Excel指定sheet页的数据。
     * 
     * @param filePath 文件路径
     * @param sheetNum sheet页编号.从1开始。
     * @throws Exception
     */
    public void readOneSheet(String filePath, int sheetNum) throws Exception {
    	
    	if (filePath.endsWith(".xlsx")) {//处理excel2007文件
        	OPCPackage pkg = OPCPackage.open(filePath);
            XSSFReader r = new XSSFReader(pkg);
            SharedStringsTable sst = r.getSharedStringsTable();

            XMLReader parser = getSheetParser(sst);

            // 根据 rId# 或 rSheet# 查找sheet
            InputStream sheet2 = r.getSheet("rId" + sheetNum);
            InputSource sheetSource = new InputSource(sheet2);
            parser.parse(sheetSource);
            sheet2.close();
        } else {
            throw new Exception("文件格式错误,文件扩展名只能是xlsx。");
        }
    	
        
    }
    
    /**
     * 读取Excel指定sheet页的数据。
     * 
     * @param filePath 文件路径
     * @param sheetName sheet页名称。
     * @throws Exception
     */
    public void readOneSheet(String filePath, String sheetName) throws Exception {
    	
    	if (filePath.endsWith(".xlsx")) {//处理excel2007文件
        	OPCPackage pkg = OPCPackage.open(filePath);
            XSSFReader r = new XSSFReader(pkg);
            SharedStringsTable sst = r.getSharedStringsTable();

            XMLReader parser = getSheetParser(sst);
            
            // 根据名称查找sheet
            int sheetNum = 0;
            SheetIterator sheets = (SheetIterator)r.getSheetsData();
            while (sheets.hasNext()) {
            	curRow = 0;
            	sheetNum++;
            	InputStream sheet = sheets.next();
            	if(sheets.getSheetName().equals(sheetName)){
            		sheet.close();
            		break;
            	}
            	sheet.close();
            }
            // 根据 rId# 或 rSheet# 查找sheet
            InputStream sheet2 = r.getSheet("rId" + sheetNum);
            InputSource sheetSource = new InputSource(sheet2);
            parser.parse(sheetSource);
            sheet2.close();
        } else {
            throw new Exception("文件格式错误,文件扩展名只能是xlsx。");
        }
    	
        
    }
    
    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
        // c => 单元格
        if (name.equals("c")) {

            // 如果下一个元素是 SST 的索引,则将nextIsString标记为true
            String cellType = attributes.getValue("t");
            if (cellType != null && cellType.equals("s")) {
                nextIsString = true;
            } else {
                nextIsString = false;
            }
        }

        // 置空
        lastContents = "";

        /**
         * 记录当前读取单元格的名称
         */
        String cellName = attributes.getValue("r");
        if (cellName != null && !cellName.isEmpty()) {
            curCellName = cellName;
        }
    }

    @Override
    public void endElement(String uri, String localName, String name) throws SAXException {
        // 根据SST的索引值的到单元格的真正要存储的字符串
        // 这时characters()方法可能会被调用多次
        if (nextIsString) {
            try {
                int idx = Integer.parseInt(lastContents);
                lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
            } catch (Exception e) {

            }
        }

        // v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
        // 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
        if (name.equals("v")) {
            String value = lastContents.trim();
            value = value.equals("") ? " " : value;
            rowValueMap.put(curCellName, value);
        } else {
            // 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
            if (name.equals("row")) {
                optRows(curRow, rowValueMap);
                rowValueMap.clear();
                curRow++;
            }
        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        // 得到单元格内容的值
        lastContents += new String(ch, start, length);
    }

    /**
     * 获取单个sheet页的xml解析器。
     * @param sst
     * @return
     * @throws SAXException
     */
    private XMLReader getSheetParser(SharedStringsTable sst) throws SAXException {
        XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
        this.sst = sst;
        parser.setContentHandler(this);
        return parser;
    }
    
}
package com.qb.keco.common.utils.excel.largeData;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;


public class ParseXlsxExcel extends ExcelAbstract {

    /**
     * 提取列名称的正则表达式
     */
    private static final String DISTILL_COLUMN_REG = "^([A-Z]{1,})";

    /**
     * 读取excel的每一行记录。map的key是列号(A、B、C...), value是单元格的值。如果单元格是空,则没有值。
     */
    private List<Map<String, String>> dataList = new ArrayList<>();

    @Override
    public void optRows(int curRow, Map<String, String> rowValueMap) {

        Map<String, String> dataMap = new HashMap<>();
        rowValueMap.forEach((k,v)->dataMap.put(removeNum(k), v));
        dataList.add(dataMap);
    }

    /**
     * 日期数字转换为字符串。
     * 
     * @param dateNum excel中存储日期的数字
     * @return 格式化后的字符串形式
     */
    public static String dateNum2Str(String dateNum) {
        Date date = HSSFDateUtil.getJavaDate(Double.parseDouble(dateNum));
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        return formatter.format(date);
    }

    /**
     * 删除单元格名称中的数字,只保留列号。
     * @param cellName 单元格名称。如:A1
     * @return 列号。如:A
     */
    private String removeNum(String cellName) {
        Pattern pattern = Pattern.compile(DISTILL_COLUMN_REG);
        Matcher m = pattern.matcher(cellName);
        if (m.find()) {
            return m.group(1);
        }

        return "";
    }

    public List<Map<String, String>> getDataList() {
        return dataList;
    }
    
    
    public static void main(String[] args) { 
    	try { 
	    	ParseXlsxExcel excel = new ParseXlsxExcel(); 
	    	 try {
	    		 excel.readOneSheet("C:\\Users\\**\\Desktop\\Antigua_SI_Settings_V0.3V0.00.13-111-user-signed test report1017.xlsx","Resdion"); 
				} catch (Exception e) {
					e.printStackTrace();
				}
	    	 System.out.println(excel.getDataList().isEmpty());
	    	//System.out.println(excel.getDataList().get(excel.getDataList().size()-2).get("C")); 
	    	} catch (Exception e) { 
	    	e.printStackTrace(); 
	    	} 
    	} 
    
}

 

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: Java POI是一种用于读取和写入Microsoft Office式文件的Java API。它可以读取和写入Excel、Word和PowerPoint文件。使用Java POI读取Excel文件可以使用HSSF和XSSF API。HSSF用于读取Excel 97-2003文件式(.xls),而XSSF用于读取Excel 2007及更高版本的文件式(.xlsx)。使用POI读取Excel文件需要创建工作簿(Workbook)、工作Sheet)和行(Row)对象,然后使用这些对象来读取单元(Cell)的值。读取Excel文件时,可以使用POI提供的各种方法来获取单元的值、式、样式等信息。使用Java POI读取Excel文件的工具类可以简化读取Excel文件的过程,提高代码的可读性和可维护性。 ### 回答2: Java POI 是一个 Java API,可以帮助我们读取、写入和操作 Microsoft Office 式的文档,包括 Excel、Word 和 PowerPoint 等。在 Java 开发中,使用 Java POI 可以轻松地读取 Excel 文件。 读取 Excel 文件,需要使用工具类。下面我们来看一下如何使用 Java POI 读取 Excel 工具类。 第一步:添加依赖 在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> ``` 第二步:定义工具类 在项目中定义读取 Excel工具类,包含以下方法: ```java public static List<List<String>> readExcel(String filePath, int sheetIndex) throws IOException { FileInputStream fis = new FileInputStream(filePath); Workbook workbook = new XSSFWorkbook(fis); Sheet sheet = workbook.getSheetAt(sheetIndex); List<List<String>> dataList = new ArrayList<>(); for (int i = 0; i <= sheet.getLastRowNum(); i++) { List<String> rowList = new ArrayList<>(); Row row = sheet.getRow(i); if (row == null) { continue; } for (int j = 0; j < row.getLastCellNum(); j++) { Cell cell = row.getCell(j); if (cell == null) { rowList.add(""); } else { rowList.add(cell.toString()); } } dataList.add(rowList); } fis.close(); return dataList; } ``` 该方法接受 Excel 文件路径和工作的索引,返回一个二维 List,存储了读取Excel 数据。 第三步:调用工具类 在需要读取 Excel 的地方,调用工具类的 readExcel 方法即可。 例如: ```java List<List<String>> dataList = ExcelUtils.readExcel("example.xlsx", 0); for (List<String> rowList : dataList) { for (String cellValue : rowList) { System.out.print(cellValue + "\t"); } System.out.println(); } ``` 上述示例会读取 example.xlsx 文件中第一个工作的所有数据,并输出到控制台。 总结 Java POI 是一种强大的 Java API,可以帮助我们读取、写入和操作 Microsoft Office 式的文档。本文介绍了使用 Java POI 读取 Excel工具类,适用于大部分 Java 项目的开发。 ### 回答3: Java POI是一个开源JAVA API,它提供了读取、写入和操作Microsoft Office式文件的能力。其中,读取Excel文件是它的一个重要功能。 Java POI读取Excel工具类一般分为以下步骤: 1. 创建文件输入流和Workbook对象,根据文件名或流读取Excel文件; ``` // 创建文件输入流 InputStream inputStream = new FileInputStream(filePath); // 根据文件输入流,创建Workbook对象 Workbook workbook = WorkbookFactory.create(inputStream); ``` 2. 选择读取Sheet单,若不指定则默认读取第一个Sheet单; ``` // 根据指定Sheet名称获取Sheet对象 Sheet sheet = workbook.getSheet(sheetName); // 若未指定Sheet名称,则默认读取第一个Sheet if (sheet == null) { sheet = workbook.getSheetAt(0); } ``` 3. 遍历Sheet的每一行,并读取每一列的值; ``` // 遍历每一行 for (Row row : sheet) { // 遍历每一列 for (Cell cell : row) { // 获取单元的值 String cellValue = ""; switch (cell.getCellType()) { case STRING: cellValue = cell.getStringCellValue(); break; case NUMERIC: cellValue = String.valueOf(cell.getNumericCellValue()); break; case BOOLEAN: cellValue = String.valueOf(cell.getBooleanCellValue()); break; case FORMULA: cellValue = cell.getCellFormula(); break; default: cellValue = ""; break; } // 打印单元的值 System.out.println(cellValue); } } ``` 4. 关闭文件输入流和Workbook对象; ``` // 关闭输入流 if (inputStream != null) { inputStream.close(); } // 关闭Workbook if (workbook != null) { workbook.close(); } ``` 以上是Java POI读取Excel的基本操作读取数据可以进一步进行处理和操作,比如存储到数据库、输出到文件等。同时,Java POI也支持读取其他类型的Microsoft Office式文件,如Word和PowerPoint等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑的小鱼儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值