美文网首页JAVA工具类程序员
POI实现通用导出Excel表格的工具(JAVA)

POI实现通用导出Excel表格的工具(JAVA)

作者: 白袜子先生 | 来源:发表于2018-04-12 16:27 被阅读109次

    需求

    一次在查看项目代码时,无意发现项目中一段导出excel文档的接口。但是导出写的很敷衍,就是纯人工导出差别不大。大概有五个类型集合的导出,每个类型都写了一个导出,整个类有2000多行代码。简直不能忍,于是就决定修改这部分代码。先搞个导出的工具类。四处查找之后 ,经过几次修改,最后成型。

    引入jar包

            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.9</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-excelant</artifactId>
                <version>3.9</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-scratchpad</artifactId>
                <version>3.9</version>
            </dependency>
    

    自定义注解

    实现导出的时候,我觉定采用注解的形式标注column name
    ,列宽 ,还有列顺序。等设置。

    package com.xescm.whc.annotation;
    
    import com.xescm.whc.utils.DateUtils;
    import lombok.Data;
    
    import java.lang.annotation.*;
    import java.lang.reflect.Field;
    import java.math.BigDecimal;
    import java.util.Date;
    
    /**
     * @author huxingnan
     * @date 2018/3/2113:30
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface ExcelColumn {
        String name() default "";//列名
        int index() default 0;//列的顺序
        short width() default 10;//列宽
    
    //注解内部类 列的配置
        @Data
        class ExcellColumnConfig{
    
            private int index;//列顺序
            private short width;//列宽
            private String columnName;//列名
            private Field field;//对应属性
        }
    // 转换器 ,本来可以设计一个接口的,但是目前能用,就没有这么设计。
        class CellDataConvertor{
            public static String convertor(Object o){
                if(o == null){return "";}
    
                if(o instanceof Date){
                   return DateUtils.getDate2String(DateUtils.YYYY_MM_DD_HH_MM_SS,(Date) o);
                }
                if(o instanceof BigDecimal){
                    return ((BigDecimal) o).toPlainString();
                }
                return o.toString();
            }
        }
    }
    
    

    工具实现

    直接上代码

    package com.xescm.whc.utils;
    
    import com.xescm.whc.annotation.ExcelColumn;
    import org.apache.poi.hssf.usermodel.*;
    import org.apache.poi.ss.usermodel.Cell;
    import java.lang.reflect.Field;
    import java.util.*;
    
    /**
     * 通用的 导出 Excel 文件
     * 需要配合 注解 ExcelColumn
     * @see ExcelColumn
     * @author huxingnan
     * @date 2018/3/21 13:14
     */
    public class ExportBeanExcelUtil {
    
        /**
         *
         * @param dtoList 数据集合
         * @param type 数据类型
         * @param title 工作薄标题
         * @param <T> 泛型类
         * @return HSSFWorkbook 对象
         */
        public static<T>  HSSFWorkbook exportExcell(List<T> dtoList,Class<T> type,String title){
            //1.解析注解  属性名 和 列名
            List<ExcelColumn.ExcellColumnConfig> columnConfigList = processAnnotation(type);//
            //2. 按照指定顺序 对列进行排序
            columnConfigList = sortColumn(columnConfigList);
            //3.创建工作薄
            HSSFWorkbook wb = new HSSFWorkbook();
            HSSFSheet sheet = wb.createSheet(title);
            //4.初始化列宽 表头
            initTableHeader(sheet,columnConfigList);
            //5. 导出数据
            createTableBody(sheet,columnConfigList,dtoList);
            return wb;
        }
    
    
        /**
         * 根据 数据 集合 创建表体
         * @param sheet 工作薄对象
         * @param columnConfigArray 排序后的
         * @param dtoList 数据集合
         * @param <T> 泛型
         */
        private static <T> void createTableBody(HSSFSheet sheet,   List<ExcelColumn.ExcellColumnConfig> columnConfigArray, List<T> dtoList) {
    
            int lineNo = 1;
            HSSFRow row;
            HSSFCell cell;
            try {
                int size = columnConfigArray.size();
                for (T t : dtoList) {
                    row = sheet.createRow(lineNo++);
                    for (int i = 0; i < size; i++) {
                        cell = row.createCell(i);
                        ExcelColumn.ExcellColumnConfig excellColumnConfig = columnConfigArray.get(i);
                        Field field = excellColumnConfig.getField();
                        field.setAccessible(true);
                        Object cellData = field.get(t);//获取数据
                        String cellDataStr = ExcelColumn.CellDataConvertor.convertor(cellData);//转换数据
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        cell.setCellValue(cellDataStr);
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
    
        /**
         * 初始化 表头 设置列宽
         * @param sheet 工作薄 对象
         * @param columnConfigArray 排序后的
         */
        private static void initTableHeader(HSSFSheet sheet, List<ExcelColumn.ExcellColumnConfig> columnConfigArray) {
            HSSFRow row = sheet.createRow(0);
            int size = columnConfigArray.size();
            HSSFCell cell;
           for (int i = 0 ; i < size;i++){
               cell = row.createCell(i, HSSFCellStyle.ALIGN_CENTER);
               ExcelColumn.ExcellColumnConfig excellColumnConfig =  columnConfigArray.get(i);
               cell.setCellType(Cell.CELL_TYPE_STRING);
               cell.setCellValue(excellColumnConfig.getColumnName());
               short width = excellColumnConfig.getWidth();
               sheet.setColumnWidth(i,width*256);
           }
        }
    
        /**
         * 解析 注解
         * @param type Class
         * @return columnConfig 集合
         */
        private static List<ExcelColumn.ExcellColumnConfig> processAnnotation(Class type){
            Field[] fields = type.getDeclaredFields();
            List<ExcelColumn.ExcellColumnConfig> columnConfigList  = new ArrayList<>();
            for (Field field : fields) {
                ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                if(annotation != null){
                    //列顺序
                    int index = annotation.index();
                    //列宽度
                    short width = annotation.width();
                    //当前列名
                    String name = annotation.name().equals("")?field.getName():annotation.name();
                    ExcelColumn.ExcellColumnConfig excellColumnConfig = new ExcelColumn.ExcellColumnConfig();
                    excellColumnConfig.setColumnName(name);
                    excellColumnConfig.setField(field);
                    excellColumnConfig.setIndex(index);
                    excellColumnConfig.setWidth(width);
                    columnConfigList.add(excellColumnConfig);
                }
            }
            return columnConfigList;
    
        }
    
        /**
         * 排序列 按照 columnConfig 中的index 排序
         *
         * @param columnConfigList columnCofig集合
         * @return columnConfig 排序后的
         */
        private static List<ExcelColumn.ExcellColumnConfig> sortColumn(List<ExcelColumn.ExcellColumnConfig> columnConfigList){
            Collections.sort(columnConfigList,new Comparator<ExcelColumn.ExcellColumnConfig>() {
                @Override
                public int compare(ExcelColumn.ExcellColumnConfig o1, ExcelColumn.ExcellColumnConfig o2) {
                    return o1.getIndex()-o2.getIndex();
                }
            });
    
            return columnConfigList;
        }
    }
    
    

    用例

    package com.xescm.whc.domain;
    
    import com.xescm.whc.annotation.ExcelColumn;
    import lombok.Data;
    
    import java.io.Serializable;
    import java.math.BigDecimal;
    import java.util.Date;
    
    /**
     * 库存冻结单
     */
    @Data
    public class WhcFrozen implements Serializable {
    
        private static final long serialVersionUID = 1826699766249042796L;
    
        /**
         * 冻结单号
         */
        @ExcelColumn(name = "冻结单号")
        private String holdOrderCode;
    
        /**
         * 批次号
         */
        @ExcelColumn(name = "批次号")
        private String lotNum;
    
        /**
         * 库位
         */
         //默认的index = 0 
        @ExcelColumn(name = "库位" index='-1')
        private String locationCode;
    
    }
    

    相关文章

      网友评论

        本文标题:POI实现通用导出Excel表格的工具(JAVA)

        本文链接:https://www.haomeiwen.com/subject/pfixkftx.html