java后端导出excel

最近工作中需要导出excel。这次机智一点做个笔记,顺便写了一个比较通用的工具类。自然目前不能生成java实体类属性嵌套多次的这种没办法导出了,后续有需要的时候我再改改。

首先,java后端导出excel需要的HSSFWorkbook或者XSSFWorkbook,实际上他们并没有什么区别,只是导出的格式不同而已(在我看来)。前者导出.xls格式,后者导出.xlsx格式的。不过新版的好像就没有这个区别了吧,因为我也是使用HSSFWorkbook,但是同样也能导出.xlsx格式的文件呦。

HSSFWorkbook(XSSFWorkbook)他们都是Apache的产品,你可以按照需求随意切换!他们没有实质上的太多的差别,听别人说他们还有一个差别就是HSSFWorkbook只能导出65535条数据,再大的话就会报错,而XSSFWorkbook可以导出数据量是非常大的(在下并没有测试,感兴趣的兄弟可以试一下),实际上一般我们也用不了导出超过65535条数据吧。

先看一下api吧!http://poi.apache.org/apidocs/dev/org/apache/poi/hssf/usermodel/HSSFWorkbook.html

接下来我就直接粘代码了

package com.ml.code.one.until;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author lhf
 * @param <T>
 * @since 1.0
 * <p>
 *     导出excel工具类,比较通用的呦
 * </p>
 */
public class ExcelUtil<T> {


    /**
     * 导出excel
     * @param datas  要导出的数据
     * @param excelName excel名字
     * @param sheetHead 表头 key对应java中的属性名,每个key前边    
     * 加01-99,为了排序。value对应表头的中文名
     * @param path 路径
     * @param entity 分装属性名(如果有连表查询的话)
     * @return -1其他异常   1导出成功     2目标文件被占用(文件已存在但是被其他应用占用)   0 导出失败(io)
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    public  int outExcel(Collection<T>datas, String excelName,
                                  Map<String, String> sheetHead,String path,String... entity) throws IllegalAccessException, InvocationTargetException {
        HSSFWorkbook workbook = new HSSFWorkbook(); //excel对象
        HSSFSheet sheet = workbook.createSheet(excelName);
        sheet.autoSizeColumn(1,true);

        //第一行表名
        HSSFRow row = sheet.createRow(0);
        HSSFCell cell = row.createCell(0);
        cell.setCellValue(excelName);


        //获取表头集合中所有的key(那么顺序可能会乱)
        Set<String> sheetKeySet = sheetHead.keySet();
        //转换为list集合,并排序
        List<String> sheetKey = sheetKeySet.stream().sorted().collect(Collectors.toList());//将set集合进行排序并转换成List集合
        //合并单元格
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, sheetKey.size() - 1));

        //设置单元格文字垂直居中,水平居中
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setAlignment(HorizontalAlignment.CENTER_SELECTION);
        cell.setCellStyle(cellStyle);

        //日期格式
        HSSFCellStyle style = workbook.createCellStyle();
//        HSSFDataFormat dataFormat = workbook.getCreationHelper().createDataFormat();
        HSSFDataFormat dataFormat = workbook.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("yyyy/m/d"));

        //表头
        HSSFRow row1 = sheet.createRow(1);
        for (int i = 0; i < sheetKey.size(); i++) {
            HSSFCell cell1 = row1.createCell(i);
            cell1.setCellValue(sheetHead.get(sheetKey.get(i)));
            cell1.setCellStyle(cellStyle);
        }

        List<T> data = datas.stream().collect(Collectors.toList()); //将Collection转为List集合
        T t=null; //获取到的泛型
        //开始向excel表中添加信息
        for (int i = 0; i < data.size(); i++) {//生成行
            HSSFRow row2 = sheet.createRow(i + 2);
            t=data.get(i);
            Method[] declaredMethods = t.getClass().getDeclaredMethods();
            for (int m = 0; m < sheetKey.size(); m++) {//拿到key值  key的数量代表列的数量
                String key = sheetKey.get(m).substring(2);
                String newKey = "get" + key.substring(0, 1).toUpperCase() + key.substring(1);//key首字母大写

                    for (int k = 0; k < declaredMethods.length; k++) {//遍历字段进行比较并添加信息//添加列信息
                        String methodName = declaredMethods[k].getName();//方法名
                        Object invoke1=null;
                        if (methodName.equals(newKey)) {//执行方法获取属性值
                             invoke1= declaredMethods[k].invoke(t);
                        }else if (entity.length>0){//如果有分装属性 A类中封装了B类 一下代码块就是执行B类中get方法
                            for (int j=0;j<entity.length;j++){
                                String s = "get"+entity[j].substring(0,1).toUpperCase()+entity[j].substring(1);
                                if (s.equals(methodName)){
                                    Object oo = declaredMethods[k].invoke(t);
                                    Method[] mes = oo.getClass().getDeclaredMethods();
                                    for (int p=0;p<mes.length;p++){
                                        if (mes[p].getName().equals(newKey)){
                                             invoke1 = mes[p].invoke(oo);
                                        }
                                    }

                                }
                            }
                        }

                        if (invoke1 instanceof String){
                            boolean matches = Pattern.matches("[0-9]*", invoke1.toString());
                            if (matches){
                                Double invoke = (Double)invoke1;
                                row2.createCell(m).setCellValue(invoke);
                            }else {
                                String invoke= (String) invoke1;
                                row2.createCell(m).setCellValue(invoke);
                            }
                        } else if (invoke1 instanceof Integer){
                            Integer invoke = (Integer) invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Short){
                            Short invoke = (Short) invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Long){
                            Long invoke = (Long)invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Boolean){
                            Boolean invoke = (Boolean)invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Double){
                            Double invoke = (Double)invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Float){
                            Float invoke = (Float)invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Byte){
                            Byte invoke = (Byte)invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Character){
                            Character invoke = (Character)invoke1;
                            row2.createCell(m).setCellValue(invoke);
                        } else if (invoke1 instanceof Date){
                            Date invoke = (Date)invoke1;
                            HSSFCell cell1 = row2.createCell(m);
                            cell1.setCellStyle(style);
                            cell1.setCellValue(invoke);
                        } else if (invoke1 instanceof java.sql.Date){
                            java.sql.Date invoke = (java.sql.Date)invoke1;
                            HSSFCell cell1 = row2.createCell(m);
                            cell1.setCellStyle(style);
                            cell1.setCellValue(invoke);
                        } //if  类型转换
                    }//for k
            }//for m
        }//for  i

        //写入到文件
        try {
            File file = new File(path + excelName + ".xlsx");
            if (!file.exists()) {
                file.createNewFile();
            }
            workbook.write(file);
            return 1;//导出成功
        } catch (FileNotFoundException e){
            e.printStackTrace();
            return 2;//目标文件被占用
        } catch (IOException e) {
            e.printStackTrace();
            return 0;//导出失败
        } catch (Exception e){
            e.printStackTrace();
            return -1;//其他异常
        }finally {
            try {
                if (workbook!=null)
                workbook.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
    

代码很简单,相信大家看的懂。有什么不明白的加我qq1490030544。

以下的伪代码是表名什么情况下不能用该类:

以上这种情况通过A类导出Excel时可以拿到B类的id,但是拿不到C类的id(虽然可以拿到C类的对象),这个后续可能我会改造一下,看时间安排吧

 

posted @ 2019-06-26 09:30  葬月!  阅读(569)  评论(0编辑  收藏  举报