导出Excel的技术分享-综合篇

news2024/11/18 21:48:17

在这里插入图片描述

导出Excel的技术分享-综合篇

简单的EasyExcel使用

/**
     * 最简单的写
     */
    public void simpleWrite() {
        // 注意 simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入

        // 写法1 JDK8+
        // since: 3.0.0-beta1
        String fileName = "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, DemoData.class)
                .sheet("模板")
                .doWrite(data());
    }
 private List<DemoData> data() {
        List<DemoData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDate(new Date());
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

行标题设置

   public static void main(String[] args) {
        String powerTitle = "行单元格样例演示\n" +
               "行单元格样例演示\n";
        ExcelWriter excelWriter = EasyExcel.write("行标题设置.xlsx").build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0,"行标题设置").head(DemoData.class)
                .relativeHeadRowIndex(2)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new IndexStandardStyleHandler(powerTitle)).build();
        excelWriter.write(data(),writeSheet);
        excelWriter.finish();
    }
public class IndexStandardStyleHandler implements SheetWriteHandler {


    private String tableTitle;

    public IndexStandardStyleHandler(String title) {
        this.tableTitle = title;
    }

    @Override
    public void afterSheetCreate(SheetWriteHandlerContext context) {
        // 在创建工作表之后执行的操作
        WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder();
//        ExcelWriteHeadProperty excelWriteHeadProperty = writeSheetHolder.getExcelWriteHeadProperty();
//        excelWriteHeadProperty.setHeadRowNumber(3);
        // 设置行高和样式
        // 创建第一行并设置样式
        Row row = writeSheetHolder.getSheet().createRow(0);
        row.setHeight((short) 1000);
        Cell cell = row.createCell(0);
        cell.setCellValue(tableTitle);
        //设置标题
        // 准备样式
        CellStyle cellStyle = context.getWriteWorkbookHolder().getWorkbook().createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        Font font = context.getWriteWorkbookHolder().getWorkbook().createFont();
//        font.setBold(true);
        font.setFontHeight((short) 500);
        font.setFontName("宋体");
        font.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex());
        cellStyle.setFont(font);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setWrapText(true);
        cell.setCellStyle(cellStyle);
        //writeWorkbookHolder.createCellStyle(style,null);
        Sheet sheet = context.getWriteSheetHolder().getSheet();
        sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 1, 0, 2));
    }

    @Override
    public int order() {
        return 3;
    }
}

单元格线设置

 public static void main(String[] args) {
        String powerTitle = "行单元格样例演示\n" +
               "行单元格样例演示\n";
        ExcelWriter excelWriter = EasyExcel.write("单元格线设置.xlsx").build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0,"单元格线设置").head(DemoData.class)
                .relativeHeadRowIndex(2)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new CelllineStyleHandler())
                .registerWriteHandler(new IndexStandardStyleHandler(powerTitle)).build();
        excelWriter.write(data(),writeSheet);
        excelWriter.finish();
    }
public class CelllineStyleHandler implements CellWriteHandler {

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        for (int i = 0; i < cellDataList.size(); i++) {
            WriteCellData<?> writeCellData = cellDataList.get(i);
            WriteCellStyle writeCellStyle = writeCellData.getWriteCellStyle();
            writeCellStyle.setBorderLeft(THIN);
            writeCellStyle.setBorderRight(THIN);
            writeCellStyle.setBorderTop(THIN);
            writeCellStyle.setBorderBottom(THIN);
            writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            writeCellStyle.setShrinkToFit(true);
        }
    }

    @Override
    public int order() {
        return 1;
    }
}

下拉框设置

  public static void main(String[] args) {
        String powerTitle = "行单元格样例演示\n" +
               "行单元格样例演示\n";
        ExcelWriter excelWriter = EasyExcel.write("下拉框设置.xlsx").build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0,"下拉框设置").head(DemoData.class)
                .relativeHeadRowIndex(2)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new CelllineStyleHandler())
                .registerWriteHandler(new CellDropDownBoxWriteHandler())
                .registerWriteHandler(new IndexStandardStyleHandler(powerTitle)).build();
        excelWriter.write(data(),writeSheet);
        excelWriter.finish();
    }
public class CellDropDownBoxWriteHandler implements SheetWriteHandler {

    /**
     * 定义一个map key是需要添加下拉框的列的index value是下拉框数据
     */
    Map<Integer, String[]> mapDropDown = new HashMap<>();

    String[] checkFrequency = {"字符串0","字符串1","字符串2","字符串3","字符串4"};

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        //下拉选在Excel中对应的列
        Field[] fields = writeSheetHolder.getClazz().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if (field.isAnnotationPresent(ExcelProperty.class) && field.isAnnotationPresent(ExcelProperty.class)){
                mapDropDown.put(i,checkFrequency);
            }
        }

        //获取工作簿
        Sheet sheet = writeSheetHolder.getSheet();
        ///开始设置下拉框
        DataValidationHelper helper = sheet.getDataValidationHelper();
        //设置下拉框
        for (Map.Entry<Integer, String[]> entry : mapDropDown.entrySet()) {
            /*起始行、终止行、起始列、终止列  起始行为1即表示表头不设置**/
            //这里设置65535可能又问题,因为这个是excel的最大行数,如果数据量超过这个数,就会报错
            CellRangeAddressList addressList = new CellRangeAddressList(1, 65535, entry.getKey(), entry.getKey());
            /*设置下拉框数据**/
            DataValidationConstraint constraint = helper.createExplicitListConstraint(entry.getValue());
            DataValidation dataValidation = helper.createValidation(constraint, addressList);

            //阻止输入非下拉选项的值
            dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
            dataValidation.setShowErrorBox(true);
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.createErrorBox("提示", "输入值与单元格定义格式不一致");
            dataValidation.createPromptBox("填写说明", "填写内容只能为下拉数据集中的类型");

            sheet.addValidationData(dataValidation);
        }
    }

    @Override
    public int order() {
        return 1;
    }
}

标题和内容字体样式设置不一样

 public static void main(String[] args) {
        String powerTitle = "行单元格样例演示\n" +
               "行单元格样例演示\n";
        ExcelWriter excelWriter = EasyExcel.write("标题和内容字体样式不一样设置.xlsx").build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0,"标题和内容字体样式不一样设置").head(DemoData.class)
                .relativeHeadRowIndex(2)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new CelllineStyleHandler())
                .registerWriteHandler(new CellDropDownBoxWriteHandler())
                .registerWriteHandler(new FontStyleWriteHandler())
                .registerWriteHandler(new IndexStandardStyleHandler(powerTitle)).build();
        excelWriter.write(data(),writeSheet);
        excelWriter.finish();
    }
public class FontStyleWriteHandler implements CellWriteHandler {
    /**
     * 设置字体样式
     * @param writeSheetHolder
     * @param writeTableHolder Nullable.It is null without using table writes.
     * @param cellDataList     Nullable.It is null in the case of add header.There may be several when fill the data.
     * @param cell
     * @param head             Nullable.It is null in the case of fill data and without head.
     * @param relativeRowIndex Nullable.It is null in the case of fill data.
     * @param isHead           It will always be false when fill data.
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        for (int i = 0; i < cellDataList.size(); i++) {
            WriteCellData<?> writeCellData = cellDataList.get(i);
            WriteCellStyle writeCellStyle = writeCellData.getWriteCellStyle();
            if (2 == cell.getRowIndex()) {
                WriteFont writeFont = new WriteFont();
                writeFont.setBold(true);
                writeFont.setFontHeightInPoints((short) 13);
                writeFont.setFontName("楷体");
                writeCellStyle.setWriteFont(writeFont);
            } else {
                WriteFont writeFont = new WriteFont();
                writeFont.setFontName("宋体");
                writeCellStyle.setBorderLeft(THIN);
                writeCellStyle.setBorderRight(THIN);
                writeCellStyle.setBorderTop(THIN);
                writeCellStyle.setBorderBottom(THIN);
                writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
                writeCellStyle.setWriteFont(writeFont);
//                writeCellStyle.setShrinkToFit(true);
            }
        }
    }

    @Override
    public int order() {
        return 1;
    }
}

单元格合并设置

 public static void main(String[] args) {
        String powerTitle = "行单元格样例演示\n" +
               "行单元格样例演示\n";
        ExcelWriter excelWriter = EasyExcel.write("单元格合并设置.xlsx").build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0,"单元格合并设置").head(DemoData.class)
                .relativeHeadRowIndex(2)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new CelllineStyleHandler())
                .registerWriteHandler(new CellDropDownBoxWriteHandler())
                .registerWriteHandler(new FontStyleWriteHandler())
                .registerWriteHandler(new ExcelFillCellMergeStrategyHandler(2,new int[]{0,1,2}))
                .registerWriteHandler(new IndexStandardStyleHandler(powerTitle)).build();
        excelWriter.write(data(),writeSheet);
        excelWriter.finish();
    }
public class ExcelFillCellMergeStrategyHandler implements CellWriteHandler {

    /**
     * 合并字段的下标,如第一到五列new int[]{0,1,2,3,4}
     */
    private int[] mergeColumnIndex;
    /**
     * 从第几行开始合并,如果表头占两行,这个数字就是2
     */
    private int mergeRowIndex;

    public ExcelFillCellMergeStrategyHandler(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {

        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();


        if (curRowIndex > mergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }

        for (int i = 0; i < list.size(); i++) {
            WriteCellData<?> writeCellData = list.get(i);
            WriteCellStyle writeCellStyle = writeCellData.getWriteCellStyle();
            writeCellStyle.setBorderLeft(THIN);
            writeCellStyle.setBorderRight(THIN);
            writeCellStyle.setBorderTop(THIN);
            writeCellStyle.setBorderBottom(THIN);
            writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            writeCellStyle.setShrinkToFit(true);
        }
    }

    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
        Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() :
                cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        Object preData = preCell.getCellType() == CellType.STRING ? preCell.getStringCellValue() :
                preCell.getNumericCellValue();
        // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
        //
        if (curData.equals(preData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
                        curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }

    @Override
    public int order() {
        return 1;
    }
}

自定义多个sheet页导出设置

public class Test07 {
    public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException {
        String powerTitle = "行单元格样例演示\n" +
               "行单元格样例演示\n";
        ExcelWriter excelWriter = EasyExcel.write("自定义多个sheet页导出设置.xlsx").build();
        // 第一个sheet的写入
        WriteSheet writeSheet01 = EasyExcel.writerSheet(0,"自定义多个sheet页导出设置").head(DemoData.class)
                .relativeHeadRowIndex(2)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new CelllineStyleHandler())
                .registerWriteHandler(new CellDropDownBoxWriteHandler())
                .registerWriteHandler(new FontStyleWriteHandler())
                .registerWriteHandler(new ExcelFillCellMergeStrategyHandler(2,new int[]{0,1,2}))
                .registerWriteHandler(new IndexStandardStyleHandler(powerTitle)).build();
        excelWriter.write(data(),writeSheet01);
        // 后续sheet写入
        Map map = listGroupInfo(DemoData.class, dataList());
        int i = 1;
        Map<String,String> orgNameMap = new HashMap<>();
        orgNameMap.put("自定义sheet页1","自定义sheet页1");
        orgNameMap.put("自定义sheet页2","自定义sheet页2");
        orgNameMap.put("自定义sheet页3","自定义sheet页3");
        orgNameMap.put("自定义sheet页4","自定义sheet页4");
        for (Map.Entry<String, String> entry : orgNameMap.entrySet()) {
            String OrgCode = entry.getKey();
            String orgName = entry.getValue();
            Object list = map.get(OrgCode);
            // 设置非供电单位写入标题
            String noPowerTitle = "行单元格样例演示\n" +OrgCode+
                    "行单元格样例演示\n";;
            WriteSheet sheet = EasyExcel.writerSheet(i, orgName).head(DemoData.class)
                    .relativeHeadRowIndex(2)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .build();
            excelWriter.write((Collection<?>) list,sheet);
            i = i + 1;
        }
        excelWriter.finish();
    }

    private static Map listGroupInfo(Class<?> head1, List<?> dataList1) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        String groupField = "string";
        String name = head1.getName();
        Class<?> clazz = Class.forName(name);
        Field field = clazz.getDeclaredField(groupField);
        field.setAccessible(true);
        Map<Object, ? extends List<?>> map = dataList1.stream()
                .collect(Collectors.groupingBy(obj -> {
                    try {
                        return field.get(obj);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                        return null;
                    }
                }));
        Set<Object> objects = map.keySet();
        Iterator<Object> iterator = objects.iterator();
//        while (iterator.hasNext()) {
//            List<?> list = map.get(iterator.next());
//            for (int i = 0; i < list.size(); i++) {
//                Object o = list.get(i);
//                Field fieldSerialNumber = clazz.getDeclaredField("serialNumber");
//                fieldSerialNumber.setAccessible(true);
//                fieldSerialNumber.set(o,String.valueOf(i+1));
//            }
//        }
        return map;
    }

    private static List<DemoData> data() {
        List<DemoData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDate(new Date());
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

    private static List<DemoData> dataList() {
        List<DemoData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data1 = new DemoData();
            data1.setString("自定义sheet页1");
            data1.setDate(new Date());
            data1.setDoubleData(111.111);
            list.add(data1);
        }
        for (int i = 0; i < 10; i++) {
            DemoData data2 = new DemoData();
            data2.setString("自定义sheet页2");
            data2.setDate(new Date());
            data2.setDoubleData(222.222);
            list.add(data2);
        }
        for (int i = 0; i < 10; i++) {
            DemoData data3 = new DemoData();
            data3.setString("自定义sheet页3");
            data3.setDate(new Date());
            data3.setDoubleData(333.333);
            list.add(data3);
        }
        for (int i = 0; i < 10; i++) {
            DemoData data3 = new DemoData();
            data3.setString("自定义sheet页4");
            data3.setDate(new Date());
            data3.setDoubleData(444.444);
            list.add(data3);
        }
        return list;
    }


}
public class ExcelFillCellMergeStrategyHandler implements CellWriteHandler {

    /**
     * 合并字段的下标,如第一到五列new int[]{0,1,2,3,4}
     */
    private int[] mergeColumnIndex;
    /**
     * 从第几行开始合并,如果表头占两行,这个数字就是2
     */
    private int mergeRowIndex;

    public ExcelFillCellMergeStrategyHandler(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {

        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();


        if (curRowIndex > mergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }

        for (int i = 0; i < list.size(); i++) {
            WriteCellData<?> writeCellData = list.get(i);
            WriteCellStyle writeCellStyle = writeCellData.getWriteCellStyle();
            writeCellStyle.setBorderLeft(THIN);
            writeCellStyle.setBorderRight(THIN);
            writeCellStyle.setBorderTop(THIN);
            writeCellStyle.setBorderBottom(THIN);
            writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            writeCellStyle.setShrinkToFit(true);
        }
    }

    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
        Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() :
                cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        Object preData = preCell.getCellType() == CellType.STRING ? preCell.getStringCellValue() :
                preCell.getNumericCellValue();
        // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
        //
        if (curData.equals(preData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
                        curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }

    @Override
    public int order() {
        return 1;
    }
}

单元格锁设置

 public static void main(String[] args) {
        String powerTitle = "行单元格样例演示\n" +
               "行单元格样例演示\n";
        ExcelWriter excelWriter = EasyExcel.write("单元格锁设置.xlsx").build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0,"单元格锁设置").head(DemoDataLock.class)
                .relativeHeadRowIndex(2)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new CelllineStyleHandler())
                .registerWriteHandler(new LockHandler())
                .registerWriteHandler(new IndexStandardStyleHandler(powerTitle)).build();
        excelWriter.write(data(),writeSheet);
        excelWriter.finish();
    }
public class LockHandler extends LongestMatchColumnWidthStyleStrategy implements SheetWriteHandler {


    @Override
    public void afterCellDispose(CellWriteHandlerContext context) {
        // 锁定有内容过的单元格(方法1)
        Class clazz = context.getWriteSheetHolder().getClazz();
        Field[] fields = clazz.getDeclaredFields();
        Field field = fields[context.getColumnIndex()];
        if (field.isAnnotationPresent(UnLockCell.class) && field.isAnnotationPresent(ExcelProperty.class)) {
            WriteCellStyle writeCellStyle = context.getFirstCellData().getOrCreateStyle();
            writeCellStyle.setLocked(false);
        }
    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        // 设置保护密码
        writeSheetHolder.getSheet().protectSheet("ZhiChengKeJi");
        // 锁定单元格不可选中(防止别人直接复制内容到其他excel修改)
        ((SXSSFSheet) writeSheetHolder.getSheet()).lockSelectLockedCells(false);
//        ((SXSSFSheet) writeSheetHolder.getSheet()).lockSelectLockedCells(true);
    }
}

设置大标题行样式

在这里插入图片描述

@PostMapping("/exportExcel")
    public void exportExcel(HttpServletResponse response) throws IOException {
        // 数据库获取数据
        List<Profile> list = iProfileService.exportExcel(response);
        List<ProfileExcel> profileExcels = ObjectConvertUtil.convertList(list, ProfileExcel.class);
//        List<ProfileExcel> profileExcels = ExcelConvert.INSTANCE.converList(list);
        // 输出
        ExcelUtils.write(response, "大佬信息", "岗位列表", ProfileExcel.class, profileExcels);

    }

展示工具类中的代码

 /**
     * 将列表以Excel的形式响应给前端
     *
     * @param response 响应
     * @param fileName 文件名
     * @param sheetName Excel sheet 名
     * @param head Excel head 头
     * @param data 数据列表
     * @param <T> 泛型,保证 head 和 data 类型的一致性
     * @throws IOException 写入失败的情况
     */
    public static <T> void write(HttpServletResponse response, String fileName, String sheetName, Class<T> head, List<T> data) throws IOException {
        // 这一部分是设置编码样式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
        // 输出Excel
        EasyExcel.write(response.getOutputStream(),head)
                .relativeHeadRowIndex(2)
                // 不要自动关闭,交给 Servlet 自己处理
                //.autoCloseStream(false)
                .registerWriteHandler(new ExportIndexTypeSheetWriteHandler())
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .registerWriteHandler(new ExcelFillCellMergeStrategy(3,new int[]{0,1,2,3,4,5,6}))
                .registerWriteHandler(new FontStyleWriteHandler())
                .sheet(sheetName).doWrite(data);
    }

核心注册类代码展示

实现SheetWriteHandler策略接口,在sheet创建之前完成对样式进行提前的设置

public class ExportIndexTypeSheetWriteHandler implements SheetWriteHandler {

    @Override
    public void afterSheetCreate(SheetWriteHandlerContext context) {
        // 在创建工作表之后执行的操作
        WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder();
//        ExcelWriteHeadProperty excelWriteHeadProperty = writeSheetHolder.getExcelWriteHeadProperty();
//        excelWriteHeadProperty.setHeadRowNumber(3);
        // 设置行高和样式
        // 创建第一行并设置样式
        Row row = writeSheetHolder.getSheet().createRow(0);
        // 设置第一行的高为
        row.setHeight((short) 1000);
        // 提前创建第一行单元格并进行设置
        Cell cell = row.createCell(0);
        // 设置需要展示的文字信息
        String title = "大佬们的信息展示\n" +
                "这个是演示的数据标题\r\n";
        // 单元格填充内容
        cell.setCellValue(title);
        //设置标题
        // 准备样式
        // 从上下文内容中获取工作簿并创建样式
        CellStyle cellStyle = context.getWriteWorkbookHolder().getWorkbook().createCellStyle();
        // 这个接口在ss。POI的核心模块中存在
        // 设置单元格的垂直对齐类型 : 垂直对齐以单元格高度为中心。
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置单元格的水平对齐样式:水平对齐居中,这意味着文本在单元格中居中。
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        // 从上下文获取字体
        Font font = context.getWriteWorkbookHolder().getWorkbook().createFont();
        // 设置字体加粗
        font.setBold(true);
        // 设置字体行高
        font.setFontHeight((short) 500);
        // 设置字体的样式名称
        font.setFontName("宋体");
        // 设置字体的颜色
        font.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex());
        // 需要在单元格样式中填充字体
        cellStyle.setFont(font);
        // 单元格设置为水平居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        // 设置单元格为允许换行,不然上述title中的单元格换行无效
        cellStyle.setWrapText(true);
        // 最后需要将单元格的样式填充到单元格中
        cell.setCellStyle(cellStyle);
        //writeWorkbookHolder.createCellStyle(style,null);
        // 有点重复操作,从上下文中获取默认第一个sheet页的样式
        Sheet sheet = context.getWriteSheetHolder().getSheet();
        // 设置单元格的合并区域,给坐标的方式。哪行开始哪行结束。哪列开始那列结束
        sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 1, 0, 5));
    }
}

标题行的样式填充颜色改变

在这里插入图片描述

在这里插入图片描述

颜色9是透明色。

相同单元格的样式合并

在这里插入图片描述

这种编码方式需要在代码使用的时候将那几列放到方法中。

public class ExcelFillCellMergeStrategy implements CellWriteHandler {
    /**
     * 合并字段的下标,如第一到五列new int[]{0,1,2,3,4}
     */
    private int[] mergeColumnIndex;
    /**
     * 从第几行开始合并,如果表头占两行,这个数字就是2
     */
    private int mergeRowIndex;

    public ExcelFillCellMergeStrategy() {
    }

    public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                                 Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
                                Head head, Integer integer, Boolean aBoolean) {

    }



    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();

        if (curRowIndex > mergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }

    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :
                cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
                preCell.getNumericCellValue();
        // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
        //
        if (curData.equals(preData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
                        curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }

}

单元格的横线设置

在这里插入图片描述

public class FontStyleWriteHandler implements CellWriteHandler {
    /**
     * 设置字体样式
     * @param writeSheetHolder
     * @param writeTableHolder Nullable.It is null without using table writes.
     * @param cellDataList     Nullable.It is null in the case of add header.There may be several when fill the data.
     * @param cell
     * @param head             Nullable.It is null in the case of fill data and without head.
     * @param relativeRowIndex Nullable.It is null in the case of fill data.
     * @param isHead           It will always be false when fill data.
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 创建字体样式
        // 设置内容字体样式
        WriteFont writeFont = new WriteFont();
        writeFont.setFontName("宋体");
        for (int i = 0; i < cellDataList.size(); i++) {
            WriteCellData<?> writeCellData = cellDataList.get(i);
            WriteCellStyle writeCellStyle = writeCellData.getWriteCellStyle();
            // 横线的设置
            writeCellStyle.setBorderLeft(THIN);
            writeCellStyle.setBorderRight(THIN);
            writeCellStyle.setBorderTop(THIN);
            writeCellStyle.setBorderBottom(THIN);
            writeCellStyle.setWriteFont(writeFont);
            writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            writeCellStyle.setShrinkToFit(true);
        }
    }

}

导出字体的样式自定义

在这里插入图片描述

public class FontStyleWriteHandler implements CellWriteHandler {
    /**
     * 设置字体样式
     * @param writeSheetHolder
     * @param writeTableHolder Nullable.It is null without using table writes.
     * @param cellDataList     Nullable.It is null in the case of add header.There may be several when fill the data.
     * @param cell
     * @param head             Nullable.It is null in the case of fill data and without head.
     * @param relativeRowIndex Nullable.It is null in the case of fill data.
     * @param isHead           It will always be false when fill data.
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 创建字体样式
        // 设置内容字体样式
        WriteFont writeFont = new WriteFont();
        writeFont.setFontName("宋体");
        // 核心设置字体样式
        writeFont.setColor(IndexedColors.RED.getIndex());
        for (int i = 0; i < cellDataList.size(); i++) {
            WriteCellData<?> writeCellData = cellDataList.get(i);
            WriteCellStyle writeCellStyle = writeCellData.getWriteCellStyle();
            writeCellStyle.setBorderLeft(THIN);
            writeCellStyle.setBorderRight(THIN);
            writeCellStyle.setBorderTop(THIN);
            writeCellStyle.setBorderBottom(THIN);
            writeCellStyle.setWriteFont(writeFont);
            writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            writeCellStyle.setShrinkToFit(true);
        }
    }

}

多级标题实现

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/983846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GMSL技术让汽车数据传输更为高效(转)

目前&#xff0c;大部分车企都在其旗舰车型上配备了达到Level 2水平的自动驾驶技术&#xff0c;也就是高级自动驾驶辅助 ADAS系统。ADAS系统硬件主要由以下几部分组成&#xff0c;包括传感器、串行器、解串器、ADAS处理器等。 除了ADAS系统&#xff0c;包括传感器融合、音视频影…

Python实现SSA智能麻雀搜索算法优化LightGBM回归模型(LGBMRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 麻雀搜索算法(Sparrow Search Algorithm, SSA)是一种新型的群智能优化算法&#xff0c;在2020年提出&a…

山西电力市场日前价格预测【2023-09-08】

日前价格预测 预测明日&#xff08;2023-09-08&#xff09;山西电力市场全天平均日前电价为356.28元/MWh。其中&#xff0c;最高日前电价为409.23元/MWh&#xff0c;预计出现在19: 30。最低日前电价为323.46元/MWh&#xff0c;预计出现在24: 00。 价差方向预测 1&#xff1a; 实…

封装flexible.js,页面替换px为rem,实现不同分辨率适配

做的vue项目需要做个大屏&#xff0c;需要适配不同电脑的分配率&#xff0c;想到了rem&#xff0c;但是直接通过npm install flexible 安装的flexible.js默认设置的分辨率范围不符合现有的需求&#xff0c;所以就把安装包里面的flexible.js单独拿出来&#xff0c;然后改下分辨率…

idea的git入门

&#xff08;1&#xff09;安装好git之后&#xff0c;在idea的设置里面&#xff0c;按照下面三步&#xff0c;配置git &#xff08;2&#xff09;创建本地git仓库 选择本地仓库的根目录&#xff0c;点击ok &#xff08;3&#xff09;创建成功之后&#xff0c;会发现文件名称都变…

C/C++输出第二个整数 2019年9月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 一、题目要求 1、编程实现 2、输入输出 二、解题思路 1、案例分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 2019年9月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 输入三个整数&#xff0c;把第二个输入的整数输出。 2、输入输出 输…

腾讯混元助手使用指南

一、腾讯混元助手简介 腾讯混元助手是什么&#xff1f; 腾讯混元助手是由腾讯研发的大语言模型的平台产品&#xff0c;具备跨领域知识和自然语言理解能力&#xff0c;实现基于人机自然语言对话的方式&#xff0c;理解用户指令并执行任务&#xff0c;帮助用户实现人获取信息&am…

利用观测云实现业务数据驱动的弹性扩缩容

背景 在使用观测云对业务系统进行观测的过程中&#xff0c;除了可以实现业务系统的全面感知&#xff0c;我们还可以基于观测云数据处理开发平台 DataFlux Func &#xff0c;结合故障模型对被测系统进行主动管理&#xff0c;例如弹性扩容或系统故障自愈&#xff0c;从而实现系统…

VirtualBox的菜单栏被隐藏

一、virtualbox虚拟机里面最顶部没有控制&#xff0c;设置和帮助选项 的解决办法&#xff1a; 右边的CtrlC 二、linux终端上下滚动 向上滚动&#xff1a;Shift Page Up 向下滚动&#xff1a;Shift Page Down

使用T2-U和Sensor_Hub开发一款智能温湿度计

文章目录 传感器 SHT30SHT30 概述数据读取1. 单次读取2. 周期读取3. 数据转换 产品创建第一步&#xff1a;选择品类第二步&#xff1a;选择功能第三步&#xff1a;选择控制面板第四步&#xff1a;选择开发方式 Sensor Hub 应用使用示例1. 设备注册、查找设备获取设备句柄2. 设备…

Qt 4设置界面区域外的颜色

Qt4界面小于显示屏, 设置界面范围之外的背后的显示颜色&#xff1a;

期权交易策略主要有哪些?期权交易策略指南

在学习更复杂的看涨和看跌期权策略之前&#xff0c;普通投资者应该彻底了解一些关于期权的基本知识&#xff0c;这样有助你后期的交易能力和理论知识水平提升有很大的帮助&#xff0c;下文科普期权交易策略主要有哪些&#xff1f;期权交易策略指南&#xff01;本文来自&#xf…

利用transform和border 创造简易图标,以适应uniapp中多字体大小情况下的符号问题

heml: <text class"icon-check"></text> css: .icon-check {border: 2px solid black;border-left: 0;border-top: 0;height: 12px;width: 6px;transform-origin: center;transform: rotate(45deg);} 实际上就是声明一个带边框的div 将其中相邻的两边去…

抖音小店爆款制造指南:打造抖音爆款商品的八大技巧

抖音小店作为一种电商模式&#xff0c;通过短视频形式展示商品&#xff0c;吸引用户购买。在抖音平台上&#xff0c;打造爆款商品是每个抖音小店主的梦想。以下是四川不若与众整理的一些抖音小店如何打造爆款商品的技巧。 1. 产品选择&#xff1a;选择适合抖音平台的产品非常重…

mysql数据库,字符串使用双引号““导致报错,使用单引号‘‘不报错,Unknown column ‘user-test‘ in ‘where clause‘

文章目录 一、完整报错二、报错数据三、报错原因四、解决方式1、更改执行sql2、更改sql数据校验模式&#xff08;改为默认校验&#xff09; 一、完整报错 > 1054 - Unknown column user-test in where clause二、报错数据 SELECT * FROM config_info WHERE config_info.da…

肖sir__设计测试用例方法之正交表08_(黑盒测试)

设计测试用例方法之正交 一、正交表定义 正交试验设计法&#xff0c;是从大量的试验点中挑选出适量的、有代表性的点&#xff0c;应用依据迦罗瓦理论导出的“正交表”&#xff0c;合理的安排试验的一种科学的试验设计方法。 二、 正交常用的术语 指标&#xff1a;通常把判断试验…

Mongodb 安装脚本(附服务器自启动)

shell脚本 #!/bin/bash #mail:xuelanchnet.com #function:auto install mongodb [ $(id -u) ! "0" ] && echo "Error: You must be root to run this script" && exit 1 logfile"/var/log/mongod_install.log" softdir"/s…

索尼 toio™ 应用创意开发征文|小巧机器,大无限,探索奇妙世界

文章目录 前言微型机器人的未来&#xff1a;toio™小机器人简介toio™小机器人&#xff1a;创新功能一览toio™小机器人&#xff1a;多领域的变革者toio™小机器人贪吃蛇游戏代码实现写在最后 前言 当我们谈到现代科技的创新时&#xff0c;往往会联想到复杂的机器和高级的编程…

腾讯正式发布新混元大模型:规模超千亿,预训练语料超2万亿

2023腾讯全球数字生态大会于9月7日举办&#xff0c;腾讯公司在此正式发布了其新的混元大模型。该模型参数规模超过千亿&#xff0c;预训练语料超过2万亿tokens&#xff0c;并已成功测试于腾讯云、腾讯广告、微信搜一搜等多个内部业务和产品中。 这一混元大模型不仅能服务于腾讯…

基于SSM的社区文化宣传网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…