利用POI读取excel文档,并进行信息提取

本文介绍了如何使用Apache POI库在Java中读取Excel文件,特别是处理包含多个表的情况。通过创建Map对象以表签名作为键,实现快速定位表格并提取数据。此外,讨论了以Object存储数据以便于后期入库,但可能需要进行类型转换。最后,提供了两个关键文件的概览:Table.java用于处理Excel版本和提取值,ReadExcel.java则用于调用和筛选入库数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近带领小伙伴们处理了一下爬虫爬下来的数据,爬下来的数据有excel表格,word文档,pdf.其中以pdf的数据最难处理,只想要保留pdf中的表格部分,但是却不得其法,目前还没有攻克.

在这篇文章里记录一下使用apache poi读取excel文件用到的方法以及问题等,希望能帮助到大家吧:

一、excel中内容介绍

在excel文件中,我们首先遇到的是一个excel中有多个表,如何遍历和提取每一个单元格的数据这是个问题.

Idea中的pom依赖:

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>

读取excel文件:

/**
     * 读取Office 2007 excel
     * */
    private Map<String,List<List<Object>>> read2007Excel(File file)
            throws IOException {
        // 构造 XSSFWorkbook 对象,strPath 传入文件路径
        XSSFWorkbook xwb = new XSSFWorkbook(new FileInputStream(file));
        evaluator = xwb.getCreationHelper().createFormulaEvaluator();
        //创建一个存储数据的HashMap对象
        Map<String,List<List<Object>>> map = new HashMap<>(16);

        // 读取第一章表格内容
        for (int a = 0; a < xwb.getNumberOfSheets(); a++) {
            List<List<Object>> list = new LinkedList<>();

            XSSFSheet sheet = xwb.getSheetAt(a);
            //待存取的value值
            Object value;
            //当前行
            XSSFRow row;
            //当前格
            XSSFCell cell;
            int counter = 0;
            //从第一行开始遍历
            for (int i = sheet.getFirstRowNum();
                 counter < sheet.getPhysicalNumberOfRows(); i++) {
                if (i == 0) {
                    //跳过第一行,不存取标题信息
                    continue;
                }
                row = sheet.getRow(i);
                if (row == null) {
                    break;
                }
                //按行存储,将该表中所有的元素存储在list对象中
                List<Object> linked = new LinkedList<>();
                //遍历当前行的所有cell元素
                for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {
                    cell = row.getCell(j);
                    //判断当前cell存储的数据类型,将其转化为Java中对应的数据类型
                    //例如时间转为Date类型
                    value = getSheetValue(cell);
                    linked.add(value);
                }
                list.add(linked);
            }
            //key为该表的名称,eg:1-潜在,基本信息
            //value为当前表,是一个二维List对象
            map.put(xwb.getSheetName(a),list);
        }
        return map;
    }

看起来还是挺简单的,但是在这一段代码中我用到了evaluator,这个evaluator其实是poi提供的用于处理excel文件中的函数的问题.比如说"='10-评委'!F3"和"SUM(B5:B10)",这样的.通过evaluator就可以达到提取时,不管函数是什么样子,直接获取该函数的结果.我这里把它作为当前类文件的一个属性来使用了.

看完代码,再说一说我读excel文件的思路:为了能够快速的通过表签名(也就是最下面那一栏)找到该表,我创建了一个Map<List<List<Object>>>对象,其中key就是表签的名字.遮掩我通过map的get方法就能够快速的获取到这个表格.

表格中我按行读取,所以value值为一个二维的List集合,遍历当前表的所有元素只需要两个for循环嵌套就可以了.

二、通过Object存数据,方便以后入库

我存储成Object的唯一目的就是为了方便以后存储到数据库中,避免了来回转换格式的问题.可是同样的,我在对单个object进行判断和取值的时候,就需要疯狂的转来转去.如果有需要,大家可以清一色的存储成String类型.

/**
     * @Description : 获取cell对象中的值,并且转为java中对应的类型
     *
     * @param cell
     * @return : java.lang.Object
     * @author : 申劭明
     * @date : 2019/8/9 15:50
     */
    public Object getSheetValue(Cell cell){
        Object value ;
        if (cell == null) {
            //导入不能为空
            value = "无";
            return value;
        }
        // 格式化 number String
        DecimalFormat df = new DecimalFormat("0");
        // 字符,格式化日期字符串
        SimpleDateFormat sdf = new SimpleDateFormat(
                "yyyy-MM-dd");
        // 格式化数字
        DecimalFormat nf = new DecimalFormat("0");
        //判断当前单元格的元素类型
        switch (cell.getCellType()) {
            case XSSFCell.CELL_TYPE_STRING:
                value = cell.getStringCellValue();
                break;
            case XSSFCell.CELL_TYPE_NUMERIC:
                value = cell.getNumericCellValue();
                //避免手机号,身份证等自动识别为double类型
                //由于精度问题需要用减法判断大小
                if (80000000.0 - (double)value < 0){
                    value = (long)((double)value);
                    value = String.valueOf(value);
                }
                break;
            case XSSFCell.CELL_TYPE_BOOLEAN:
                value = cell.getBooleanCellValue();
                break;
      
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值