java通过poi包导入Excel

  使用Apache POI包导入Excel时是需要根据行和列取到对应的值,因此取值时需要知道该列所对应的值应存放到对象的那个字段中去,表格出现变动就会变的比较麻烦,因此此处使用自定义注解的方式,在对象中标明该属性所对应的表头,从程序中遍历表头找到与之对应的单元格,方便数据的导入。

所需的jar包:(用了一下工具类,因此多导入了两个包)

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.17</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>3.17</version>
</dependency>
<dependency>
	<groupId>commons-beanutils</groupId>
	<artifactId>commons-beanutils</artifactId>
	<version>1.9.2</version>
</dependency>
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-lang3</artifactId>
	<version>3.2.1</version>
</dependency>

  自定义注解:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD ,ElementType.TYPE})
public @interface ExcelIn {

    /**
     * 导入sheet名称
     * @return
     */
    String sheetName() default "";

    /**
     * 字段对应的表头名称
     * @return
     */
    String title() default "";
}

  接收导入数据的实体:

@ExcelIn(sheetName = "用户信息")
public class UserInfo {
    private String id;

    @ExcelIn(title = "姓名")
    private String name;

    @ExcelIn(title = "年龄")
    private Integer age;

    @ExcelIn(title = "出生日期")
    private Date birthday;
}

  导入Excel数据:

public class ExcelReader<T> {
    private static BeanUtilsBean beanUtilsBean = new BeanUtilsBean();

    static {
        beanUtilsBean.getConvertUtils().register(new org.apache.commons.beanutils.converters.DateConverter(null), java.util.Date.class);
    }
    /**
     * 表头名字和对应所在第几列的下标,用于根据title取到对应的值
     */
    private final Map<String,Integer> title_to_index = new HashMap<>();
    /**
     * 所有带有ExcelIn注解的字段
     */
    private final List<Field> fields = new ArrayList<>();

    /**
     * 统计表格的行和列数量用来遍历表格
     */
    private  int firstCellNum = 0;
    private  int lastCellNum = 0;
    private  int firstRowNum = 0;
    private  int lastRowNum = 0;

    private String sheetName ;

    private HSSFSheet sheet ;

    public List<T> read(InputStream in , Class clazz) throws Exception {
        gatherAnnotationFields(clazz);
        configSheet(in);
        configHeader();
        List rList= null;
        try {
            rList = readContent(clazz);
        } catch (IllegalAccessException e) {
            throw new Exception(e);
        } catch (InstantiationException e) {
            throw new Exception(e);
        } catch (InvocationTargetException e) {
            throw new Exception(e);
        }
        return rList ;
    }

    private List readContent(Class clazz) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        Object o = null ;
        HSSFRow row = null ;
        List<Object> rsList = new ArrayList<>();
        Object value = null ;
        for(int i = (firstRowNum+1);i<=lastRowNum;i++){
            o = clazz.newInstance();
            row = sheet.getRow(i);
            HSSFCell cell = null ;
            for (Field field : fields) {
                //根据注解中的title,取到表格中该列所对应的的值
                Integer column=title_to_index.get(field.getAnnotation(ExcelIn.class).title());
                if(column==null){
                    continue;
                }
                cell = row.getCell(column);
                value = getCellValue(cell) ;
                if(null != value && StringUtils.isNotBlank(value.toString())) {
                    beanUtilsBean.setProperty(o, field.getName(), value);
                }
            }
            rsList.add(o);
        }
        return rsList ;
    }

    private void configSheet(InputStream in) throws Exception {
        //HSSFWorkbook:只能创建97-03版本的Excel,即:以xls结尾的Excel
        // 想要导入xlsx结尾的Excel,用XSSFWorkbook
        try(HSSFWorkbook wb = new HSSFWorkbook(in)){
            getSheetByName(wb);
        } catch (FileNotFoundException e) {
            throw new Exception(e);
        } catch (IOException e) {
            throw new Exception(e);
        }
    }

    /**
     * 根据sheet获取对应的行列值,和表头对应的列值映射
     */
    private void configHeader(){
        this.firstRowNum = sheet.getFirstRowNum() ;
        this.lastRowNum = sheet.getLastRowNum() ;
        //第一行为表头,拿到表头对应的列值
        HSSFRow row = sheet.getRow(firstRowNum);
        this.firstCellNum = row.getFirstCellNum();
        this.lastCellNum = row.getLastCellNum();
        for (int i = firstCellNum;i<lastCellNum;i++){
            title_to_index.put(row.getCell(i).getStringCellValue(),i);
        }
    }

    /**
     * 根据sheet名称获取sheet
     * @param workbook
     * @return
     * @throws Exception
     */
    private void getSheetByName(HSSFWorkbook workbook) throws Exception {
        int sheetNumber = workbook.getNumberOfSheets();
        for (int i = 0; i < sheetNumber; i++) {
            String name = workbook.getSheetName(i);
            if(StringUtils.equals(this.sheetName,name)) {
                this.sheet = workbook.getSheetAt(i);
                return;
            }
        }
        throw new Exception("excel中未找到名称为"+this.sheetName+"的sheet");
    }

    /**
     * 根据自定义注解,获取所要导入表格的sheet名称和需要导入的字段名称
     * @param clazz
     * @throws Exception
     */
    private void gatherAnnotationFields(Class clazz) throws Exception {
        if(!clazz.isAnnotationPresent(ExcelIn.class)){
            throw new Exception(clazz.getName()+"类上没有ExcelIn注解");
        }
        ExcelIn excelIn = (ExcelIn)clazz.getAnnotation(ExcelIn.class) ;
        this.sheetName = excelIn.sheetName();
        // 得到所有定义字段
        Field[] allFields = FieldUtils.getAllFields(clazz) ;
        // 得到所有field并存放到一个list中
        for (Field field : allFields)
        {
            if (field.isAnnotationPresent(ExcelIn.class))
            {
                fields.add(field);
            }
        }
        if( fields.isEmpty()){
            throw new Exception(clazz.getName()+"中没有ExcelIn注解字段");
        }
    }

    private Object getCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        Object obj = null;
        switch (cell.getCellTypeEnum()) {
            case BOOLEAN:
                obj = cell.getBooleanCellValue();
                break;
            case ERROR:
                obj = cell.getErrorCellValue();
                break;
            case FORMULA:
                try {
                    obj = String.valueOf(cell.getStringCellValue());
                } catch (IllegalStateException e) {
                    obj = numericToBigDecimal(cell);
                }
                break;
            case NUMERIC:
                obj = getNumericValue(cell);
                break;
            case STRING:
                String value = String.valueOf(cell.getStringCellValue());
                value = value.replace(" ", "");
                value = value.replace("\n", "");
                value = value.replace("\t", "");
                obj = value;
                break;
            default:
                break;
        }
        return obj;
    }

    private Object getNumericValue(Cell cell){
        // 处理日期格式、时间格式
        if (HSSFDateUtil.isCellDateFormatted(cell)) {
            return  cell.getDateCellValue();
        }else if (cell.getCellStyle().getDataFormat() == 58) {
            // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)
            double value = cell.getNumericCellValue();
            return org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value);
        } else {
            return numericToBigDecimal(cell);
        }
    }

    private Object numericToBigDecimal(Cell cell) {
        String valueOf = String.valueOf(cell.getNumericCellValue());
        BigDecimal bd = new BigDecimal(valueOf);
        return bd;
    }
}

  测试导入结果:

@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {

    @org.junit.Test
    public void t(){
        try{
            File file = new File("d:/abc.xls");
            ExcelReader<UserInfo> reader = new ExcelReader<>();
            InputStream is = new FileInputStream(file);
            List<UserInfo> list = reader.read(is,UserInfo.class);
            if (CollectionUtils.isNotEmpty(list)) {
                for (UserInfo u : list) {
                    System.out.println("姓名:" + u.getName() + " ,年龄:" + u.getAge() + " ,出身日期:" + u.getBirthday());
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

  导入的Excel数据:(Excel的sheet名称为接收实体对象的sheetName)

  结果展示:

原文地址:https://www.cnblogs.com/xiao-OvO-/p/11012989.html

时间: 2024-10-03 21:40:18

java通过poi包导入Excel的相关文章

java利用poi包 为excel生成超链接

转载自:http://www.blogjava.net/leekiang/archive/2008/10/21/235794.html 1,一个需求, 要求报表生成的Excel表格支持超链接.例如点击Excel内的公司名, 自动打开浏览器并连到该公司的网站上去.在Excel里面选中所需的单元格, 右键弹出属性, 选超链接就能输入相应的地址了,既然Excel支持超链接.那就没有什么借口说不能实现了.:). 翻了翻POI的文档, 很容易就找到了解决方案.在POI中让单元格实现超链接功能, 可以用Hy

java 使用POI批量导入excel数据

一.定义 Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 二.所需jar包: 三.简单的一个读取excel的demo 1.读取文件方法 /** * 读取出filePath中的所有数据信息 * @param filePath excel文件的绝对路径 * */ public static void getDataFromExcel(String filePath) { //String fileP

Java使用poi包读取Excel文档

项目需要解析Excel文档获取数据,就在网上找了一些资料,结合自己这次使用,写下心得: 1.maven项目需加入如下依赖: <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.10-FINAL</version> </dependency> <dependency> <gr

java中使用poi实现导入Excel

1.java中使用poi实现导入Excel public class XlsDto { /** * 选课号 */ private Integer xkh; /** * 学号 */ private String xh; /** * 姓名 */ private String xm; /** * 学院 */ private String yxsmc; /** * 课程号 */ private Integer kch; /** * 课程名 */ private String kcm; /** * 成绩

java的poi技术写Excel的Sheet

在这之前写过关于java读,写Excel的blog如下: Excel转Html java的poi技术读,写Excel[2003-2007,2010] java的poi技术读取Excel[2003-2007,2010] java的poi技术读取Excel数据到MySQL java的jxl技术导入Excel java的poi技术读取和导入Excel 然而,这篇blog主要内容是关于Excel里面怎样去写Sheet数据. 那么在Excel里面什么叫做Sheet呢?如下图红色框里面的内容就是Excel的

java的poi技术读取Excel[2003-2007,2010]

这篇blog主要是讲述java中poi读取excel,而excel的版本包括:2003-2007和2010两个版本, 即excel的后缀名为:xls和xlsx. 读取excel和MySQL相关: java的poi技术读取Excel数据到MySQL 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术 :java的jxl技术导入Excel  下面是本文的项目结构: 项目中所需要的jar文件: 所用的Excel数据(2003-2007,2010都是一

java的poi技术读取Excel数据

这篇blog主要是讲述java中poi读取excel,而excel的版本包括:2003-2007和2010两个版本, 即excel的后缀名为:xls和xlsx. 读取excel和MySQL相关: java的poi技术读取Excel数据到MySQL 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术 :java的jxl技术导入Excel  下面是本文的项目结构: 项目中所需要的jar文件: 所用的Excel数据(2003-2007,2010都是一

java的poi技术读取Excel数据到MySQL

这篇blog是介绍java中的poi技术读取Excel数据,然后保存到MySQL数据中. 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术可以在 :java的jxl技术导入Excel  项目结构: Excel中的测试数据: 数据库结构: 对应的SQL: 1 CREATE TABLE `student_info` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `no` varchar(20) DEFAU

java自定义jar包读取Excel(包含2003和2007)数据,并举例说明

用java自定义jar包读取excel数据支持excel2007和excel2003 在http://download.csdn.net/detail/u010792467/8079355下载所需要的包 如果需要excel2003和excel2007文件可以去 http://download.csdn.net/detail/u010792467/8072009下载 在http://download.csdn.net/detail/u010792467/8079345下载工程 自定义jar包运用举