Excle导入-通用

先放代码,别人给我的,做个留存,有需要的可以参考一下

public class ImportExcel<T> {
    Class<T> clazz;

    public ImportExcel(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Collection<T> importExcelInputStream(InputStream inputStream, Integer sheetIndex, String... pattern) {
        Collection<T> dist = Lists.newArrayList();
        try {
            /**
             * 类反射得到调用方法
             */
            // 得到目标目标类的所有的字段列表
            Field filed[] = clazz.getDeclaredFields();
            // 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中
            Map fieldmap = new HashMap();
            // 循环读取所有字段
            for (int i = 0; i < filed.length; i++) {
                Field f = filed[i];
                // 得到单个字段上的Annotation
                ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
                // 如果标识了Annotationd的话
                if (exa != null) {
                    // 构造设置了Annotation的字段的Setter方法
                    String fieldname = f.getName();
                    String setMethodName = "set" + fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1);
                    // 构造调用的method,
                    Method setMethod = clazz.getMethod(setMethodName, new Class[] { f.getType() });
                    // 将这个method以Annotaion的名字为key来存入。
                    fieldmap.put("".equals(exa.exportName())?exa.value():exa.exportName(), setMethod);
                }
            }
            // excel的解析开始
            FileInputStream in = (FileInputStream)inputStream;
            // 得到工作表
            HSSFWorkbook book = new HSSFWorkbook(in);
            if (book.getNumberOfSheets() < sheetIndex + 1) {
                log.info("总sheet数:{},要获取的index:{}", book.getNumberOfSheets(), sheetIndex);
                return null;
            }
            Sheet sheet = book.getSheetAt(sheetIndex);
            Iterator<Row> row = sheet.rowIterator(); // 得到所有行
            // 得到第一行,也就是标题行
            Row title = row.next();
            // 得到第一行的所有列
            Iterator<Cell> cellTitle = title.cellIterator();
            // 将标题的文字内容放入到一个map中。
            Map titlemap = new HashMap();
            // 从标题第一列开始
            int i = 0;
            // 循环标题所有的列
            while (cellTitle.hasNext()) {
                Cell cell = cellTitle.next();
                String value = cell.getStringCellValue();
                titlemap.put(i, value);
                i = i + 1;
            }
            while (row.hasNext()) {
                // 标题下的第一行
                Row rown = row.next();
                 // 行的所有列
                Iterator<Cell> cellbody = rown.cellIterator();
                // 得到传入类的实例
                T tObject = clazz.newInstance();
                // 遍历一行的列
                boolean flag = false; // value不为空时才新增行对象值
                while (cellbody.hasNext()) {
                    Cell cell = cellbody.next();
                    // 这里得到此列的对应的标题
                    String titleString = (String) titlemap.get(cell.getColumnIndex());
                    // 如果这一列的标题和类中的某一列的Annotation相同,那么则调用此类的的set方法,进行设值
                    if (fieldmap.containsKey(titleString)) {
                        Method setMethod = (Method) fieldmap.get(titleString);
                        // 判断参数类型
                        String value = getCellValue(cell);
                        if (StringUtils.isNotBlank(value)) {
                            flag = true;
                            value = value.trim();
                            String paramType = setMethod.getParameterTypes()[0].getName();
//                            log.info("paramType == {}, value == {}, titleString == {}", paramType, value, titleString);
                            if (paramType.equals("java.lang.String")) {
                                setMethod.invoke(tObject, value);
                            } else if (paramType.equals("java.lang.Integer")) {
                                double db = Double.parseDouble(value);
                                db = Math.round(db);
                                setMethod.invoke(tObject, new Double(db).intValue());
                            } else if (paramType.equals("java.math.BigDecimal")) {
                                setMethod.invoke(tObject, new BigDecimal(value));
                            }
                        }
                    }
                }
                if (flag) {
                    dist.add(tObject);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return dist;
    }

    /**
     * 根据excel单元格类型获取excel单元格值
     * @param cell
     * @return
     */
    private String getCellValue(Cell cell) {
        String cellvalue = "";
        if (cell != null) {
            // 判断当前Cell的Type
            switch (cell.getCellType()) {
                // 如果当前Cell的Type为NUMERIC
                case Cell.CELL_TYPE_NUMERIC: {
                    short format = cell.getCellStyle().getDataFormat();
                    if(format == 14 || format == 31 || format == 57 || format == 58){     //excel中的时间格式
                        double value = cell.getNumericCellValue();
                        Date date = DateUtil.getJavaDate(value);
                        cellvalue = getDateString2(date);
                    }
                    // 判断当前的cell是否为Date
                    else if (HSSFDateUtil.isCellDateFormatted(cell)) {  //先注释日期类型的转换,在实际测试中发现HSSFDateUtil.isCellDateFormatted(cell)只识别2014/02/02这种格式。
                        // 如果是Date类型则,取得该Cell的Date值           // 对2014-02-02格式识别不出是日期格式
                        Date date = cell.getDateCellValue();
                        cellvalue = getDateString(date);
                    } else { // 如果是纯数字
                        // 取得当前Cell的数值
                        cellvalue = NumberToTextConverter.toText(cell.getNumericCellValue());

                    }
                    break;
                }
                // 如果当前Cell的Type为STRIN
                case Cell.CELL_TYPE_STRING:
                    // 取得当前的Cell字符串
                    cellvalue = cell.getStringCellValue().replaceAll("'", "''");
                    break;
                case  Cell.CELL_TYPE_BLANK:
                    cellvalue = null;
                    break;
                // 默认的Cell值
                default:{
                    cellvalue = " ";
                }
            }
        } else {
            cellvalue = "";
        }
        return cellvalue;
    }

    private String getDateString2(Date date) {
        String cellvalue;Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(1899==instance.get(Calendar.YEAR)){
            formater = new SimpleDateFormat("HH:mm:ss");
        }else if(0==instance.get(Calendar.HOUR)){
            formater = new SimpleDateFormat("yyyy-MM-dd");
        }
        cellvalue = formater.format(date);
        return cellvalue;
    }

    private String getDateString(Date date) {
        String cellvalue;
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(1899==instance.get(Calendar.YEAR)){
            formater = new SimpleDateFormat("HH:mm:ss");
        }else if(0==instance.get(Calendar.HOUR)){
            formater = new SimpleDateFormat("yyyy-MM-dd");
        }
        cellvalue= formater.format(date);
        return cellvalue;
    }

}

 

这个是主方法,提前根据列名定义对应的实体类,通过反射,将实体类和Excle表格列标题进行绑定(差不多这个意思),例:

遍历excle的值,通过当前列列名,将值set到列名对应的属性值上。这样,当excle表格改变之后,只需改变对应的实体类和sql语句,就可以对代码进行维护,维护起来很方便。如果有其他更好的方法,欢迎大家提出来。PS:此方法非原创!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java是一种通用的高级编程语言,通过Java编写程序可以实现各种功能,包括Excel的导入和导出。在Java中,可以使用Apache POI来操作Excel文件,Apache POI是一个流行的用于读写Microsoft Office文件的Java库,它包括HSSF(用于读写Excel 97-2003),XSSF(用于读写Excel 2007+)和SS(实验性的通用Spiral包)。 在Java中使用Apache POI进行Excel导入时,首先需要创建一个Workbook对象,该对象可以是XSSFWorkbook(用于.xlsx文件格式),也可以是HSSFWorkbook(用于.xls文件格式)。一旦获得了Workbook对象,就可以从工作表中获取数据。对于每个工作表,都可以使用Sheet对象访问单元格中的值,并使用Row对象访问单元格中的列数据。 在Excel导出方面,在Java中使用Apache POI可以创建Excel文档并向其中添加数据。要创建一个Excel文档,首先需要创建一个Workbook对象,然后添加一个或多个工作表。对于每个工作表,可以使用Sheet对象访问单元格,并使用Row对象访问列数据。将数据添加到单元格后,可以使用FileOutputStream将文档写入指定的文件。 总的来说,使用Java进行Excel导入导出是一种非常灵活和高效的方法,可以通过学习和使用Apache POI等工具来实现。 ### 回答2: Java是一个跨平台的编程语言,它可以很好地进行Excel文件的导入和导出。Java提供了一些库,比如Apache POI,用于操作Excel文件。通过这些库,我们可以在Java中进行Excel文件的读取和写入。 Excel的导入和导出可以用来处理各种数据,这对于企业来说非常有用。因为数据是企业的核心资产之一,所以正确导入和导出数据是非常重要的。Java对于处理Excel数据非常方便,我们可以很容易地将数据转换成Java对象,然后以任何我们需要的方式进行处理。 在使用Java进行Excel的导入和导出时,我们需要先导入Apache POI库。通过这个库,我们可以调用其提供的方法来操作Excel文件。例如,我们可以通过创建Workbook对象来读取Excel文件,并通过Sheet对象访问工作表中的单元格。 对于Excel的导出,我们首先需要定义Excel模板,然后使用Java代码填充模板。我们可以通过创建Workbook对象来创建新的工作簿。然后,我们可以创建一个Sheet对象,然后使用Row对象和Cell对象来创建表格。最后,我们将表格数据写入Excel文件中。 总而言之,Java提供了快速,可靠的Excel导入和导出解决方案。这对于企业来说非常重要,因为数据是企业运营的核心资产。利用Java的Excel导入和导出功能,企业可以更好地处理数据并提高效率。 ### 回答3: Java中导入和导出Excel文档是非常常见的操作,可以根据具体需求使用Java自带的API或者开源框架完成。本文将重点介绍Apache POI和EasyExcel两个开源框架的使用。 一、Apache POI Apache POI是Apache软件基金会的一个开源项目,提供基于Java的API用于处理Microsoft Office格式文件。其中包括Word、Excel和PowerPoint等文档的读写操作,对于Excel的读写操作使用的是XSSF和HSSF两个模块,分别支持.xlsx和.xls格式的文件。 1.导入Excel 首先需要导入POI的jar包,然后使用以下代码读取Excel中的数据: ``` File file = new File("test.xlsx"); InputStream inputStream = new FileInputStream(file); Workbook workbook = new XSSFWorkbook(inputStream);//读取xlsx格式 //Workbook workbook = new HSSFWorkbook(inputStream);//读取xls格式 Sheet sheet = workbook.getSheetAt(0);//获取第一个sheet Iterator<Row> iterator = sheet.iterator(); while(iterator.hasNext()) { Row row = iterator.next(); Iterator<Cell> cellIterator = row.cellIterator(); while(cellIterator .hasNext()) { Cell cell = cellIterator.next(); switch (cell.getCellType()) { case STRING: System.out.print(cell.getStringCellValue() + " "); break; case NUMERIC: System.out.print(cell.getNumericCellValue() + " "); break; case BOOLEAN: System.out.print(cell.getBooleanCellValue() + " "); break; case FORMULA: System.out.print(cell.getCellFormula() + " "); break; default: System.out.print(""); } } System.out.println();//换行 } inputStream.close(); ``` 2.导出Excel 基于POI的Excel导出主要是通过创建Workbook对象、Sheet对象和Cell对象,然后将数据填充到Cell对象中,最后输出到文件中。以下是导出Excel的示例代码: ``` Workbook workbook = new XSSFWorkbook();//创建工作簿 Sheet sheet = workbook.createSheet("sheet0");//创建sheet Row row = sheet.createRow(0);//创建行 Cell cell = row.createCell(0);//创建单元格 cell.setCellValue("姓名"); cell = row.createCell(1); cell.setCellValue("年龄"); cell = row.createCell(2); cell.setCellValue("性别"); row = sheet.createRow(1);//创建行 cell = row.createCell(0); cell.setCellValue("张三"); cell = row.createCell(1); cell.setCellValue(20); cell = row.createCell(2); cell.setCellValue("男"); FileOutputStream outputStream = new FileOutputStream("test.xlsx");//输出到文件 workbook.write(outputStream); outputStream.close(); ``` 二、EasyExcel EasyExcel是一个基于POI封装的Java开源框架,提供简单易用的方式完成Excel的导入和导出操作。相对于POI,EasyExcel的优点在于它的API更加简单明了,使用起来更加方便快捷。 1.导入Excel EasyExcel导入Excel的方式主要是通过读取监听器实现,可以实现不同sheet的读取、数据转换和对数据的处理等功能。以下是导入Excel的示例代码: ``` //创建读取监听器 public class ExcelListener extends AnalysisEventListener<User> { private List<User> userList = new ArrayList<>(); @Override public void invoke(User user, AnalysisContext analysisContext) { userList.add(user);//每读取一条数据就添加到List中 } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { //读取完成后的操作 } public List<User> getUserList() { return userList; } public void setUserList(List<User> userList) { this.userList = userList; } } //使用监听器读取Excel数据 File file = new File("test.xlsx"); EasyExcel.read(file, User.class, new ExcelListener()).sheet().doRead(); ``` 2.导出Excel EasyExcel导出Excel的方式主要是通过生成器模式创建写入对象、构造sheet页和单元格,最后输出到文件或者流中。以下是导出Excel的示例代码: ``` //创建写入对象 ExcelWriter writer = EasyExcel.write("test.xlsx", User.class).build(); //构造sheet页和单元格 WriteSheet sheet = EasyExcel.writerSheet("sheet0").build(); //填充数据到单元格 List<User> userList = new ArrayList<>(); userList.add(new User("张三", 20, "男")); userList.add(new User("李四", 22, "女")); writer.write(userList, sheet); //输出到文件或者流中 writer.finish(); ``` 总结 以上是Apache POI和EasyExcel两个框架的Excel导入导出操作,两者都十分流行和实用,可以根据项目需求进行选择。在实际开发中,需要注意的是Excel的版本问题、数据类型的转换、异常处理等,并加以优化和完善,从而提高代码的可维护性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值