easyexcel icon indicating copy to clipboard operation
easyexcel copied to clipboard

实现CellWriteHandler接口导出文件为xlsx样式代码格式不生效,导出格式为xls能生效

Open liuminminmin opened this issue 1 year ago • 12 comments

建议先去看文档

快速开始常见问题

触发场景描述

触发Bug的代码

   这里写代码
``` public static void main(String[] args) throws Exception {
        String fileName = "D:/excel/easyexcel.xlsx";

        writeExcel(null, new ArrayList<>(), fileName, "test", BonusSupplyInfoDTO.class);
    }
    public static void writeExcel(HttpServletResponse resp, List<? extends Object> data, String fileName, String sheetName, Class clazz) throws Exception {

        EasyExcel.write(fileName, clazz).sheet(sheetName)
                .registerWriteHandler(new CellWriteHandler() {
                    @Override
                    public void afterCellDispose(CellWriteHandlerContext context) {
                        if (context.getHead()) {
                            Cell cell = context.getCell();
                            String stringCellValue = cell.getStringCellValue();
                            Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
                            RichTextString richTextString = workbook.getCreationHelper().createRichTextString(stringCellValue);
                            Font font = workbook.createFont();
                            font.setColor(Font.COLOR_RED);
                            richTextString.applyFont(0, 1, font);
                            cell.setCellValue(richTextString);
                        }
                    }
                }).doWrite(data);
    }
# 提示的异常或者没有达到的效果
导出的文件格式为xlsx,代码设置的样式没生效,为xls时,导出样式会生效

liuminminmin avatar Jul 05 '24 03:07 liuminminmin

xls格式使用的字体样式类为org.apache.poi.ss.usermodel.Font,xlsx格式使用的字体样式类为org.apache.poi.xssf.usermodel.XSSFFont,参考如下:

        if (isHead) {
            Sheet sheet = writeSheetHolder.getSheet();
            Workbook workbook = sheet.getWorkbook();
            XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle();
            // 复制已存在的样式
            cellStyle.cloneStyleFrom(cell.getCellStyle());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            // RGB颜色值
            //IndexedColorMap colorMap = ((XSSFWorkbook) workbook).getStylesSource().getIndexedColors();
            int red = 0, green = 0, blue = 0;
            XSSFColor color = new XSSFColor(new Color(red, green, blue), new DefaultIndexedColorMap());
            // 设置RGB背景颜色
            cellStyle.setFillForegroundColor(color);
            // 设置RGB字体颜色
            XSSFFont font = cellStyle.getFont();
            font.setColor(color);
            cellStyle.setFont(font);
            cellStyle.setDataFormat(49);
            cell.setCellStyle(cellStyle);
        }

LSL1618 avatar Jul 05 '24 03:07 LSL1618

xls格式使用的字体样式类为org.apache.poi.ss.usermodel.Font,xlsx格式使用的字体样式类为org.apache.poi.xssf.usermodel.XSSFFont,参考如下:

        if (isHead) {
            Sheet sheet = writeSheetHolder.getSheet();
            Workbook workbook = sheet.getWorkbook();
            XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle();
            // 复制已存在的样式
            cellStyle.cloneStyleFrom(cell.getCellStyle());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            // RGB颜色值
            //IndexedColorMap colorMap = ((XSSFWorkbook) workbook).getStylesSource().getIndexedColors();
            int red = 0, green = 0, blue = 0;
            XSSFColor color = new XSSFColor(new Color(red, green, blue), new DefaultIndexedColorMap());
            // 设置RGB背景颜色
            cellStyle.setFillForegroundColor(color);
            // 设置RGB字体颜色
            XSSFFont font = cellStyle.getFont();
            font.setColor(color);
            cellStyle.setFont(font);
            cellStyle.setDataFormat(49);
            cell.setCellStyle(cellStyle);
        }

还是没生效呀,我要实现的是把excel的表头的第一个字符变成红色

liuminminmin avatar Jul 05 '24 04:07 liuminminmin

还有进展吗。我这里也有同样问题

EasyExcel.write(response.getOutputStream()) .head(headListAll) .excelType(ExcelTypeEnum.XLSX) .sheet("") 
//.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自动调整列宽 
.registerWriteHandler(new CellWriteHandler() {
 // 注册单元格写入处理器
 @Override
 public int order(){ return 50000; } 
@Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { 
// 在这里可以做任何初始化工作 }
                @Override
                public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
                                            Head head, Integer relativeRowIndex, Boolean isHead) {
                    // 在这里可以设置单元格样式
                    if (!isHead && deleteLine.contains(relativeRowIndex)) { // 假设只对第一列设置删除线
                        CellStyle style = cell.getCellStyle();
                        XSSFFont font = (XSSFFont) cell.getSheet().getWorkbook().createFont();
                        font.setColor(Font.COLOR_RED);
                        font.setStrikeout(true); // 设置删除线
                        style.setFont(font);
                        cell.setCellStyle(style);
                        writeSheetHolder.getSheet();
                    }
                }
                @Override
                public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                                   WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead){
                    // 在这里可以设置单元格样式
                    if (!isHead && deleteLine.contains(relativeRowIndex)) { // 假设只对第一列设置删除线
                        CellStyle style = cell.getCellStyle();
                        Font font = cell.getSheet().getWorkbook().createFont();
                        font.setColor(Font.COLOR_RED);
                        font.setStrikeout(true); // 设置删除线
                        style.setFont(font);
                        cell.setCellStyle(style);
                    }
                }
                @Override
               public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                            List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
                    // 在这里可以设置单元格样式
                    if (!isHead && deleteLine.contains(relativeRowIndex)) { // 假设只对第一列设置删除线
                        CellStyle style = cell.getCellStyle();
                        Font font = cell.getSheet().getWorkbook().createFont();
                        font.setColor(Font.COLOR_RED);
                        font.setStrikeout(true); // 设置删除线
                        style.setFont(font);
                        cell.setCellStyle(style);
                    }
                }

            })
            .doWrite(dataListAll); 

上述地方都试过好像没有成功。有啥建议没

cxp4 avatar Jul 27 '24 14:07 cxp4

@cxp4 ,建议只在afterCellDispose方法中设置样式,你这样3个方法都设置会存在覆盖问题。还有个颜色关键点要设置填充模式cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

LSL1618 avatar Aug 01 '24 08:08 LSL1618

我知道这个,写三个方法的意思是证明3个我都试验过。 颜色的部分谢谢指教。 xlsx无法生成删除线的问题我有些感觉因为没有重新从workhook中createCellStyle的问题(可能不确定)xls导出模式中是有效的。

---原始邮件--- 发件人: @.> 发送时间: 2024年8月1日(周四) 下午4:32 收件人: @.>; 抄送: @.@.>; 主题: Re: [alibaba/easyexcel] 实现CellWriteHandler接口导出文件为xlsx样式代码格式不生效,导出格式为xls能生效 (Issue #3866)

@cxp4 ,建议只在afterCellDispose方法中设置样式,你这样3个方法都设置会存在覆盖问题。还有个颜色关键点要设置填充模式cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);。

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

cxp4 avatar Aug 01 '24 09:08 cxp4

有结果了吗? [3674](url)

我知道这个,写三个方法的意思是证明3个我都试验过。 颜色的部分谢谢指教。 xlsx无法生成删除线的问题我有些感觉因为没有重新从workhook中createCellStyle的问题(可能不确定)xls导出模式中是有效的。 ---原始邮件--- 发件人: @.> 发送时间: 2024年8月1日(周四) 下午4:32 收件人: @.>; 抄送: @.@.>; 主题: Re: [alibaba/easyexcel] 实现CellWriteHandler接口导出文件为xlsx样式代码格式不生效,导出格式为xls能生效 (Issue #3866) @cxp4 ,建议只在afterCellDispose方法中设置样式,你这样3个方法都设置会存在覆盖问题。还有个颜色关键点要设置填充模式cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);。 — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

lolkt avatar Aug 28 '24 06:08 lolkt

有进展了吗?我也发现了,在afterCellDispose应用头部样式不生效

xi-xi-jun avatar Sep 11 '24 05:09 xi-xi-jun

没有,换我这里直接换成了xls,使用起来问题不大。 同时记得从sheet层面新建样式不哟样式覆盖

---原始邮件--- 发件人: @.> 发送时间: 2024年9月11日(周三) 中午1:50 收件人: @.>; 抄送: @.@.>; 主题: Re: [alibaba/easyexcel] 实现CellWriteHandler接口导出文件为xlsx样式代码格式不生效,导出格式为xls能生效 (Issue #3866)

有进展了吗?我也发现了,在afterCellDispose应用头部样式不生效

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

cxp4 avatar Sep 11 '24 05:09 cxp4

https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%B7%E5%BC%8F,这文档里说可以使用easyexcel的样式、poi的样式2种方式来设置。我测试了poi的样式,确实有效。 image image

LSL1618 avatar Sep 14 '24 02:09 LSL1618

@LSL1618 你是正确的,我提醒一下,重点在于这一句,原文档是这样说的: image

end1314 avatar Sep 20 '24 01:09 end1314

@LSL1618 你是正确的,我提醒一下,重点在于这一句,原文档是这样说的: image

你好 图片 我在这里设置了表单锁定,然后 图片 这个地方解锁特定的单元格,为什么我这样写是不生效的呢

409713427 avatar Nov 28 '24 06:11 409713427

@409713427 我也没用过表格锁定解锁功能,不太清楚是否支持这种整个sheet锁定、单个cell解锁的情景。另外afterSheetCreate()和afterCellDispose()这2个方法需要搞清楚谁先执行谁后执行。

LSL1618 avatar Nov 29 '24 04:11 LSL1618