poi 导出excel 加水印

1、引入相关依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.1</version>
</dependency>

2、ExcelWaterMarkUtil 工具类

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.BindException;

/**
 * poi 导出excel加水印 工具类
 * 该工具类只适用于 XSSFWorkbook、XSSFSheet,其他类型未测试
 * @author test
 */
public class ExcelWaterMarkUtil {

    private static BufferedImage createWatermarkImage(WaterMarkBean waterMark) {
        int width = waterMark.getWidth();
        int height = waterMark.getHeight();
        Font font = waterMark.getFont();  //字体

        // 创建空白图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取图片画笔
        Graphics2D g2d = image.createGraphics();
        // 设置背景透明度
        image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g2d.dispose();

        g2d = image.createGraphics();
        g2d.setColor(new Color(0, 0, 0, 30)); // 设置字体颜色和透明度,最后一个参数为透明度
        g2d.setStroke(new BasicStroke(1)); // 设置字体
        g2d.setFont(font); // 设置字体类型  加粗 大小
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  // 设置字体平滑
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));// 设置透明度

        // 水印位置
        int x = width / 2;
        int y = height / 2;
        // 设置水印旋转
        g2d.rotate(Math.toRadians(-30), x, y);

        //文字从中心开始输入,算出文字宽度,左移动一半的宽度,即居中
        FontMetrics fontMetrics = g2d.getFontMetrics(font);
        String[] content = waterMark.getContent().split("\n");
        for (String context : content) {
            int textWidth = fontMetrics.stringWidth(context); // 文字宽度
            g2d.drawString(context, x - (textWidth / 2), y);// 画出字符串
            y = y + font.getSize();
        }

        // 释放对象
        g2d.dispose();
        return image;
    }

    /**
     * 为Excel打上水印工具函数 请自行确保参数值,以保证水印图片之间不会覆盖。
     * @param workbook Excel Workbook
     * @throws IOException
     */
    public static void addWaterMarkToExcel(Workbook workbook, WaterMarkBean waterMark) throws IOException {
        if (waterMark == null || waterMark.getContent() == null) {
            throw new BindException("水印配置信息不可为空");
        }

        // 创建水印图片
        BufferedImage image = createWatermarkImage(waterMark);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(image, "png", os);

        int pictureIdx = workbook.addPicture(os.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG);
        POIXMLDocumentPart poixmlDocumentPart = (POIXMLDocumentPart) workbook.getAllPictures().get(pictureIdx);
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表
            XSSFSheet sheet = (XSSFSheet) workbook.getSheetAt(i);
            PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
            String relType = XSSFRelation.IMAGES.getRelation();
            PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
            sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
        }
    }

}

3、WaterMarkBean 水印配置封装类

import java.awt.*;

/**
 * @description: 水印配置封装类
 * @auth: yang.jicheng
 * @date: 2024-11-08 15:00
 */
public class WaterMarkBean {

    //水印内容,多行文字使用\n分隔
    private String content;

    //水印高度
    private int height;

    //水印宽度
    private int width;

    //水印字体
    private String fontName;

    //水印字体样式 Font.PLAIN、Font.BOLD、Font.ITALIC
    private int fontStyle;

    //水印字体大小
    private int fontSize;

    public WaterMarkBean(String content) {
        this.content = content;
        this.height = 400;
        this.width = 500;
        this.fontName = "microsoft-yahei";
        this.fontStyle = Font.BOLD;
        this.fontSize = 28;
    }

    public WaterMarkBean(String content, int height, int width) {
        this.content = content;
        this.height = height;
        this.width = width;
        this.fontName = "microsoft-yahei";
        this.fontStyle = Font.BOLD;
        this.fontSize = 28;
    }

    public WaterMarkBean(String content, String fontName, int fontStyle, int fontSize) {
        this.content = content;
        this.fontName = fontName;
        this.fontStyle = fontStyle;
        this.fontSize = fontSize;
        this.height = 400;
        this.width = 500;
    }

    public WaterMarkBean(String content, int height, int width, String fontName, int fontStyle, int fontSize) {
        this.content = content;
        this.height = height;
        this.width = width;
        this.fontName = fontName;
        this.fontStyle = fontStyle;
        this.fontSize = fontSize;
    }


    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public String getFontName() {
        return fontName;
    }

    public void setFontName(String fontName) {
        this.fontName = fontName;
    }

    public int getFontStyle() {
        return fontStyle;
    }

    public void setFontStyle(int fontStyle) {
        this.fontStyle = fontStyle;
    }

    public int getFontSize() {
        return fontSize;
    }

    public void setFontSize(int fontSize) {
        this.fontSize = fontSize;
    }

    public Font getFont() {
        return new Font(this.fontName, this.fontStyle, this.fontSize);
    }
}

4、实现效果

image

5、可能遇到的问题

1、沒有CTSheetBackgroundPicture封装类
应版本问题,可能没有 CTSheetBackgroundPicture封装类, 导致 sheet.getCTWorksheet().addNewPicture().setId(pr.getId());报错

解决办法: 引入依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>ooxml-schemas</artifactId>
    <version>1.4</version>
</dependency>
posted @ 2024-11-08 16:36  初·陽  阅读(68)  评论(0编辑  收藏  举报