java使用POI识别excel的复选框插件

前言:

不知道小伙伴们有没有遇见过“要识别excel里的插件对象”的需求。一般情况来说,在软件项目开发的过程中这种需求一般不常见,因为在excel里面的内容完全可以通过线上来提交,比如使用form表单等形式来进行数据录入。但是在线下处理一些材料、数据等可能会遇到这样的问题。
我的这个需求就是线下遇到的,也并不是软件项目开发中的需求(附带讲:项目中的这种功能完全没有必要存在,因为实现这种需求的方式太有针对性了,还并不能保证它的正确性。总之,这种功能完全就是出力不讨好的典型)

问题描述:

问题背景是这样的,我们要做一个数据分析模型,然后甲方需要提供分析数据,将一个个excel数据表转化为一个一条条记录的记录表好用作模型分析。最后就是提供给我们的数据表是含带插件对象的excel表,因为之前没有读取过excel的插件对象,让我以为这种插件对象完全读取不了。后经查看文章发现有一种方式是可以读取的,可以依靠这种方式实现数据读取。

注:在这里要感谢一下前辈的这篇文章“在Java中的Apache POI读取Excel的复选框值(Reading Excel checkbox values in Java Apache POI)

下面给出实现经过和方式:

我们先来看下复选框或单选框长得什么样:
在这里插入图片描述
我们要做的就是要识别excel中,选择的是男或女、是或否。
目前只能通过代码实现对选择框的选中判断,返回true或false,以此来做识别判断

所需jar包:
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.1</version>
        </dependency>
识别代码如下:
package com.yzw.exceldemo.excel;

import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * @author yzw
 */
public class ExcelObject {
    private static final String Workbook = "Workbook";

    public static void readCheckbox(String path) {
        FileInputStream file = null;
        InputStream istream = null;
        try {
            file = new FileInputStream(new File(path));
            POIFSFileSystem poifs = new POIFSFileSystem(file);
            istream = poifs.createDocumentInputStream(Workbook);
            HSSFRequest req = new HSSFRequest();
            req.addListenerForAllRecords(new EventExample());
            HSSFEventFactory factory = new HSSFEventFactory();
            factory.processEvents(req, istream);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (file != null)
                    file.close();
                if (istream != null)
                    istream.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 写个main方法来做一个测试
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("ReadExcelFile");
        //此处为我使用的一个线程用来存储每次复选框的识别列表(目前不需要)
        ObjectList.setCurrentFlag(new ArrayList());
        System.out.println("ReadCheckbox");
        readCheckbox("C:\\Users\\Administrator\\Desktop\\复选框测试.xls");
    }
}



然后,我们还需要写一个类来实现HSSFListener类,并重写processRecord方法,代码如下:

package com.yzw.exceldemo.excel;

import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.SubRecord;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yzw
 */
public class EventExample implements HSSFListener {

    private final static Pattern P = Pattern.compile("\\[sid=0x000A.+?\\[0(\\d),");

    @Override
    public void processRecord(Record record) {

        switch (record.getSid()) {
            case ObjRecord.sid:
                ObjRecord objRec = (ObjRecord) record;

                List<SubRecord> subRecords = objRec.getSubRecords();
                for (SubRecord subRecord : subRecords) {

                    if (!(subRecord instanceof CommonObjectDataSubRecord)) {
                        Matcher m = P.matcher(subRecord.toString());
                        if (m.find()) {
                            String checkBit = m.group(1);
                            if (checkBit.length() == 1) {
                                boolean checked = "1".equals(checkBit);
                                ObjectList.getCurrentFlag().add(checked);

                                System.out.println(ObjectList.getCurrentFlag().size()+"--------"+checked+"-----------"+checkBit);
                            }
                        }
                    }
                }
                break;
            default:
                break;
        }
    }
}

然后运行上面的main方法做一个测试,打印测试结果:
在这里插入图片描述
然后我们变动一下单选框,如下:
在这里插入图片描述
再次运行main方法,打印结果:
在这里插入图片描述
基于此,我们可以得出对应关系如下:

1----对应----男(true)
2----对应----女(true)
3----对应----是(true)
4----对应----否(true)

注意:我们在使用这种方式时,一定要注意对应关系,尤其是复选框或单选框较多时。

接下来我来贴出ObjectList类的实现,其实还是有很多方法来实现存储当前的识别列表集合:
package com.yzw.exceldemo.excel;

import java.util.List;

/**
 * @author yzw
 * 使用一个线程对当前的数据进行一个存储
 */
public class ObjectList {

    private static ThreadLocal currentUser = new ThreadLocal();

    public static void setCurrentFlag(List t) {
        currentUser.set(t);
    }

    public static List getCurrentFlag() {
        return (List) currentUser.get();
    }

    public static void removeCurrentFlag() {
        currentUser.remove();
    }
}

注意:在当前使用完后,一定要记得清除List的数据。
当前方式只支持xls格式的excel,如需要将xlsx文件转为xls文件的则可以参照 使用宏将xlsx格式文件批量转为xls格式文件 这篇文章

关于excel的读取和写入这里就不进行展示了,网上一大堆。

好了,小伙伴们!只要能获取到识别结果,那么接下来的实现方式就不需要在展示了吧。

今天的分享到此结束,如有更好的实现方式,麻烦您一定要告知我,感谢!
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值