wangguanquan / eec

A fast and lower memory excel write/read tool.一个非POI底层,支持流式处理的高效且超低内存的Excel读写工具
https://github.com/wangguanquan/eec/wiki
Apache License 2.0
205 stars 55 forks source link

在导入excel后 如果有数据校验报错 在对应的cell上更改字体和背景颜色 然后添加tooltips 后重新导出 #383

Open pocketchew opened 3 months ago

pocketchew commented 3 months ago

如题 能不能做到 在导入excel后 如果有数据校验报错 在对应的cell上更改字体和背景颜色 然后添加tooltips 后重新导出'

主要是想要在特定的cell上更改字体和颜色和添加tooltips 这个功能怎么做到

wangguanquan commented 3 months ago

EEC只具备底层操作Excel的能力,不包含任何的业务逻辑,不过可以简单封装来达到这个效果,以下是示例代码

  1. 提前检查数据是否合规,如果全部合规就执行导入,如果有一条不合规就提前中断并创建Excel
  2. 使用TemplateSheet模板工作表做为输出源,这样可以最大限度保留原始文件样式
  3. 检查数据行并按需修改“字体”,“填充色”以及tooltips

麻烦的地方是修改样式,这部分代码可以提出公共方法来处理,不合规样式固定的话可以写死

@Test public void testDataCheck() throws IOException {
    try (ExcelReader reader = ExcelReader.read(Paths.get("./students.xlsx"))) {
        // 提前检查数据是否合规(任意一条不合规就中断)
        boolean invalid = reader.sheet(0).dataRows().map(row -> row.too(Student.class)).anyMatch(e -> !check(e));

        // 包含不合规的数据则创建一个Excel
        if (invalid) {
            new Workbook().addSheet(new TemplateSheet(Paths.get("./students.xlsx")) {
                @Override
                protected void resetBlockData() {
                    super.resetBlockData();

                    // 获取样式表
                    Styles styles = workbook.getStyles();

                    // 再次全面检查所有行数据
                    for (int i = 0, position = rowBlock.position(); i < position; i++) {
                        org.ttzero.excel.entity.Row row = rowBlock.get(i);
                        Cell[] cells = row.getCells();

                        // 检查必要列

                        // 检查“姓名”(设定第2列为“姓名”
                        Cell cell = cells[1];
                        String v = checkName(cell.stringVal);
                        // "姓名"不合规
                        if (v != null) {
                            // 获取原始样式
                            int style = styles.getStyleByIndex(cell.xf);
                            // 修改字体
                            // 如果仅仅是改字体样式,比如改为红色,加粗,斜体等可以先获取原始字体然后再修改
                            Font font = styles.getFont(style); // 注意:这里拿到的是字体的引用,修改前必须clone一份新字体
                            // 修改字体样式 - 改为斜体
                            style = styles.modifyFont(style, font.clone().italic()); // <- 注意这里clone了原始字体然后再改为斜体,如果不clone则将修改所有使用原始字体的单元格

                            // 修改填充色 - 改为橙色
                            style = styles.modifyFill(style, new Fill(Color.ORANGE));

                            // 添加进样式表并修改单元格样式
                            cell.xf = styles.of(style);

                            // 添加tooltips
                            createComments().addComment(new String(int2Col(2)) + (row.getIndex() + 1), new Comment("", v)); // int2Col(2) 将第2列转为Excel的ref值也就是'B'
                        }
                    }
                }
            }.setPrefix("$#@!$")).writeTo(Paths.get("./student-checked.xlsx"));
        }
        // 检查正常的情况下处理导入
        else {
            // TODO
        }
    }
}

public static String checkName(String name) {
    if (StringUtil.isEmpty(name)) {
        return "姓名不能为空";
    }
    if (name.trim().length() > 25) {
        return "姓名过长,最多不超过25个汉字";
    }
    return null;
}

public static boolean check(Student student) {
    return false;
}
wangguanquan commented 3 months ago

导入并检查