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、实现效果
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>