• easypoi多级表头、多个sheet导出,动态导出列


    一、多级表头和多个sheet

    🧐 效果

    在这里插入图片描述

    因为这里是用注解实现的,只有到三级表头,如果表头超过了三级,比如有四级、五级的话,就不建议用注解,还是用模板比较方便。

    🍔 代码

    多级表头一个是可以用注解实现:@ExcelCollection 和 @Excel 组合使用还有就是可以用模板实现;还有一种就是用原生poi写,这个就更麻烦了。模板实现就更灵活,很复杂的表格都可以实现,不过就是填充数据比较麻烦。这里先写用注解实现的方式。

    1、实体bean

    import cn.afterturn.easypoi.excel.annotation.Excel;
    import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
    import lombok.Data;
    
    import java.util.List;
    
    @Data
    public class ExcelExportVo {
    	
    	// 这两个就是一级表头,最后一级表头对应的是具体的某个属性,它们都是被包裹在一级表头下的
        @ExcelCollection(name = "用户信息")
        private List<UserInfo> userInfoList;
    
        @ExcelCollection(name = "用户角色和权限")
        private List<RoleInfo> roleInfoList;
    
        /**
         * 用户信息
         */
        @Data
        public static class UserInfo{
        	// 二级表头可以用 groupName 实现
            @Excel(name = "用户账号",width = 20,groupName = "基本信息")
            private String userName;
    
            @Excel(name = "用户姓名",width = 20,groupName = "基本信息")
            private String realName;
    
            @Excel(name = "手机号码",width = 20,groupName = "基本信息")
            private String phone;
    
            @Excel(name = "所在公司",width = 20,groupName = "单位部门")
            private String com;
    
            @Excel(name = "所在部门",width = 20,groupName = "单位部门")
            private String dept;
    
            public UserInfo(String userName, String realName, String phone, String com, String dept) {
                this.userName = userName;
                this.realName = realName;
                this.phone = phone;
                this.com = com;
                this.dept = dept;
            }
        }
    
        /**
         * 用户角色权限
         */
        @Data
        public static class RoleInfo{
            @Excel(name = "所属角色名称",width = 20,groupName = "角色")
            private String roleName;
    
            @Excel(name = "所属角色代码",width = 20,groupName = "角色")
            private String roleCode;
    
            @Excel(name = "菜单权限",width = 40,groupName = "权限")
            private String menu;
    
            @Excel(name = "数据权限",width = 40,groupName = "权限")
            private String data;
    
            public RoleInfo(String roleName, String roleCode, String menu, String data) {
                this.roleName = roleName;
                this.roleCode = roleCode;
                this.menu = menu;
                this.data = data;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    2、ExcelUtil、ExcelStyleUtil

    import cn.afterturn.easypoi.excel.ExcelExportUtil;
    import cn.afterturn.easypoi.excel.ExcelImportUtil;
    import cn.afterturn.easypoi.excel.annotation.Excel;
    import cn.afterturn.easypoi.excel.entity.ExportParams;
    import cn.afterturn.easypoi.excel.entity.ImportParams;
    import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
    import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
    import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
    import cn.afterturn.easypoi.excel.imports.ExcelImportService;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.springframework.web.multipart.MultipartFile;
    import sun.misc.BASE64Decoder;
    
    import javax.imageio.ImageIO;
    import javax.servlet.http.HttpServletResponse;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.lang.reflect.Field;
    import java.net.URLEncoder;
    import java.util.*;
    
    /**
     * excel操作工具类
     */
    public class ExcelUtil {
    
        /**
         * 偶数行设置背景色
         */
        private static void setRowBackground(Workbook workbook){
            Sheet sheet = workbook.getSheetAt(0);
            CellStyle styles = ExcelStyleUtil.getStyles(workbook,false,(short) 12);
            for(int i = 0; i <= sheet.getLastRowNum(); i ++) {
                Row row = sheet.getRow(i);
                if (i%2==0){
                    for(int j = 0; j < row.getPhysicalNumberOfCells(); j ++) {
                        Cell cell = row.getCell(j);
                        cell.setCellStyle(styles);
                    }
                }
            }
        }
    
        /**
         * 导出设置隔行背景色
         * @param params 导出参数
         * @param list 数据
         * @param pojoClass pojo类型
         * @param fileName 文件名称
         * @param isSetRowBackground 是否设置隔行背景色
         */
        public static void exportExcel(ExportParams params, List<?> list, Class<?> pojoClass, String fileName,boolean isSetRowBackground, HttpServletResponse response){
            Workbook workbook = ExcelExportUtil.exportExcel(params,pojoClass,list);
            if (workbook != null);
            if (isSetRowBackground) setRowBackground(workbook);
            downLoadExcel(fileName, response, workbook);
        }
    
        /**
         * excel 导出
         * @param list           数据
         * @param title          标题
         * @param sheetName      sheet名称
         * @param pojoClass      pojo类型
         * @param fileName       文件名称
         */
        public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response){
            ExportParams exportParams = new ExportParams(title, sheetName, ExcelType.XSSF);
            exportParams.setStyle(ExcelStyleUtil.class);
            defaultExport(list, pojoClass, fileName, response, exportParams);
        }
    
        /**
         * excel 导出
         * @param list           数据
         * @param pojoClass      pojo类型
         * @param fileName       文件名称
         */
        public static void exportExcel(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response){
            ExportParams exportParams = new ExportParams();
            exportParams.setStyle(ExcelStyleUtil.class);
            defaultExport(list, pojoClass, fileName, response, exportParams);
        }
    
        /**
         * list map 导出
         * @param list     数据
         * @param fileName 文件名称
         */
        public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response){
            ExportParams exportParams = new ExportParams();
            exportParams.setStyle(ExcelStyleUtil.class);
            defaultExport(list, fileName, response);
        }
    
        /**
         * 默认的 excel 导出
         * @param list         数据
         * @param pojoClass    pojo类型
         * @param fileName     文件名称
         * @param exportParams 导出参数
         */
        private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams){
            Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
            downLoadExcel(fileName, response, workbook);
        }
    
        /**
         * 默认的 excel 导出
         * @param list     数据
         * @param fileName 文件名称
         */
        private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response){
            Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.XSSF);
            downLoadExcel(fileName, response, workbook);
        }
    
        /**
         * 下载
         * @param fileName 文件名称
         * @param response
         * @param workbook excel数据
         */
        public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook){
            try {
                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-Type", "application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + "." + ExcelTypeEnum.XLS.getValue(), "UTF-8"));
                workbook.write(response.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        /**
         * excel 导入
         * @param filePath   excel文件路径
         * @param titleRows  标题行
         * @param headerRows 表头行
         * @param pojoClass  pojo类型
         */
        public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
            if (StringUtils.isBlank(filePath)) {
                return null;
            }
            ImportParams params = new ImportParams();
            params.setTitleRows(titleRows);
            params.setHeadRows(headerRows);
            params.setNeedSave(true);
            params.setSaveUrl("/excel/");
            try {
                return ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
            } catch (NoSuchElementException e) {
                throw new IOException("模板不能为空");
            } catch (Exception e) {
                throw new IOException(e.getMessage());
            }
        }
    
        /**
         * excel 导入
         * @param file       上传的文件
         * @param titleRows  标题行
         * @param headerRows 表头行
         * @param needVerify 是否检验excel内容
         * @param pojoClass  pojo类型
         */
        public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, boolean needVerify, Class<T> pojoClass) throws IOException {
            if (file == null) {
                return null;
            }
            try {
                return importExcel(file.getInputStream(), titleRows, headerRows, needVerify, pojoClass);
            } catch (Exception e) {
                throw new IOException(e.getMessage());
            }
        }
    
        /**
         * excel 导入
         * @param inputStream 文件输入流
         * @param titleRows   标题行
         * @param headerRows  表头行
         * @param needVerify  是否检验excel内容
         * @param pojoClass   pojo类型
         */
        public static <T> List<T> importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, boolean needVerify, Class<T> pojoClass) throws IOException {
            if (inputStream == null) {
                return null;
            }
            ImportParams params = new ImportParams();
            params.setTitleRows(titleRows);
            params.setHeadRows(headerRows);
            params.setSaveUrl("upload/excel/");
            params.setNeedSave(true);
            params.setNeedVerify(needVerify);
            try {
                return ExcelImportUtil.importExcel(inputStream, pojoClass, params);
            } catch (NoSuchElementException e) {
                throw new IOException("excel文件不能为空");
            } catch (Exception e) {
                throw new IOException(e.getMessage());
            }
        }
    
        /**
         * Excel 类型枚举
         */
        enum ExcelTypeEnum {
            XLS("xls"), XLSX("xlsx");
            private String value;
    
            ExcelTypeEnum(String value) {
                this.value = value;
            }
    
            public String getValue() {
                return value;
            }
    
            public void setValue(String value) {
                this.value = value;
            }
        }
    
    
        /**
         * 上传文件,返回一个workbook
         * @param file
         */
        public static Workbook importExcel(MultipartFile file) throws IOException {
            File toFile = new File(file.getOriginalFilename());
            Workbook workbook = null;
            if(toFile.getPath().endsWith("xls")){
                workbook = new HSSFWorkbook(file.getInputStream());
            }else if(toFile.getPath().endsWith("xlsx")){
                workbook = new XSSFWorkbook(file.getInputStream());
            }else {
                throw new RuntimeException("请确认你上传的文件类型");
            }
            return workbook;
        }
    
        /**
         * 读取指定sheet的数据
         * @param file 上传的文件
         * @param sheetName 要读取的sheetName
         * @param titleRows 表头行数
         * @param headRows 标题行数
         * @param startRows 表头之前有多少行不要的数据,从1开始,忽略空行
         * @param readRows 要读取多少行数据,从0开始,比如读取十行,值就是9; 不指定时默认为0
         * @param pojoClass 实体
         */
        public static <T> List<T> importExcel(MultipartFile file,String sheetName,Integer titleRows,Integer headRows, Integer startRows,Integer readRows,Class<T> pojoClass) throws Exception {
            Workbook workbook = importExcel(file);
            int numberOfSheets = workbook.getNumberOfSheets();
            List<T> list = null;
            for (int i = 0; i < numberOfSheets; i++) {
                String name = workbook.getSheetName(i).trim();
                if (name.equals(sheetName) || name.endsWith(sheetName)){
                    ImportParams params = new ImportParams();
                    params.setTitleRows(titleRows);
                    params.setHeadRows(headRows);
                    params.setStartRows(startRows);
                    params.setReadRows(readRows);
                    //第几个sheet页
                    params.setStartSheetIndex(i);
                    final ExcelImportService excelImportService = new ExcelImportService();
                    ExcelImportResult<T> result = excelImportService.importExcelByIs(file.getInputStream(), pojoClass, params, false);
                    list = result.getList();
                    break;
                }
            }
            return list;
        }
    
        /**
         * 以map的形式导出表格
         * @param list 数据
         */
        public static <T> List<Map<String, Object>> objectToMap(List<T> list){
            List<Map<String, Object>> result = new ArrayList<>();
            Map<String, Object> map = null;
            try {
                for (T item : list) {
                    map = new HashMap<>();
                    Class<?> clazz = item.getClass();
                    for (Field field : clazz.getDeclaredFields()) {
                        field.setAccessible(true);
                        String fieldName = field.getName();
                        Object value = field.get(item);
                        map.put(fieldName, value);
                    }
                    result.add(map);
                }
                return result;
            }catch (IllegalAccessException e){
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 动态导出列,根据Excel注解获取列的字段注释(表头名)、宽度
         * @param clazz
         * @param fields 选择要导出的列
         */
        public static List<ExcelExportEntity> dynamicExport(Class<?> clazz,String fields) {
            List<ExcelExportEntity> beanList = new ArrayList<>();
            String[] split = fields.split(",");
            int length = split.length;
            try {
                for (int i = 0; i < length; i++) {
                    Field f = clazz.getDeclaredField(split[i]);
                    Excel annotation = f.getAnnotation((Excel.class));
                    String comment = annotation.name();
                    Double width = annotation.width();
                    beanList.add(new ExcelExportEntity(comment, f.getName(),width.intValue()));
                }
            }catch (NoSuchFieldException e){
                e.printStackTrace();
            }
            return beanList;
        }
    
        /**
         * 导出Excel,并在最后追加图片
         * @param sheetName sheet名称
         * @param wb        HSSFWorkbook对象
         */
        public static Workbook getWorkbook(String sheetName,Workbook wb, String imgUrl) throws IOException {
            // 第一步,创建一个HSSFWorkbook,对应一个Excel文件
            if (wb == null) {
                wb = new HSSFWorkbook();
            }
            // 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
            Sheet sheet = wb.getSheet(sheetName);
            /*生成图表*/
            if(!StringUtils.isEmpty(imgUrl)) {
                String[] imgUrlArr = imgUrl.split("base64,");//拆分base64编码后部分
                byte[] buffer = new BASE64Decoder().decodeBuffer(imgUrlArr[1]);
                String picPath = System.getProperty("user.dir")+"\\upload\\image\\pic.png";
                File file = new File(picPath);//图片文件
                try {
                    //生成图片
                    OutputStream out = new FileOutputStream(file);//图片输出流
                    out.write(buffer);
                    out.flush();//清空流
                    out.close();//关闭流
                    ByteArrayOutputStream outStream = new ByteArrayOutputStream(); // 将图片写入流中
                    BufferedImage bufferImg = ImageIO.read(new File(picPath));
                    ImageIO.write(bufferImg, "PNG", outStream);
                    // 利用HSSFPatriarch将图片写入EXCEL
                    Drawing<?> drawing = sheet.createDrawingPatriarch();
                    //位置:第1个单元格中x轴的偏移量、第1个单元格中y轴的偏移量、 第2个单元格中x轴的偏移量、 第2个单元格中y轴的偏移量、第1个单元格的列号、第1个单元格的行号、 第2个单元格的列号、第2个单元格的行号
                    //HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 0, 8, (short) 10, 40);
                    ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 6, 9, 40);
                    drawing.createPicture(anchor, wb.addPicture(outStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                if (file.exists()) {
                    file.delete();//删除图片
                }
            }
            return wb;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
    import cn.afterturn.easypoi.excel.entity.params.ExcelForEachParams;
    import cn.afterturn.easypoi.excel.export.styler.IExcelExportStyler;
    import org.apache.poi.ss.usermodel.*;
    
    /**
     * excel导出样式设置工具类
     */
    public class ExcelStyleUtil implements IExcelExportStyler {
    
        private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
        private static final short FONT_SIZE_TEN = 12;
        private static final short FONT_SIZE_ELEVEN = 14;
        private static final short FONT_SIZE_TWELVE = 18;
    
        /**
         * 大标题样式
         */
        private CellStyle headerStyle;
        /**
         * 每列标题样式
         */
        private CellStyle titleStyle;
        /**
         * 数据行样式
         */
        private CellStyle styles;
    
        public ExcelStyleUtil(Workbook workbook) {
            this.init(workbook);
        }
    
        /**
         * 初始化样式
         * @param workbook
         */
        private void init(Workbook workbook) {
            this.headerStyle = initHeaderStyle(workbook);
            this.titleStyle = initTitleStyle(workbook,true,FONT_SIZE_ELEVEN);
            this.styles = initStyles(workbook);
        }
    
        @Override
        public CellStyle getHeaderStyle(short i) {
            return headerStyle;
        }
    
        @Override
        public CellStyle getTitleStyle(short i) {
            return titleStyle;
        }
    
        @Override
        public CellStyle getTemplateStyles(boolean b, ExcelForEachParams excelForEachParams) {
            return null;
        }
    
        @Override
        public CellStyle getStyles(boolean b, ExcelExportEntity excelExportEntity) {
            return styles;
        }
    
        @Override
        public CellStyle getStyles(Cell cell, int i, ExcelExportEntity entity, Object o, Object o1) {
            return getStyles(true, entity);
        }
    
        /**
         * 设置隔行背景色
         */
        public static CellStyle getStyles(Workbook workbook,boolean isBold,short size) {
            CellStyle style = initTitleStyle(workbook,isBold,size);
            style.setDataFormat(STRING_FORMAT);
            return style;
        }
    
        /**
         * 初始化--大标题样式
         */
        private static CellStyle initHeaderStyle(Workbook workbook) {
            CellStyle style = getBaseCellStyle(workbook);
            style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true));
            return style;
        }
    
        /**
         * 初始化--每列标题样式
         */
        private static CellStyle initTitleStyle(Workbook workbook,boolean isBold,short size) {
            CellStyle style = getBaseCellStyle(workbook);
            style.setFont(getFont(workbook, size, isBold));
            //背景色
            style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            return style;
        }
    
        /**
         * 初始化--数据行样式
         */
        private static CellStyle initStyles(Workbook workbook) {
            CellStyle style = getBaseCellStyle(workbook);
            style.setFont(getFont(workbook, FONT_SIZE_TEN, false));
            style.setDataFormat(STRING_FORMAT);
            return style;
        }
    
        /**
         * 基础样式
         */
        private static CellStyle getBaseCellStyle(Workbook workbook) {
            CellStyle style = workbook.createCellStyle();
            //下边框
            style.setBorderBottom(BorderStyle.THIN);
            //左边框
            style.setBorderLeft(BorderStyle.THIN);
            //上边框
            style.setBorderTop(BorderStyle.THIN);
            //右边框
            style.setBorderRight(BorderStyle.THIN);
            //水平居中
            style.setAlignment(HorizontalAlignment.CENTER);
            //上下居中
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            //设置自动换行
            style.setWrapText(true);
            return style;
        }
    
        /**
         * 字体样式
         * @param size   字体大小
         * @param isBold 是否加粗
         */
        private static Font getFont(Workbook workbook, short size, boolean isBold) {
            Font font = workbook.createFont();
            //字体样式
            font.setFontName("宋体");
            //是否加粗
            font.setBold(isBold);
            //字体大小
            font.setFontHeightInPoints(size);
            return font;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145

    3、导出

    import cn.afterturn.easypoi.excel.ExcelExportUtil;
    import cn.afterturn.easypoi.excel.entity.ExportParams;
    import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
    import com.common.util.ExcelStyleUtil;
    import com.common.util.ExcelUtil;
    import com.entity.sys.query.ExcelExportVo;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletResponse;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @RestController
    @RequestMapping("/api/test")
    public class TestController {
    
        /**
         * 多级表头、多个sheet导出
         */
        @RequestMapping("/export")
        public void export(HttpServletResponse response){
        	// 模拟数据
            List<ExcelExportVo> dataList = new ArrayList<>();
            List<ExcelExportVo.UserInfo> userInfoList = new ArrayList<>();
            List<ExcelExportVo.RoleInfo> roleInfoList = new ArrayList<>();
            userInfoList.add(new ExcelExportVo.UserInfo("chenyi","陈仪","12345678910","战神联盟","科研部"));
            userInfoList.add(new ExcelExportVo.UserInfo("honger","洪洱","13241220000","前途有限公司","市场部"));
            userInfoList.add(new ExcelExportVo.UserInfo("zhangsan","张三","12544445555","前途有限公司","研发部"));
            userInfoList.add(new ExcelExportVo.UserInfo("lisi","李四","13125223561","战神联盟","科研部"));
            userInfoList.add(new ExcelExportVo.UserInfo("wangwu","王五","15423226355","战神联盟","销售部"));
    
            roleInfoList.add(new ExcelExportVo.RoleInfo("经理","JL","sys,dept,role,menu","view,add,update,delete"));
            roleInfoList.add(new ExcelExportVo.RoleInfo("经理","JL","sys,dept,role,menu","view,add,update,delete"));
            roleInfoList.add(new ExcelExportVo.RoleInfo("组长","ZZ","role,menu","view,add,update"));
            roleInfoList.add(new ExcelExportVo.RoleInfo("普通","PT","menu","view,add"));
            roleInfoList.add(new ExcelExportVo.RoleInfo("普通","PT","menu","view,add"));
    
            ExcelExportVo vo = new ExcelExportVo();
            vo.setUserInfoList(userInfoList);
            vo.setRoleInfoList(roleInfoList);
            dataList.add(vo);
    
            // 第一个sheet
            ExportParams params1 = new ExportParams();
            params1.setStyle(ExcelStyleUtil.class);
            params1.setSheetName("用户信息1");
            params1.setTitle("用户信息");
            Map<String, Object> params1Map = new HashMap<>();
            params1Map.put("title", params1);
            params1Map.put("entity", ExcelExportVo.class);
            params1Map.put("data", dataList);
    
            // 第二个sheet
            ExportParams params2 = new ExportParams();
            params2.setStyle(ExcelStyleUtil.class);
            params2.setSheetName("用户信息2");
            Map<String, Object> params2Map = new HashMap<>();
            params2Map.put("title", params2);
            params2Map.put("entity", ExcelExportVo.class);
            params2Map.put("data", new ArrayList<>());
    
            // 第三个sheet
            ExportParams params3 = new ExportParams();
            params3.setStyle(ExcelStyleUtil.class);
            params3.setSheetName("用户信息3");
            Map<String, Object> params3Map = new HashMap<>();
            params3Map.put("title", params3);
            params3Map.put("entity", ExcelExportVo.class);
            params3Map.put("data", new ArrayList<>());
    		
    		// 将3个sheet封装
            List<Map<String, Object>> sheetsList = new ArrayList<>();
            sheetsList.add(params1Map);
            sheetsList.add(params2Map);
            sheetsList.add(params3Map);
            Workbook workBook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF);
            ExcelUtil.downLoadExcel("用户信息",response,workBook);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    二、模板导出

    关于模板导出,其他倒没什么,主要是填充数据比较麻烦,此外还有一个要注意的点,就是关于数据横向遍历,也就是列遍历,就是新建列而不是新建行。

    横向遍历,模板的语法是用 #fe,然后还需要在代码中手动开启列遍历。(之前我看文档上写的这个语法是横向遍历的,但是我用了一直不起作用,后面找啊找,终于在网上找到原因了)

    {{#fe:headList t.name }}
    
    • 1
    String excelPath = System.getProperty("user.dir")+"\\src\\main\\resources\\template\\1.xls";
    TemplateExportParams params = new TemplateExportParams(excelPath);
    // 就是这一句,必须要设置为 true
    params.setColForEach(true);
    
    • 1
    • 2
    • 3
    • 4

    三、动态导出不同列

    就是有的时候有某列或者某几列不符合条件,不要导出。

    举个🌰:
    1、就比如有两个页面,它们的数据来源、字段其实都是一个表的,但是因为有一些条件,页面1只展示符合条件xx的数据,页面2只展示符合条件xxx的数据,而且展示的字段也不尽相同;

    2、还有一个假如根据天数来导出数据,每一天作为列,但是每个月的天数都不一样,要怎么根据月份的天数去导出正确的列数呢?

    我们可以用 ExcelExportEntity@Excel 来实现。

    思路:案例1因为两个页面数据都是同一个数据库表的数据,所以实体bean也是同一个。我们可以把两个页面要导出的字段都注解上@Excel,然后点击导出,调用接口的时候,控制哪个页面要导出哪几个字段。

    // 这里简单说一下,比如实体bean有这几个字段:姓名、性别、年龄、手机、邮箱。
    // 页面1 要导出 姓名、性别、年龄 这几个字段;页面2 要导出 姓名、手机、邮箱 这几个字段。
    // 那么在controller中,直接把这几个字段名用逗号隔开拼接就行,调用 ExcelUtil.dynamicExport 方法,会创建动态列的表头。
    
    • 1
    • 2
    • 3

    下面这里详细讲一下案例2。

    🍟 根据天数动态导出列

    @Data
    public class TemplateVo {
    	// 这里只导出25号以后的天数(不然的话字段太多了,这里只是举个栗子,具体字段看实际情况)
        @Excel(name = "25日",width = 12)
        private String day1;
        @Excel(name = "26日",width = 12)
        private String day2;
        @Excel(name = "27日",width = 12)
        private String day3;
        @Excel(name = "28日",width = 12)
        private String day4;
        @Excel(name = "29日",width = 12)
        private String day5;
        @Excel(name = "30日",width = 12)
        private String day6;
        @Excel(name = "31日",width = 12)
        private String day7;
    
        public TemplateVo(String day1, String day2, String day3, String day4, String day5, String day6, String day7) {
            this.day1 = day1;
            this.day2 = day2;
            this.day3 = day3;
            this.day4 = day4;
            this.day5 = day5;
            this.day6 = day6;
            this.day7 = day7;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    /**
     * 根据年月获取需要导出的列
     */
    private String getExportColumn(int year,int month){
        String column = "";
        String date = year+"-"+month+"-25";
        LocalDate parse = LocalDateTimeUtil.parseDate(date,"yyyy-M-dd");
        // 获取这个月份的长度,也就是天数
        int length = parse.lengthOfMonth();
        // 因为是导出25号(包括25号)以后的天数,所以需要 总天数-25+1
        int day = length-25+1;
        // 25号到31号总共7天,遍历7次,拼接要导出的列名
        for (int i = 1; i <= 7; i++) {
            if (i<day) column += "day"+i+",";
            else if (i==day) column += "day"+i;
        }
        return column;
    }
    
    /**
     * 导出动态列
     */
    @RequestMapping("/dynamicColumnExport")
    public void dynamicColumnExport(int year,int month,HttpServletResponse response){
        List<TemplateVo> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new TemplateVo("25号"+i,"26号"+i,"27号"+i,"28号"+i,"29号"+i,"30号"+i,"31号"+i));
        }
        // 获取要导出的列名
        String column = getExportColumn(year, month);
        // 这里是创建动态列的表头,dynamicExport 这个方法在上面那个 ExcelUtil 有
        List<ExcelExportEntity> beanList = ExcelUtil.dynamicExport(TemplateVo.class, column);
        ExportParams params = new ExportParams();
        params.setStyle(ExcelStyleUtil.class);
        Workbook workbook = ExcelExportUtil.exportExcel(params, beanList, list);
        ExcelUtil.downLoadExcel("下载",response,workbook);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    🌭 效果

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    暂时就这些了,其实做项目的时候,easypoi碰到的问题不止这些,现在项目做完了,有空了,想总结下把解决办法都写出来,发现项目中遇到的那些问题好像都不适合用来做案例来讲。看一下以后有没有什么补充的吧。(最后,如果觉得文章对你有帮助的话,点个赞再走吧~👀)

  • 相关阅读:
    systemverilog运行的时候调用系统函数运行python等
    【办公常识】写好的代码如何上传?使用svn commit
    【Leetcode】33- 搜索旋转排序数组
    阿里云ECS和轻量服务器有什么区别?
    Config:分布式配置中心
    卷积神经网络到底是什么,卷积神经网络是一种
    关于Validation的方法使用
    如何从宏观层面构建优秀的大语言模型
    机器学习AI大模型的开源与闭源:哪个更好?
    AIX7.1安装Oracle11g补丁33829709(PSU+OJVM)
  • 原文地址:https://blog.csdn.net/weixin_43165220/article/details/126266394