package com.hsl.watermark.util;
import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.vml.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STTrueFalse;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.stream.Stream;
/**
* @description: word文档添加水印,支持一行多个,一页多行的效果,而非一页只有一个水印的效果
* @author: slhe
* @version: 1.0
* @date: 2024/8/23 下午1:43
* @Copyright: http://www.powersi.com 2024 创智和宇
*/
@Slf4j
public class WaterMarkUtil {
/** word字体 */
private static final String FONT_NAME = "宋体";
/** 字体大小 */
private static final String FONT_SIZE = "0.3pt";
/** 字体颜色 */
private static final String FONT_COLOR = "#C0C0C0";
/** 一个字平均长度,单位pt,用于:计算文本占用的长度(文本总个数*单字长度)*/
private static final Integer WIDTH_PER_WORD = 10;
/** 文本旋转角度 */
private static final String STYLE_ROTATION = "30";
public static void waterMarkDocXDocument(String inPutPath, String putPutPath, String fingerText) {
long beginTime = System.currentTimeMillis();
try (
OutputStream out = new FileOutputStream(putPutPath);
InputStream in = new FileInputStream(inPutPath);
OPCPackage srcPackage = OPCPackage.open(in);
XWPFDocument doc = new XWPFDocument(srcPackage)
) {
// 把整页都打上水印
int i = 0, marginTop;
for (int lineIndex = -1; lineIndex < 6; lineIndex++) {
marginTop = 300 * lineIndex;
waterMarkDocXDocument(doc, fingerText, i, marginTop);
i++;
}
// 输出新文档
doc.write(out);
log.info("添加水印成功!一共耗时" + (System.currentTimeMillis() - beginTime) + "毫秒");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void waterMarkDocXDocument(XWPFDocument doc, String fingerText, int i, int marginTop) {
// 水印文字之间使用8个空格分隔
fingerText = fingerText + repeatString(" ", 8);
// 一行水印重复水印文字次数
fingerText = repeatString(fingerText, 5);
// 如果之前已经创建过 DEFAULT 的Header,将会复用
XWPFHeader header = doc.createHeader(HeaderFooterType.DEFAULT);
int size = header.getParagraphs().size();
if (size == 0) {
header.createParagraph();
}
CTP ctp = header.getParagraphArray(0).getCTP();
byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
byte[] rsidrDefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
ctp.setRsidP(rsidr);
ctp.setRsidRDefault(rsidrDefault);
CTPPr ppr = ctp.addNewPPr();
ppr.addNewPStyle().setVal("Header");
// 开始加水印
CTR ctr = ctp.addNewR();
CTGroup group = CTGroup.Factory.newInstance();
CTShapetype shapeType = group.addNewShapetype();
CTTextPath shapeTypeTextPath = shapeType.addNewTextpath();
shapeTypeTextPath.setOn(STTrueFalse.T);
shapeTypeTextPath.setFitshape(STTrueFalse.T);
CTLock lock = shapeType.addNewLock();
lock.setExt(STExt.EDIT);
CTShape shape = group.addNewShape();
shape.setId("PowerPlusWaterMarkObject" + (i+1));
shape.setSpid("_x0000_s206" + +(i+1));
shape.setSpt(136f);
shape.setType("#_x0000_t136");
// 设置形状样式(旋转,位置,相对路径等参数)
shape.setStyle(getShapeStyle(fingerText, i, marginTop));
shape.setFillcolor(FONT_COLOR);
shape.setFilled(STTrueFalse.T);
shape.setCoordsize("21600,21600");
shape.setAdj("10800");
// 字体设置为实心
shape.setStroked(STTrueFalse.FALSE);
// 绘制文本的路径
// 设置文本字体与大小
CTTextPath shapeTextPath = shape.addNewTextpath();
shapeTextPath.setStyle("font-family:" + FONT_NAME + ";font-size:" + FONT_SIZE);
shapeTextPath.setString(fingerText);
CTPicture pict = ctr.addNewPict();
pict.set(group);
}
private static String getShapeStyle(String fingerText, int i, int marginTop) {
StringBuilder sb = new StringBuilder();
// 文本path绘制的定位方式
sb.append("position: ").append("absolute");
// 计算文本占用的长度(文本总个数*单字长度)
sb.append(";width: ").append(fingerText.length() * WIDTH_PER_WORD).append("pt");
// 字体高度
sb.append(";height: ").append("20pt");
sb.append(";z-index: ").append(-251645952 + i);
sb.append(";mso-wrap-edited: ").append("f");
// 设置水印的间隔,这是一个大坑,不能用top,必须要margin-top。
sb.append(";margin-top: ").append(marginTop);
sb.append(";mso-position-horizontal-relative: ").append("page");
sb.append(";mso-position-vertical-relative: ").append("page");
sb.append(";mso-position-vertical: ").append("left");
sb.append(";mso-position-horizontal: ").append("center");
sb.append(";rotation: ").append(STYLE_ROTATION);
return sb.toString();
}
private static String repeatString(String pattern, int repeats) {
StringBuilder buffer = new StringBuilder(pattern.length() * repeats);
Stream.generate(() -> pattern).limit(repeats).forEach(buffer::append);
return new String(buffer);
}
public static void main(String[] arg0){
String inputFilePath = "D:\\doctest\\自定义查询操作手册V1.4.docx";
String outputFilePath = "D:\\doctest\\output.docx";
String fingerText = "创智和宇授权-严禁复制";
WaterMarkUtil.waterMarkDocXDocument(inputFilePath, outputFilePath, fingerText);
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
效果: 支持一行多个,一页多行水印 支持libreoffice将Word转PDF后水印仍然有效 开发环境: Idea 2024.4 openjdk-22.0.2 Maven 3.6.1 Poi-tl 1.12.2 Poi .5.2.2 代码包: 用Idea打开工程可直接运行查看效果 原理: 依赖Poi-tl对Word的解析功能,通过对各段落添加新段落实现
资源推荐
资源详情
资源评论
收起资源包目录
WaterMark.rar (17个子文件)
WaterMark
HELP.md 829B
mvnw.cmd 7KB
pom.xml 2KB
src
test
java
com
hsl
watermark
WaterMarkApplicationTests.java 221B
test
TestWaterMarkForWord.java 581B
main
resources
application.yml 43B
java
com
hsl
watermark
WaterMarkApplication.java 328B
util
WaterMarkUtil.java 7KB
.mvn
wrapper
maven-wrapper.properties 952B
.idea
jarRepositories.xml 864B
workspace.xml 5KB
misc.xml 547B
compiler.xml 779B
.gitignore 190B
encodings.xml 191B
mvnw 10KB
.gitignore 395B
共 17 条
- 1
资源评论
slhe08
- 粉丝: 18
- 资源: 11
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于Java语言的Zzyl-Together合作智慧养老项目设计源码
- 基于Thinkphp5框架的Java插件设计源码
- 基于Python、JavaScript和Vue的“大道无形,生育天地”主题网站设计源码
- 基于Netty4与Spring、MyBatis等流行框架的轻量级RESTful HTTP服务器设计源码
- 基于Jupyter Notebook的Python与Shell脚本分享设计源码
- 基于Java的Android平台Ecg绘图设计源码
- 基于中国大学MOOC《机器人操作系统入门》的ROS-Academy-for-Beginners设计源码
- open3d-0.15.2-cp38-cp38-win-amd64.whl
- Open3D-v0.17.0-cuda11.1-msvc2019-win64.zip
- IMG_20241105_235746.jpg
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功