zoukankan      html  css  js  c++  java
  • easyExcel生成excel并导出自定义样式(二)添加复杂表头

    设置合并竖行单元格,表头设置
    OutputStream outputStream = ExcelUtils.getResponseOutputStream(response, fileName);
            //根据数据组装需要合并的单元格
            Map<String, List<String>> strategyMap = addMerStrategy(importAssignExcelDemo());
            ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(outputStream)
                    .registerWriteHandler(new ReadCustomCellStyleStrategy(new WriteCellStyle(), new WriteCellStyle()))
                    .registerWriteHandler(new DemoMergeStrategy(strategyMap))//添加的竖行内容一致时,合并单元格
                    .excelType(ExcelTypeEnum.XLSX);
            ExcelWriter excelWriter = excelWriterBuilder.build();
            String customer = "***表头名称";
            String dateStr = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
          //getHeader()获取自定义表头 ExcelUtils.writeOnly(excelWriter, importAssignExcelDemo(), ImportDemoExcelDTO.
    class, 1, fileName + "数据", getHeader(customer, dateStr));
    private List<List<String>> getHeader(String customer, String dateStr) {
            /**
             * 打算展示成如下样子
             * |客户:xxx 公司 (这一行需要合并单元格)
             * |单号: SO22222222222222|  日期: 2020-01-01 (分别需要合并单元格)
             * |产品ID|产品名称|价格|数量|总金额|备注|
             */
            List<List<String>> list = new ArrayList<>();
            //反射获取excel表头所有字段
            List<String> attributeList = getExcelObjectAttribute();
            //拼装表头
            attributeList.forEach(excelName->{
                List<String> head = new ArrayList<>();
                head.add(customer);
                head.add(dateStr);
                head.add(excelName);
                list.add(head);
            });
            return list;
    /**
         * 反射获取excel对象excel注解属性坐表头
         */
        public static List<String> getExcelObjectAttribute() {
            List<String> list = new ArrayList();
            try {
                //获取类名的包名地址
                Class<?> clazz = Class.forName("com.。。。.importexcel.ImportExcelDTO");
                // 得到所有定义字段
                Field[] allFields = clazz.getDeclaredFields();
                // 得到所有field并存放到一个list中.
                for (Field field : allFields) {
                    //判断并获取excel注解信息
                    if (field.isAnnotationPresent(ExcelProperty.class)) {
                        ExcelProperty excelProperty = field.getDeclaredAnnotation(ExcelProperty.class);
                        list.add(excelProperty.value()[0]);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return list;
        }
    /**
     * 重载:生成excel文件指定sheet页方法
     *
     * @param excelWriter
     * @param data
     * @param clazz
     * @param sheetNo
     * @param sheetName
     * @param <T>
     * @param head 重载添加表头参数
     */
    public static <T> void writeOnly(ExcelWriter excelWriter, List<T> data, Class clazz, Integer sheetNo, String sheetName, List<List<String>> head) {
        ExcelWriterSheetBuilder excelWriterSheetBuilder;
        WriteSheet writeSheet = new WriteSheet();
        excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriter);
        excelWriterSheetBuilder.sheetNo(sheetNo);
        excelWriterSheetBuilder.sheetName(sheetName);
        writeSheet.setSheetNo(sheetNo);
        writeSheet.setSheetName(sheetName);
        writeSheet.setClazz(clazz);
        writeSheet.setHead(head);
        excelWriter.write(data, writeSheet);
    }
    /**
         * 合并竖行单元格
         * @param excelDtoList
         * @return
         */
        private Map<String, List<String>> addMerStrategy(List<ImportDemoExcelDTO> excelDtoList) {
            Map<String, List<String>> strategyMap = new HashMap<>();
            ImportDemoExcelDTO preExcelDto = null;
            //是否合并
            int startCol = 0;
            List<String> mapList = new ArrayList<>();
            String mapTest = "";
            for (int i = 0; i < excelDtoList.size(); i++) {
                ImportDemoExcelDTO importAssignExcelDTO = excelDtoList.get(i);
                if (preExcelDto != null) {
                    //从第二行开始判断是否需要合并
                    if (!preExcelDto.getLeaderName().equals(importAssignExcelDTO.getLeaderName())) {
                        mapTest = startCol + "," + (i);
                        //第0行是表头
                        startCol = i + 1;
                        if (i == excelDtoList.size() - 1) {
                            mapList.add(mapTest);
                            //最后一条清空不用合并
                            mapTest = "";
                        }
                    } else if (i == excelDtoList.size() - 1) {
                        mapTest = startCol + "," + (startCol+1);//竖行合并
                    }
                } else {
                    startCol = i + 1;
                }
                preExcelDto = importAssignExcelDTO;
                if (StringUtils.isNotBlank(mapTest)) {
                    mapList.add(mapTest);
                }
            }
            //1代表第一列,excel从0开始。(至合并第一列)
            strategyMap.put("1", mapList);
            return strategyMap;
        }
    package com.****.write.style;
    
    import com.alibaba.excel.metadata.Head;
    import com.alibaba.excel.write.merge.AbstractMergeStrategy;
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.util.CellRangeAddress;
    
    import java.util.List;
    import java.util.Map;
    
    public class DemoMergeStrategy extends AbstractMergeStrategy {
    
      //竖行合并,合并列:开始行,结束行
    private Map<String, List<String>> strategyMap; private Sheet sheet; public DemoMergeStrategy(Map<String, List<String>> strategyMap) { this.strategyMap = strategyMap; } @Override protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { this.sheet = sheet;
        System.out.println(cell.getRowIndex()+",测试记录行列,"+cell.getColumnIndex());
        if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) { 

        /** * 保证每个cell被合并一次,如果不加上面的判断,因为是一个cell一个cell操作的, * 例如合并A2:A3,当cell为A2时,合并A2,A3,但是当cell为A3时,又是合并A2,A3, * 但此时A2,A3已经是合并的单元格了 */

        for (Map.Entry<String, List<String>> entry : strategyMap.entrySet()) {
          Integer columnIndex
    = Integer.valueOf(entry.getKey());
          entry.getValue().forEach(rowRange
    -> {
            //添加一个合并请求
            String startRow = rowRange.split(",")[0];
            String endRow
    = rowRange.split(",")[1];
            sheet.addMergedRegionUnsafe(
    new CellRangeAddress(Integer.parseInt(startRow), Integer.parseInt(endRow), columnIndex, columnIndex));
          }); 
        }

        }
      }
    }

    效果实现




    下面为参考内容:
    调整内容:
    OutputStream outputStream = ExcelUtils.getResponseOutputStream(response, excelName);
    ExcelWriter excelWriter;
    ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(outputStream);
                int lastCol = ExportCommentsTaskExcelDTO.class.getDeclaredFields().length-1;
                //根据数据组装需要合并的单元格
                Map<String, List<String>> strategyMap = addMerStrategy(commentsTaskExcelDTOList);
                excelWriterBuilder
                        .registerWriteHandler(new CommentsCustomExcelHeader(excelName, createTime, lastCol))//文档名、时间、表头合并结束列数
                        .registerWriteHandler(new CommentsExcelStyleStrategy(new WriteCellStyle(), new WriteCellStyle()))
                        .registerWriteHandler(new CommentsExcelMergeStrategy(strategyMap)).relativeHeadRowIndex(3)//真实数据从第三行开始
                        .excelType(ExcelTypeEnum.XLSX);
                excelWriter = excelWriterBuilder.build();
                ExcelUtils.writeOnly(excelWriter, commentsTaskExcelDTOList, ExportCommentsTaskExcelDTO.class, 1, excelName + "数据");
    

      

    DetectionSheetWriteHandler 复杂表头样式整理

    这个类继承SheetWriteHandler 抽象类,实现afterSheetCreate方法,进行自定义表头策略,传入自定义的表头信息,及自定义样式。

    public class DetectionSheetWriteHandler implements SheetWriteHandler {
    	
    	private String dataTime;
        public DetectionSheetWriteHandler(){}
        public DetectionSheetWriteHandler(String dataTime){
            this.dataTime = dataTime;
        }
        @Override
        public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
    
        }
    
        @Override
        public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
            Workbook workbook = writeWorkbookHolder.getWorkbook();
            Sheet sheet = workbook.getSheetAt(0);
            //设置第一行标题
            Row row1 = sheet.createRow(1);
            row1.setHeight((short) 800);
            Cell row1Cell1 = row1.createCell(0);
            row1Cell1.setCellValue(" 统 计 表");
            CellStyle row1CellStyle = workbook.createCellStyle();
            row1CellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            row1CellStyle.setAlignment(HorizontalAlignment.CENTER);
            Font row1Font = workbook.createFont();
            row1Font.setBold(true);
            row1Font.setFontName("宋体");
            row1Font.setFontHeightInPoints((short) 18);
            row1CellStyle.setFont(row1Font);
            row1Cell1.setCellStyle(row1CellStyle);
            //合并单元格,起始行,结束行,起始列,结束列
            sheet.addMergedRegionUnsafe(new CellRangeAddress(1, 1, 0, 5));
    //        sheet.addMergedRegionUnsafe(new CellRangeAddress(1, 1, 22, 23));
    
    //        设置第二行标题
            Row row2 = sheet.createRow(2);
            row2.setHeight((short) 400);
            Cell row2Cell1 = row2.createCell(0);
            row2Cell1.setCellValue("时间范围:"+ dataTime);
            CellStyle row2CellStyle = workbook.createCellStyle();
            row2CellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            row2CellStyle.setAlignment(HorizontalAlignment.RIGHT);
            Font row2Font = workbook.createFont();
            row2Font.setFontName("宋体");
            row2Font.setFontHeightInPoints((short) 10);
            row2CellStyle.setFont(row2Font);
            row2Cell1.setCellStyle(row2CellStyle);
            sheet.addMergedRegionUnsafe(new CellRangeAddress(2, 2, 0, 5));
    
        }
    }
    

      

    自定义excel内容格式

    DetectionCellStyleStrategy 类 自定义excel内容的样式
    
    public class DetectionCellStyleStrategy {
    
    	/**
    	 * 导出excel时的样式配置
    	 * 
    	 * @param headFont
    	 *            contentFont字体大小
    	 * @return
    	 */
    	public static HorizontalCellStyleStrategy getStyleStrategy(short headFont, short contentFont) {
    		// 头的策略
    		WriteCellStyle headWriteCellStyle = new WriteCellStyle();
    		// 背景设置为灰色
    		// headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
    		WriteFont headWriteFont = new WriteFont();
    		headWriteFont.setFontHeightInPoints(headFont);
    		// 字体样式
    		headWriteFont.setFontName("宋体");
    		headWriteCellStyle.setWriteFont(headWriteFont);
    		// 自动换行
    		headWriteCellStyle.setWrapped(true);
    		// 水平对齐方式
    		headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
    		// 垂直对齐方式
    		headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
    		headWriteCellStyle.setBorderLeft(BorderStyle.THIN);// 左边框
    		headWriteCellStyle.setBorderTop(BorderStyle.THIN);// 上边框
    		headWriteCellStyle.setBorderRight(BorderStyle.THIN);// 右边框
    		headWriteCellStyle.setBorderBottom(BorderStyle.THIN);// 下边框
    
    		// 内容的策略
    		WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
    		// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了
    		// FillPatternType所以可以不指定
    		// contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES);
    		// 背景白色
    		contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
    
    		// 字体策略
    		WriteFont contentWriteFont = new WriteFont();
    		// 字体大小
    		contentWriteFont.setFontHeightInPoints(contentFont);
    		// 字体样式
    		contentWriteFont.setFontName("宋体");
    		contentWriteCellStyle.setWriteFont(contentWriteFont);
    		// 自动换行
    		contentWriteCellStyle.setWrapped(true);
    		// 水平对齐方式
    		contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
    		// 垂直对齐方式
    		contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
    		contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
    		contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
    		contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
    		contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
    		// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
    		return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    	}
    }
    

      效果:


    ————————————————
    版权声明:本文为CSDN博主「笑依」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    参考原文链接:https://blog.csdn.net/weixin_50539367/article/details/108530250




    合并行:
    excelWriterBuilder
                        .registerWriteHandler(new CommentsCustomExcelHeader(excelName, createTime, lastCol))
                        .registerWriteHandler(new CommentsExcelStyleStrategy(new WriteCellStyle(), new WriteCellStyle()))
                        .registerWriteHandler(new CommentsExcelMergeStrategy(strategyMap))
                        .relativeHeadRowIndex(2)
                        .excelType(ExcelTypeEnum.XLSX);


    package com.****.excel.write.style;

    import com.alibaba.excel.metadata.Head;
    import com.alibaba.excel.write.merge.AbstractMergeStrategy;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.ss.util.CellRangeAddress;

    import java.util.List;
    import java.util.Map;

    public class CommentsExcelMergeStrategy extends AbstractMergeStrategy { //需要合并的行:合并的开始,结束列 private Map<String, String> strategyMap; private Sheet sheet; public CommentsExcelMergeStrategy(Map<String, String> strategyMap) { this.strategyMap = strategyMap; } @Override protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { this.sheet = sheet; if (cell.getRowIndex() >= 3 && cell.getColumnIndex() == 0) { /** * 保证每个cell被合并一次,如果不加上面的判断,因为是一个cell一个cell操作的, * 例如合并A2:A3,当cell为A2时,合并A2,A3,但是当cell为A3时,又是合并A2,A3, * 但此时A2,A3已经是合并的单元格了 */ for (Map.Entry<String, String> entry : strategyMap.entrySet()) { System.out.println(entry.getKey()+",内容,"+entry.getValue()); if(entry.getKey().equals(cell.getRowIndex()+"")){ Integer rowIndex = Integer.valueOf(entry.getKey()); //添加一个合并请求 String startCol = entry.getValue().split(",")[0]; String endCol = entry.getValue().split(",")[1]; sheet.addMergedRegionUnsafe(new CellRangeAddress(rowIndex, rowIndex, Integer.parseInt(startCol), Integer.parseInt(endCol))); //设置样式,加粗,靠左 CellStyle cellStyle = sheet.getWorkbook().createCellStyle(); Font font = sheet.getWorkbook().createFont(); cellStyle.setAlignment(HorizontalAlignment.LEFT); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); font.setBold(true); cellStyle.setFont(font); cell.setCellStyle(cellStyle); } } } } }

      

    /**
         * 横行领导名称合并单元格
         *
         * @param excelDtoList
         * @return
         */
        private Map<String, String> addMerStrategy(List<Object> excelDtoList, int endCol) {
            Map<String, String> strategyMap = new HashMap<>();
            //第0行是表头
            int startCol = 3;
            String mapTest = "";
            for (int i = 0; i < excelDtoList.size(); i++) {
                ExportCommentsTaskExcelDTO commentsTaskExcelDTO = (ExportCommentsTaskExcelDTO) excelDtoList.get(i);
                //从第二行开始判断是否需要合并
                if (StringUtils.contains(commentsTaskExcelDTO.getSortNum(), "(") && Objects.isNull(strategyMap.get(startCol+i))) {
                    mapTest = 0 + "," + endCol;
                    strategyMap.put(startCol + i + "", mapTest);
                }
            }
            return strategyMap;
        }
    

      效果:











  • 相关阅读:
    sql 计算auc
    tf.app.flags
    transformer
    python 直连 hive
    rnn 详解
    yolov3
    记学习react-native
    html5横、竖屏状态 以及禁止横屏
    图片懒加载
    npm安装的时候报-4048
  • 原文地址:https://www.cnblogs.com/mangwusuozhi/p/15788844.html
Copyright © 2011-2022 走看看