Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于分别修改表头和body样式的问题 #396

Open
zhangwx95 opened this issue Nov 7, 2024 · 12 comments
Open

关于分别修改表头和body样式的问题 #396

zhangwx95 opened this issue Nov 7, 2024 · 12 comments

Comments

@zhangwx95
Copy link

麻烦大佬帮忙看下我这个问题,应该是我对样式修改没理解,谢谢。
我现在有个输出的样式的需求,表头所有列宽指定且要换行改字体大小,body不换行以及其他格式要求
我现在通过ListSheet<>添加数据 Sheet sumSheet = new ListSheet<>(resultSummaryPOS).setName("汇总");
本来想通过setHeadStyle设置表头,但没看到可以设置表头换行的方法
那么通过Column[] 构造列
然后通过sheet.setColumns设置表头,如wiki所写为例,

sheet.setColumns(new Column[] {  
        new Column("编码", "code").setWidth(20.0D).setWrapText(true).setFont(new Font("宋体",10))  
        , new Column("姓名", "name").setWidth(20.0D).setWrapText(true).setFont(new Font("宋体",10)) 
        , new Column("日期", "date").setWidth(20.0D).setWrapText(true).setFont(new Font("宋体",10)) 
        , new Column("数字", "num").setWidth(20.0D).setWrapText(true).setFont(new Font("宋体",10)) 
});

然后我该如何修改body样式?也是如wiki里所写吗?

new Workbook()
    .addSheet(new ListSheet<>(resultSummaryPOS
        , new Column("编码", "code").setFont(new Font("Trebuchet MS", 20))
        , new Column("姓名", "name").setFont(new Font("Trebuchet MS", 20)).setHorizontal(Horizontals.CENTER) // <-- 设置水平居中
        , new Column("日期", "date").setFont(new Font("华文行楷", 11)).setNumFmt("yyyy-mm-dd hh:mm:ss")
        , new Column("数字", "num").setFont(new Font("Bauhaus 93", 14)).setNumFmt("#,##0_);[Red]-#,##0_);0_)") // <- 指定字体和格式化
    )).writeTo(Paths.get("f:/excel"));

那是不是意味着有两个Column[] ,分别是表头和body的,且分别生效互不影响?还是说不是我这么理解的,麻烦大佬,谢谢~

@wangguanquan
Copy link
Owner

wangguanquan commented Nov 7, 2024

通过new Column("编码", "code").setWidth(20.0D).setWrapText(true).setFont(new Font("宋体",10)) 设置的样式均为body样式,目前只能通过setHeaderStyle设置表头样式

Workbook workbook = new Workbook();
Styles styles = workbook.getStyles();
int headerStyle = styles.addFont(new Font("宋体",10));
// 折行
headerStyle = styles.modifyWrapText(headerStyle, true);
// 水平居中
headerStyle = styles.modifyHorizontal(headerStyle, Horizontals.CENTER);

workbook.addSheet(new ListSheet<>(resultSummaryPOS
        , new Column("编码", "code").setFont(new Font("Trebuchet MS", 20)).setHeaderStyle(headerStyle)
        , new Column("姓名", "name").setFont(new Font("Trebuchet MS", 20)).setHorizontal(Horizontals.CENTER).setHeaderStyle(headerStyle) // <-- 设置水平居中
        , new Column("日期", "date").setFont(new Font("华文行楷", 11)).setNumFmt("yyyy-mm-dd hh:mm:ss").setHeaderStyle(headerStyle)
        , new Column("数字", "num").setFont(new Font("Bauhaus 93", 14)).setNumFmt("#,##0_);[Red]-#,##0_);0_)").setHeaderStyle(headerStyle) // <- 指定字体和格式化
    )).writeTo(Paths.get("f:/excel"));

如果表头样式一样的则可以使用ListSheet.setHeadStyle(headerStyle)来设置统一的表头样式,使用Column.setHeadStyle(headerStyle)可以为每一列设置不同的表头样式,设置不同的背景和颜色可以起到提示作用,可以参考WIKI静态样式设置

@zhangwx95
Copy link
Author

感谢大佬,在wiki看漏了setHeaderStyle(borderStyle)这个方法 TAT
再问一下,如果不用Column,而是实体类上用了@ExcelColumn注解,生效的也是body样式吗?我看@ExcelColumn注解里没有设置font的方法,是不是意味着要设置body的font只能用Column?感谢~

@wangguanquan
Copy link
Owner

wangguanquan commented Nov 8, 2024 via email

@zhangwx95
Copy link
Author

明白了,感谢大佬

@wangguanquan
Copy link
Owner

你可以先尝试做一下,直接复制高级特性里的代码然后将上面的代码添加到Column即可,自定义注解可以更通用

如果只是需要添加样式则可以简单实现大体如下
样式注解可以放在createColumn方法中,表头样式注解一般可以放在对象上不需要每个字段都添加

// 添加body样式
@Override
protected ListSheet.EntryColumn createColumn(AccessibleObject ao) {
    ListSheet.EntryColumn column = super.createColumn(ao);
    // 解析自定义Body样式注解
    ExcelStyle bodyStyle = ao.getAnnotation(ExcelStyle.class);
    if (bodyStyle != null) {
        Font font = headerStyle.getFont();
        if (font != null) {
            // 修改表头样式
            column.setFont(font);
        }
        ... 复制上面的代码添加样式
    }
}

// 添加header样式
protected void buildHeaderStyle(AccessibleObject main, AccessibleObject sub, Column column) {
    // 从对象头上拿到注释
   ExcelStyle headerStyle = tClazz.getAnnotation(ExcelStyle.class);
    if (headerStyle != null) {
        Styles styles = workbook.getStyles();
        Font font = headerStyle.getFont();
        int styleIndex = 0;
        if (font != null) {
            styleIndex = styles.modifyFont(styles.createFont(font));
        }
        ... 复制上面的代码
            
        // 修改表头样式
        column.setHeaderStyle(styleIndex);
    }
}

这只是示例效果得自己尝试,如果注释不好使用则可能自定义一个ListSheet传入一个ExcelStyle对象,像下面这样

public class CustomStyleListSheet<T> extends ListSheet<T> {
    private ExcelStyle headerStyle, bodyStyle; // 传入表头和body样式
    public CustomStyleListSheet(ExcelStyle headerStyle, ExcelStyle bodyStyle) {
        this.headerStyle = headerStyle;
        this.bodyStyle = bodyStyle;
    }
    
    // 其它不变方法和上面的一样修改即可,不再需要从注解从获取
}

@zhangwx95
Copy link
Author

zhangwx95 commented Nov 8, 2024

你可以先尝试做一下,直接复制高级特性里的代码然后将上面的代码添加到Column即可,自定义注解可以更通用

如果只是需要添加样式则可以简单实现大体如下 样式注解可以放在createColumn方法中,表头样式注解一般可以放在对象上不需要每个字段都添加

// 添加body样式
@Override
protected ListSheet.EntryColumn createColumn(AccessibleObject ao) {
    ListSheet.EntryColumn column = super.createColumn(ao);
    // 解析自定义Body样式注解
    ExcelStyle bodyStyle = ao.getAnnotation(ExcelStyle.class);
    if (bodyStyle != null) {
        Font font = headerStyle.getFont();
        if (font != null) {
            // 修改表头样式
            column.setFont(font);
        }
        ... 复制上面的代码添加样式
    }
}

// 添加header样式
protected void buildHeaderStyle(AccessibleObject main, AccessibleObject sub, Column column) {
    // 从对象头上拿到注释
   ExcelStyle headerStyle = tClazz.getAnnotation(ExcelStyle.class);
    if (headerStyle != null) {
        Styles styles = workbook.getStyles();
        Font font = headerStyle.getFont();
        int styleIndex = 0;
        if (font != null) {
            styleIndex = styles.modifyFont(styles.createFont(font));
        }
        ... 复制上面的代码
            
        // 修改表头样式
        column.setHeaderStyle(styleIndex);
    }
}

这只是示例效果得自己尝试,如果注释不好使用则可能自定义一个ListSheet传入一个ExcelStyle对象,像下面这样

public class CustomStyleListSheet<T> extends ListSheet<T> {
    private ExcelStyle headerStyle, bodyStyle; // 传入表头和body样式
    public CustomStyleListSheet(ExcelStyle headerStyle, ExcelStyle bodyStyle) {
        this.headerStyle = headerStyle;
        this.bodyStyle = bodyStyle;
    }
    
    // 其它不变方法和上面的一样修改即可,不再需要从注解从获取
}

好的,看上去自定义一个ListSheet传入一个ExcelStyle对象好像更简单点,我有空了一定尝试下到时候回复;

现在遇到个新问题,设置表头自动换行后,高度没有自适应调整,表头样式里确实也没找到调整高度的地方?
image

@wangguanquan
Copy link
Owner

wangguanquan commented Nov 8, 2024

EEC默认表头行高20.5与Body相区隔这里没有考虑到wrapText后续改进。Sheet有一个方法setHeaderRowHeight可以用于设置高度,正数为实际行高,负数表示不设置自动计算new ListSheet<>().setHeaderRowHeight(-1)

@zhangwx95
Copy link
Author

zhangwx95 commented Nov 8, 2024

谢谢大佬,setHeaderRowHeight(-1)可以生效
我自己尝试了自定义注解,表头已经生效了,
但是自定义的body没有生效,我把body注解也放在对象上,打断点看是因为bodyStyle为null,麻烦看看问题在哪,感谢~
自定义注解

@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface HeaderExcelStyle {

    String fontName() default "宋体";

    int fontSize() default 10;

    boolean wrapText() default true;

    ColorDefine color() default ColorDefine.Z_BLUE;

}



@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface BodyExcelStyle {
    String fontName() default "宋体";

    int fontSize() default 10;

    double width() default 11D;

}

自定义ListSheet

 @Override
    protected ListSheet.EntryColumn createColumn(AccessibleObject ao) {
        ListSheet.EntryColumn column = super.createColumn(ao);
//        // 解析自定义Body样式注解
        BodyExcelStyle bodyStyle = ao.getAnnotation(BodyExcelStyle.class);
        if (bodyStyle != null) {
            Font font = new Font(bodyStyle.fontName(),bodyStyle.fontSize());
            if (font != null) {
                // 修改表头样式
                column.setFont(font);
            }

        }
        return column;
    }

    // 添加header样式
    @Override
    protected void buildHeaderStyle(AccessibleObject main, AccessibleObject sub, Column column) {
        // 从对象头上拿到注释
        HeaderExcelStyle headerStyle = tClazz.getAnnotation(HeaderExcelStyle.class);
        if (headerStyle != null) {
            Styles styles = workbook.getStyles();
            Font font = new Font(headerStyle.fontName(), headerStyle.fontSize());
            int styleIndex = 0;
            if (font != null) {
                styleIndex = styles.addFont(font);
            }
            styleIndex = styles.modifyHorizontal(styleIndex, Horizontals.CENTER);
            styleIndex = styles.modifyVertical(styleIndex, Verticals.CENTER);
            styleIndex = styles.modifyWrapText(styleIndex, headerStyle.wrapText());
            Color color = headerStyle.color().getRGB();
            if (color != null) {
                styleIndex = styles.modifyFill(styleIndex, new Fill(PatternType.solid, color));
            }

            // 修改表头样式
            column.setHeaderStyle(styleIndex);
        }

    }

@wangguanquan
Copy link
Owner

优秀,这样写已经可以满足你现在的需求,不过可以更进一步通用化,可以包含所有Style样式不限制字体,折行和颜色两种样式。
还可以将行高放在buildHeaderStyle方法,wrapText=true时默认将HeaderRowHeight设为-1,这样在外部就不需要再次设置了

@zhangwx95
Copy link
Author

优秀,这样写已经可以满足你现在的需求,不过可以更进一步通用化,可以包含所有Style样式不限制字体,折行和颜色两种样式。 还可以将行高放在buildHeaderStyle方法,wrapText=true时默认将HeaderRowHeight设为-1,这样在外部就不需要再次设置了

谢谢大佬,行高设置我修改后生效了

if(headerStyle.wrapText()){
                headerRowHeight = -1;
            }

不过没太懂 可以包含所有Style样式不限制字体,折行和颜色两种样式 这个是什么意思?

@wangguanquan
Copy link
Owner

优秀,这样写已经可以满足你现在的需求,不过可以更进一步通用化,可以包含所有Style样式不限制字体,折行和颜色两种样式。 还可以将行高放在buildHeaderStyle方法,wrapText=true时默认将HeaderRowHeight设为-1,这样在外部就不需要再次设置了

谢谢大佬,行高设置我修改后生效了

if(headerStyle.wrapText()){
                headerRowHeight = -1;
            }

不过没太懂 可以包含所有Style样式不限制字体,折行和颜色两种样式 这个是什么意思?

我看BodyExcelStyle只定义了字体,折行和颜色,所以建议写个更通用的,比如加上背景,边框,格式化,垂直对齐,水平对齐这几个样式,当然这个并不是必须的,根据业务需求来适配即可。

@zhangwx95
Copy link
Author

优秀,这样写已经可以满足你现在的需求,不过可以更进一步通用化,可以包含所有Style样式不限制字体,折行和颜色两种样式。 还可以将行高放在buildHeaderStyle方法,wrapText=true时默认将HeaderRowHeight设为-1,这样在外部就不需要再次设置了

谢谢大佬,行高设置我修改后生效了

if(headerStyle.wrapText()){
                headerRowHeight = -1;
            }

不过没太懂 可以包含所有Style样式不限制字体,折行和颜色两种样式 这个是什么意思?

我看BodyExcelStyle只定义了字体,折行和颜色,所以建议写个更通用的,比如加上背景,边框,格式化,垂直对齐,水平对齐这几个样式,当然这个并不是必须的,根据业务需求来适配即可。

哦哦 看懂了 断句断错了哈哈哈哈 谢谢大佬

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants