使用easyExcel模板填充时如何自适应行高

文章介绍了在EasyExcel中设置单元格自动换行和行高的方法,包括使用模板和单元格样式策略。同时提到了自适应行高时存在的样式一致性问题以及通过Graphics2D计算字符宽度和行高的复杂实现过程。
摘要由CSDN通过智能技术生成
  • 模板中设置单元格的自动换行和最合适行高

缺点:这种方式只对未合并的单元格有效。

在registerWriteHandler中设置单元格样式策略

{
// 生成excel文件
EasyExcel.write(saveWordFilePath, DirectoryPrint2BO.class)
    .withTemplate(excelFileTemplate)
    .needHead(false)
    // 单元格样式策略
    .registerWriteHandler(this.getHorizontalCellStyleStrategy((short) 12))
    .sheet("Sheet1")
    .doWrite(directoryPrint2BoList);
}
 
/**
* 单元格样式策略
*/
public static HorizontalCellStyleStrategy getHorizontalCellStyleStrategy(Short fontHeightInPoints) {
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 设置边框
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.NONE);
 
        // 配置字体
        WriteFont contentWriteFont = new WriteFont();
        // 字体
        contentWriteFont.setFontName("宋体");
        // 字体大小
        contentWriteFont.setFontHeightInPoints(fontHeightInPoints);
        // 设置加粗
        contentWriteFont.setBold(false);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
 
        // 【水平居中需要使用以下两行】
        // 设置文字左右居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 设置文字上下居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置 自动换行
        contentWriteCellStyle.setWrapped(true);
 
        // 样式策略
        return new HorizontalCellStyleStrategy(null, contentWriteCellStyle);
    }

缺点:实现自适应行高的时候,无法保证样式和模板中一致。

在自定义registerWriteHandler通过代码计算字符宽度和行高

通过Graphics2D自动获取字符的像素宽度和高度

public static double calculateStringWidthInPixels(String text, Font font) {
        Graphics2D g2d = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).createGraphics();
        FontRenderContext frc = g2d.getFontRenderContext();
        Rectangle2D bounds = font.getStringBounds(text, frc);
        return bounds.getWidth();
    }

    public static double calculateStringHeightInPixels(String text, Font font) {
        Graphics2D g2d = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).createGraphics();
        FontRenderContext frc = g2d.getFontRenderContext();
        Rectangle2D bounds = font.getStringBounds(text, frc);
        return bounds.getHeight();
    }

计算字符宽度和所需行高

private void setWrap(Sheet sheet, int rowIndex,  int startColIndex, int endColIndex) {
        if (ObjectUtils.isEmpty(sheet)){
            return;
        }
        Row r = sheet.getRow(rowIndex);
        if (ObjectUtils.isEmpty(r)){
            return;
        }
        Cell c = r.getCell(startColIndex);
        if (ObjectUtils.isEmpty(c)){
            return;
        }
        CellStyle cellStyle = c.getCellStyle();
        if (ObjectUtils.isEmpty(cellStyle)){
            return;
        }
        // 获取当前字体
        Font writeFont = sheet.getWorkbook().getFontAt(cellStyle.getFontIndex());
        // 假设我们有一个字符串和字体
        String text = c.getStringCellValue();
        if (StringUtils.isEmpty(text)){
            return;
        }
        java.awt.Font font = convertToAwtFont(writeFont);

        // 计算字符串的像素宽度
        double pixelWidth = FillUtil.calculateStringWidthInPixels(text, font);
        double pixelHeight = FillUtil.calculateStringHeightInPixels(text, font);

        // 假设一个字符在 Excel 中平均占用 100 像素(这个值需要根据实际情况调整)
        // 然后计算字符宽度(以 1/256 个字符宽度为单位)
        double textWidth = (pixelWidth / 256 * 256);
        double textHeight = (pixelHeight / 256 * 256);
        if (textWidth <= 0){
            return;
        }
        if (textHeight <= 0){
            return;
        }
        //获取列宽
        double totalColWidth = 0;
        for (int i = startColIndex; i <= endColIndex; i++) {
            float currentColWidth = sheet.getColumnWidthInPixels(i);
            totalColWidth += currentColWidth;
        }
        if (totalColWidth <= 0){
            return;
        }
        float currentRowHeight = r.getHeightInPoints();
        //每行除字体外的留白高度
        double eachLineBlankHeight = Math.abs(currentRowHeight - textHeight);
        if (lineBlankHeightMap.containsKey(rowIndex)){
            eachLineBlankHeight = lineBlankHeightMap.get(rowIndex);
        }else {
            lineBlankHeightMap.put(rowIndex, eachLineBlankHeight);
        }
        if (textWidth > totalColWidth){
            //调整行高
            int heightMultiple = (int) Math.ceil(textWidth / totalColWidth);
            if (currentRowHeight < (textHeight + eachLineBlankHeight) * heightMultiple){
                r.setHeightInPoints((currentRowHeight * heightMultiple));
            }
        }
    }

字符宽度和像素宽度之间比例为1:256,行高和像素高度一致,具体需要自行通过代码中的值和模板中的行高、列宽进行比对来确定;

缺点:实现较为复杂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值