记录一个jxl导出excel工具类

自定义注解

ExcelField

package com.hfepay.ai.platform.application.attend.annotation;

import java.lang.annotation.*;

/***
 * @ClassName: ExcelField
 * @Description: 导出注解
 * @Author: wm_yu
 * @Create_time: 9:46 2019-10-22
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelField {
    /**
     * 标题行
     */
    String title();

    /**
     * 列排序
     */
    int order() default 0;

    /**
     * 标红条件,大于改值
     */
    int colorInt() default -1;

    /**
     * 日期格式
     */
    String dateFormat() default "yyyy-MM-dd HH:mm:ss";

}

 

使用到的反射工具类:

package com.hfepay.ai.platform.application.attend.util;

import com.alibaba.druid.sql.visitor.functions.Char;
import com.hfepay.ai.platform.application.attend.annotation.ExcelField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/***
 * @ClassName: ClassReflectUtil
 * @Description: 反射工具类
 * @Author: wm_yu
 * @Create_time: 9:51 2019-10-22
 */
public class ClassReflectUtil {

    private final static Logger LOG = LoggerFactory.getLogger(ClassReflectUtil.class);

    private static final String ORDER_ARR = "order_arr";
    private static final String COLUMN_ARR = "column_arr";
    private static final String TITLE_ARR = "title_arr";

    /**
     * 根据注解获取到标题行,有排序按照排序,否则默认定义的字段顺序
     * @param clzz
     * @return
     */
    public static String[] getExcelTitle(Class<?> clzz){
        Map<String, Object> map = sort(clzz);
        return Optional.ofNullable(map).map(x -> (String[])x.get(TITLE_ARR)).orElse(new String[1]);
    }

    /**
     * 获取导出列(已排序)
     * @param clzz
     * @return
     */
    public static String[] getColumns(Class<?> clzz){
        Map<String, Object> map = sort(clzz);
        return Optional.ofNullable(map).map(x -> (String[])x.get(COLUMN_ARR)).orElse(new String[1]);
    }

    /**
     * 根据注解ExcelField对字段进行排序,生成排序数组,标题数组,列名数组
     * @param clzz
     * @return
     */
    private static Map<String,Object> sort(Class clzz){
        Assert.notNull(clzz,"class can not be null....");
        Field[] fields = getAllFields(clzz);
        long count = Arrays.stream(fields).filter(x -> x.isAnnotationPresent(ExcelField.class)).count();
        //排序数组
        int[] orderArr = new int[(int)count];
        //严格和排序对应的标题数组
        String[] titleArr = new String[(int)count];
        //严格和排序对应的对象列名称的数组
        String[] columnArr = new String[(int)count];

        int k = 0;
        for (Field field : fields) {
            if(field.isAnnotationPresent(ExcelField.class)){
                if(field.isAccessible()){
                    field.setAccessible(true);
                }
                ExcelField annotation = field.getAnnotation(ExcelField.class);
                orderArr[k] = annotation.order();
                titleArr[k] = annotation.title();
                columnArr[k] = field.getName();
                k ++;
            }
        }
        //排序
        for (int i = 0; i < orderArr.length; i++) {
            boolean flag = false;
            for (int j = 0; j < orderArr.length - i - 1; j++) {
                if(orderArr[j] > orderArr[j+1]){
                    int order = orderArr[j+1];
                    orderArr[j+1] = orderArr[j];
                    orderArr[j] = order;

                    String title = titleArr[j+1];
                    titleArr[j+1] = titleArr[j];
                    titleArr[j] = title;

                    String columnName = columnArr[j+1];
                    columnArr[j+1] = columnArr[j];
                    columnArr[j] = columnName;

                    flag = true;
                }
            }
            if(!flag){
                break;
            }
        }
       Map<String, Object> map = new HashMap<>(3);
        map.put(ORDER_ARR,orderArr);
        map.put(COLUMN_ARR,columnArr);
        map.put(TITLE_ARR,titleArr);
        return map;
    }

    /**
     * 获取类所有字段(含超类字段)
     * @param c
     * @return
     */
    public static Field[] getAllFields(Class c){
        List<Field> fieldList = new ArrayList<>();
        while (c!= null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(c.getDeclaredFields())));
            c= c.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    /**
     * 给null值给定默认值,时间类型排除不处理
     */
    public static <T> void nullToDefaultValue(T obj){
        Assert.notNull(obj,"source can not be null.....");
        Field[] fields = ClassReflectUtil.getAllFields(obj.getClass());
        Arrays.stream(fields)
                .filter(x -> !Modifier.isFinal(x.getModifiers())
                && !Modifier.isStatic(x.getModifiers())
                &&!Modifier.isAbstract(x.getModifiers()))
                .forEach(x -> {
                    autoMatch(x,obj);
                });
    }

    /**
     * 类型匹配
     * @param x 字段Field
     * @param obj 对象
     * @param <T>
     */
    private static <T> void autoMatch(Field x,T obj){
        if(!x.isAccessible()){
            x.setAccessible(true);
        }
        try {
            Object o = x.get(obj);
            //null值处理
            if(ObjectUtils.isEmpty(o)){
                Class<?> type = x.getType();
                if(type == Date.class){
                    return;
                }
                if(type == String.class){
                    x.set(obj,"");
                }
                else if(type == Integer.class){
                    x.set(obj,0);
                }
                else if(type == Double.class){
                    x.set(obj,0.0D);
                }
                else  if(type == BigDecimal.class){
                    x.set(obj,new BigDecimal(0));
                }
                else if(type == Float.class){
                    x.set(obj,0.0f);
                }
                else if(type == Long.class){
                    x.set(obj,0L);
                }
                else if(type == HashMap.class){
                    x.set(obj,new HashMap<>(1));
                }
                else if(type == Boolean.class){
                    x.set(obj,false);
                }
                else  if(type == Short.class){
                    x.set(obj,0);
                }
                else if(type == Char.class){
                    x.set(obj,0);
                }
                else if(type == Byte.class){
                    x.set(obj,0);
                }
                else  if(type == ConcurrentMap.class){
                    x.set(obj,new ConcurrentHashMap<>(1));
                }
                else if(type.isArray()){
                    Object[] arr = {};
                    x.set(obj,arr);
                } else if(type == List.class){
                    x.set(obj,Collections.EMPTY_LIST);
                }else{
                    Object var = x.getType().newInstance();
                    x.set(obj,var);
                }
            }
        } catch (IllegalAccessException | InstantiationException e) {
            LOG.error("对象属性:{} 不能通过反射获取到值",x.toGenericString(),e.getMessage(),e);
        }
    }
}

 

excel导出工具类:excelUtil.java

package com.hfepay.ai.platform.application.attend.util.excel;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.hfepay.ai.platform.application.attend.annotation.ExcelField;
import com.hfepay.ai.platform.application.attend.util.ClassReflectUtil;
import com.hfepay.common.util.DateUtils;
import jxl.Workbook;
import jxl.write.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/***
 * @ClassName: ExcelUtil
 * @Description: 导出工具类
 * @Author: wm_yu
 * @Create_time: 15:25 2019-10-22
 */
public class ExcelUtil {

    private final static Logger LOG = LoggerFactory.getLogger(ExcelUtil.class);

    /**
     * excel单元格宽度,默认为20
     */
    private static int width = 20;

    /**
     * 导出excel文件,浏览器直接下载
     * @param response response流
     * @param dataList 填充的数据集合,需要指定泛型
     * @param sheetName sheet名称
     * @param fileName  下载的文件名称
     * @param bigTitle 大标题行,限定为第一行
     * @param <T>
     */
    public static <T> void excelExport(HttpServletResponse response,List<T> dataList,String sheetName,String fileName,String bigTitle){
        if(CollectionUtils.isEmpty(dataList)){
            return;
        }
        Class<?> clzz = dataList.get(0).getClass();
        //属性集合
        Field[] fields = ClassReflectUtil.getAllFields(clzz);
        List<Field> fieldList = Arrays.stream(fields).filter(x -> x.isAnnotationPresent(ExcelField.class)).collect(Collectors.toList());
        //维护列名称和对应的索引,填充cell使用
        Map<String, Integer> map = new ConcurrentHashMap<>();
        /**
         * 列名称数组
         */
        String[] columnArr = ClassReflectUtil.getColumns(clzz);
        /**
         * 标题行数组
         */
        String[] titleArr = ClassReflectUtil.getExcelTitle(clzz);
        //构建map
        for (int i = 0; i < columnArr.length; i++) {
            map.put(columnArr[i],i);
        }
        ServletOutputStream os = null;
        try {
            os = response.getOutputStream();
            //创建workbook,sheet
            WritableWorkbook workbook = Workbook.createWorkbook(response.getOutputStream());
            //第一个sheet
            WritableSheet sheet = workbook.createSheet(sheetName, 0);
            //固定大小标题行
            sheet.getSettings().setVerticalFreeze(1);
            sheet.getSettings().setVerticalFreeze(2);
           //初始化样式
            List<WritableCellFormat> styleList = initStyleFormat();
            //构建大标题行,需要合并单元格  合并单元格,参数依次为:列索引、行索引、列索引+需要合并的列的个数、行索引+需要合并的行的个数
            sheet.mergeCells(0,0,columnArr.length - 1,0);
            Label bigLabel = new Label(0, 0, bigTitle, styleList.get(0));
            sheet.addCell(bigLabel);

            for (int i = 0; i < titleArr.length; i++) {
                Label excelTitle = new Label(i, 1, titleArr[i], styleList.get(0));
                sheet.addCell(excelTitle);
                // 设置列宽
                sheet.setColumnView(i, width);
            }
            /*****************填充数据*********************/
            //数据行从第三行开始,第一行为大标题行,第二行为小标题行
            int rowIndex = 2;
            for (T data : dataList) {
                //循环field
                for (Field field : fieldList) {
                    if(!field.isAccessible()){
                        field.setAccessible(true);
                    }
                    //判断是否需要标红数据
                    String dateFormat = field.getAnnotation(ExcelField.class).dateFormat();
                    int colorInt = field.getAnnotation(ExcelField.class).colorInt();
                    Object o = field.get(data);
                     Label label = null;
                    if(!ObjectUtils.isEmpty(o)){
                        if(o instanceof String){
                            //创建单元格,正常样式
                            label = new Label(map.get(field.getName()), rowIndex,(String) o,styleList.get(1));
                        }
                        else if(o instanceof Integer){
                            //排除默认值
                            if((Integer)o > colorInt && colorInt != -1){
                                //数据标红
                                label = new Label(map.get(field.getName()),rowIndex, String.valueOf(o),styleList.get(2));
                            }else{
                              label = new Label(map.get(field.getName()),rowIndex, String.valueOf(o),styleList.get(1));
                            }
                        }
                        else if(o instanceof Date){
                            label = new Label(map.get(field.getName()),rowIndex, DateUtils.format((Date) o,dateFormat),styleList.get(1));
                        }else {
                            label = new Label(map.get(field.getName()), rowIndex,String.valueOf(o),styleList.get(1));
                        }
                    //添加到行中
                    sheet.addCell(label);
                    }
                }
                ++ rowIndex;
            }
            /*****************填充数据*********************/
            //导出excel
            // 处理中文的文件名
            String fileNameCN = new String(fileName.getBytes("utf-8"),
                    "ISO-8859-1");
            response.reset();
            // 保存为excel
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.addHeader("Content-Disposition", "attachment;filename="
                    + fileNameCN);
            workbook.write(); // 写入到os流中
            workbook.close();
            os.flush();
            os.close();
        } catch (Exception e) {
            LOG.error("导出excel异常:{}",e.getMessage(),e);
        }
     }



    /**
     * 初始化样式
     * @return
     * @throws Exception
     */
    private static List<WritableCellFormat> initStyleFormat() throws Exception{
        // 列标题字体
        WritableFont wfont = new WritableFont(WritableFont.ARIAL, 16,WritableFont.BOLD, false,jxl.format.UnderlineStyle.NO_UNDERLINE,jxl.format.Colour.BLACK);
        // 列标题字体 绿色
        WritableFont wfontGreenTitle = new WritableFont(WritableFont.ARIAL, 16,WritableFont.BOLD, false,jxl.format.UnderlineStyle.NO_UNDERLINE,jxl.format.Colour.GREEN);
        // 正常字体
        WritableFont wfont2 = new WritableFont(WritableFont.ARIAL, 10,WritableFont.NO_BOLD, false,jxl.format.UnderlineStyle.NO_UNDERLINE,jxl.format.Colour.BLACK);
        // 正常字体,标红
        WritableFont wfontRed = new WritableFont(WritableFont.ARIAL, 10,WritableFont.NO_BOLD, false,jxl.format.UnderlineStyle.NO_UNDERLINE,jxl.format.Colour.RED);
        // 正常字体,绿色
        WritableFont wfontGreen = new WritableFont(WritableFont.ARIAL, 10,WritableFont.NO_BOLD, false,jxl.format.UnderlineStyle.NO_UNDERLINE,jxl.format.Colour.GREEN);

        WritableCellFormat titleFormat = new WritableCellFormat(wfont);
        titleFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        titleFormat.setAlignment(Alignment.CENTRE);
        //给单元格加边框
        titleFormat.setBorder(jxl.format.Border.ALL,jxl.format.BorderLineStyle.THIN);

        WritableCellFormat generalFormat = new WritableCellFormat(wfont2);
        generalFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        generalFormat.setAlignment(Alignment.CENTRE);
        //给单元格加边框
        generalFormat.setBorder(jxl.format.Border.ALL,jxl.format.BorderLineStyle.THIN);

        WritableCellFormat redFormat = new WritableCellFormat(wfontRed);
        redFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        redFormat.setAlignment(Alignment.CENTRE);
        redFormat.setBorder(jxl.format.Border.ALL,jxl.format.BorderLineStyle.THIN);

        WritableCellFormat greenFormat = new WritableCellFormat(wfontGreen);
        greenFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        greenFormat.setAlignment(Alignment.CENTRE);
        greenFormat.setBorder(jxl.format.Border.ALL,jxl.format.BorderLineStyle.THIN);

        WritableCellFormat greenTitleFormat = new WritableCellFormat(wfontGreenTitle);
        greenTitleFormat.setVerticalAlignment(VerticalAlignment.CENTRE);
        greenTitleFormat.setAlignment(Alignment.CENTRE);
        greenFormat.setBorder(jxl.format.Border.ALL,jxl.format.BorderLineStyle.THIN);

        List<WritableCellFormat> list = new ArrayList<WritableCellFormat>(){{
            add(titleFormat);
            add(generalFormat);
            add(redFormat);
            add(greenFormat);
            add(greenTitleFormat);
        }};
        return list;
    }

















    }


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章