【Java】通过poi给word首页添加水印图片

背景:

poi并没有提供直接插入水印图片的方法,目前需要再word的首页插入一张水印图片,于是就需要通过另一种方式,插入透明图片(png格式)并将图片设置为“浮于文字上方”的方式实现该需求。

所需jar:

poi-3.8.jar
poi-ooxml-3.8.jar
poi-ooxml-schemas-3.8.jar
xmlbeans-2.6.0.jar
dom4j-1.6.1.jar

示例代码:

创建CustomXWPFDocument类

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;import java.io.IOException;
import java.io.InputStream;/*** 文档对象*/
public class CustomXWPFDocument extends XWPFDocument {public CustomXWPFDocument() {super();}public CustomXWPFDocument(InputStream in) throws IOException {super(in);}public CustomXWPFDocument(OPCPackage pkg) throws IOException {super(pkg);}/*** 创建一个包含图片的XWPFParagraph,将图片插入到指定或新建的段落中。** @param blipId 图片在文档关系中的唯一标识(r:embed属性值),用于链接到图片数据。* @param id     图片在文档中的唯一标识(cNvPr元素的id属性值)。* @param width  图片的宽度,单位为像素。内部转换为EMU(English Metric Unit)单位。* @param height 图片的高度,单位为像素。内部转换为EMU单位。* @param paragraph 可选参数,要插入图片的XWPFParagraph。如果为null,则会创建一个新的段落。*/public void createPicture(String blipId, int id, int width, int height,XWPFParagraph paragraph) {// 定义EMU(English Metric Unit)常量,1EMU等于1/914400米,是OpenXML中使用的长度单位。final int EMU = 9525;// 将像素宽度和高度转换为EMU单位。width *= EMU;height *= EMU;// 如果传入的段落为空,则创建一个新的段落。if (paragraph == null) {paragraph = createParagraph();}// 在段落中创建一个新的运行(Run),并在运行的底层XML结构(CTR)中添加一个新的内联图形(Inline)元素。CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();// 构建包含图片详细信息的XML字符串,遵循OpenXML DrawingML规范。StringBuffer picXml = new StringBuffer();// 开始图形元素picXml.append("<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">")// 描述图形类型为图片.append( "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">")// 开始图片元素.append( "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">")// 包含非视觉属性的图片属性(名称、ID等).append( "         <pic:nvPicPr>" )// 非视觉属性主元素(通用非视觉属性)设置图片ID.append( "            <pic:cNvPr id=\"").append(id).append( "\" name=\"img_").append(id).append( "\"/>").append( "            <pic:cNvPicPr/>").append( "         </pic:nvPicPr>")// 填充图片的属性(图片源、缩放方式等).append( "         <pic:blipFill>")// 插入图片的Blip(位图)元素,引用图片数据.append( "            <a:blip r:embed=\"").append(blipId)// 引用关系命名空间.append( "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>")// 设置图片填充方式为拉伸.append( "            <a:stretch>").append( "               <a:fillRect/>").append( "            </a:stretch>").append( "         </pic:blipFill>")// 图片的形状属性(位置、尺寸、旋转等).append( "         <pic:spPr>")// 图片的变换属性(平移、缩放).append( "            <a:xfrm>")// 图片相对于容器的偏移(此处为原点).append( "               <a:off x=\"0\" y=\"0\"/>")// 图片的扩展尺寸(宽度).append( "               <a:ext cx=\"").append(width)// 图片的扩展尺寸(高度).append( "\" cy=\"").append(height).append( "\"/>").append( "            </a:xfrm>")// 使用预定义形状(矩形).append( "            <a:prstGeom prst=\"rect\">")// 空的可变几何形状属性列表(保留结构完整性).append( "               <a:avLst/>").append( "            </a:prstGeom>").append( "         </pic:spPr>").append( "      </pic:pic>").append( "   </a:graphicData>").append( "</a:graphic>");// 将构造的XML字符串解析为XmlToken对象XmlToken xmlToken = null;try {xmlToken = XmlToken.Factory.parse(picXml.toString());} catch (XmlException xe) {xe.printStackTrace();}// 将XmlToken对象设置到之前创建的CTInline元素中。inline.set(xmlToken);// 设置内联图形与周围文本的间距(顶部、底部、左侧、右侧均为0EMU)inline.setDistT(0);inline.setDistB(0);inline.setDistL(0);inline.setDistR(0);// 设置内联图形的实际尺寸(与构造的XML中一致,可能不是必需的,因为已经包含在XML中)CTPositiveSize2D extent = inline.addNewExtent();extent.setCx(width);extent.setCy(height);// 设置非视觉文档属性(名称、ID、描述等)CTNonVisualDrawingProps docPr = inline.addNewDocPr();docPr.setId(id);docPr.setName("docx_img_ " + id);docPr.setDescr("docx Picture");}/*** 创建一个带有图形对象(如图片)的CTAnchor(锚点),用于将图形放置于Word文档中特定位置,并可设定其浮于文字上方或下方。** @param ctGraphicalObject 要插入的图形对象,例如CTPicture(图片)对象。* @param deskFileName 图片的描述性文件名,用于设置锚点的描述属性。* @param width 图形对象的宽度,单位为EMU(English Metric Unit)。* @param height 图形对象的高度,单位为EMU。* @param leftOffset 图形相对于所在列左侧的偏移距离,单位为EMU。* @param topOffset 图形相对于所在段落顶部的偏移距离,单位为EMU。* @param behind 指定图形是否应位于文字下方。如果为true,则图形位于文字下方;否则位于文字上方。* @return 生成的CTAnchor对象,包含了指定图形对象及定位信息。*/public static CTAnchor getAnchorWithGraphic(CTGraphicalObject ctGraphicalObject,String deskFileName, int width, int height,int leftOffset, int topOffset, boolean behind) {// 构建锚点的XML字符串,遵循WordProcessingML DrawingML规范。String anchorXML =// 开始wp:anchor元素,定义命名空间"<wp:anchor  xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "// 设置锚点属性(简单定位、相对高度、文字前后关系、锁定状态、布局方式、重叠允许)+ "simplePos=\"0\" relativeHeight=\"0\" behindDoc=\"" + ((behind) ? 1 : 0) + "\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"// 设置简单定位信息(此处为原点)+ "<wp:simplePos x=\"0\" y=\"0\"/>"// 设置水平位置,相对于列+ "<wp:positionH relativeFrom=\"column\">"// 设置水平偏移距离+ "<wp:posOffset>" + leftOffset + "</wp:posOffset>"+ "</wp:positionH>"// 设置垂直位置,相对于段落+ "<wp:positionV relativeFrom=\"paragraph\">"+ "<wp:posOffset>" + topOffset + "</wp:posOffset>" +"</wp:positionV>"// 设置图形对象的尺寸+ "<wp:extent cx=\"" + width + "\" cy=\"" + height + "\"/>"// 设置图形边缘效果扩展距离(此处为默认值)+ "<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"3175\"/>"// 设置无环绕模式,即图形不随文字换行而移动+ "<wp:wrapNone/>"// 设置文档属性(ID、名称、描述)+ "<wp:docPr id=\"0\" name=\"Drawing 0\" descr=\"" + deskFileName + "\"/><wp:cNvGraphicFramePr/>"+ "</wp:anchor>";// 将构造的XML字符串解析为CTDrawing对象。CTDrawing drawing = null;try {drawing = CTDrawing.Factory.parse(anchorXML);} catch (XmlException e) {e.printStackTrace();}// 从解析得到的CTDrawing对象中获取第一个(也是唯一一个)CTAnchor对象。CTAnchor anchor = drawing.getAnchorArray(0);// 将提供的图形对象(如CTPicture)设置到锚点中。anchor.setGraphic(ctGraphicalObject);return anchor;}
}

创建poitest类进行验证:

import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;public class poitest {public static void main(String[] args) throws IOException, InvalidFormatException {insertWatermark("D:\\document_ls\\bb.docx","1231321","D:\\document_ls\\");}/*** 向指定Word文档中插入水印图片,并将其设置为浮于文字之上。** @param wdlj 输入Word文档路径,待插入水印的源文件路径。* @param bgxh 水印图片背景编号或其他标识,用于生成临时输出文件的名称。* @param parentPath 输出文件所在的父目录路径,用于保存临时文件和最终修改后的Word文档。* @throws IOException 在文件读写过程中发生I/O错误时抛出。* @throws InvalidFormatException 当处理的文件格式不符合预期或无法解析时抛出。*/private static void insertWatermark(String wdlj, String bgxh, String parentPath) throws IOException, InvalidFormatException {FileOutputStream fos = null ;// 定义水印图片文件路径String pic = "D:\\document_ls\\reportPic.png";// 生成临时输出文件路径String outputPath = parentPath + bgxh + "_temp.docx";// 打开并解析输入Word文档,获得OPCPackage对象和CustomXWPFDocument对象OPCPackage pk = POIXMLDocument.openPackage(wdlj);CustomXWPFDocument doc = new CustomXWPFDocument(pk);// 获取文档的第一个段落XWPFParagraph para = doc.getParagraphs().get(0);// 将水印图片添加到文档的图片数据集中,并获取其在文档中的Blip IDString blipId = para.getDocument().addPictureData(new FileInputStream(new File(pic)), XWPFDocument.PICTURE_TYPE_PNG);// 在指定段落中创建图片,设置尺寸为350px x 350px,并关联到当前段落doc.createPicture(blipId, XWPFDocument.PICTURE_TYPE_PNG, 350, 350, para);// 从段落的第一个运行中获取对应的CTR对象,并从中找到包含图形对象的CTDrawing对象CTDrawing drawing = para.getRuns().get(0).getCTR().getDrawingArray(0);// 从CTDrawing对象中提取出CTGraphicalObject对象,即插入的图片CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();// 使用getAnchorWithGraphic方法将图形对象转换为浮于文字之上的CTAnchor对象,设置相关属性CTAnchor anchor = doc.getAnchorWithGraphic(graphicalobject, "Generated",Units.toEMU(350), Units.toEMU(350),Units.toEMU(70), Units.toEMU(200), false);// 替换CTDrawing中的内联图形对象为新创建的浮点锚点对象drawing.setAnchorArray(new CTAnchor[]{anchor});// 删除原有的内联图形对象,确保仅保留浮点锚点drawing.removeInline(0);// 创建文件输出流,将修改后的文档写入临时输出文件fos = new FileOutputStream(new File(outputPath));doc.write(fos);// 关闭OPCPackage以释放资源pk.close();// 移动临时文件至源文件路径,替换原有文档Files.move(Paths.get(outputPath), Paths.get(wdlj), StandardCopyOption.REPLACE_EXISTING);}
}

效果展示:

插入前:

插入后:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/821678.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用python采集VIP会电商平台商品数据②单页数据采集

获取标头&#xff1a; 响应&#xff1a;服务器返回的数据 预览&#xff1a;查看响应得数据 载荷&#xff1a;查询参数/请求参数 标头&#xff1a;查看请求的网址/请求的标头/请求方法 数据包地址&#xff1a;https://mapi.vip.com/vips-mobile/rest/shopping/pc/product/mo…

Servlet-Filter实现反爬虫

以前用DotNetCore实现过反爬虫功能。在tomcat里面可以利用Servlet的Filter类实现请求的控制来达到反爬虫功能&#xff0c;进而增强JRT的web安全。 实现黑名单过滤器&#xff0c;对在黑名单列表的IP的所有请求都跳转到警告页面&#xff0c;业务各种请求自行定义加入黑名单 /* …

Yolo-world+Python-OpenCV之摄像头视频实时目标检测

上一次介绍了如何使用最基本的 Yolo-word来做检测&#xff0c;现在我们在加opencv来做个实时检测的例子 基本思路 1、读取离线视频流 2、将视频帧给yolo识别 3、根据识别结果 对视频进行绘制边框、加文字之类的 完整代码如下&#xff1a; import datetimefrom ultralytics …

电竞陪玩系统开发平台搭建(小程序,公众号,app)线上线下皆有,线下计算距离。

六大核心功能 1.游戏陪练:可以选择当下火爆的游戏内容&#xff0c;选择游戏大神、职业玩家进行陪练&#xff0c;也可约附近路人玩家或是身边的小伙伴语音组队开黑&#xff0c;一起享受边玩游戏边吐槽的无限乐趣。 2.约玩交友:除了游戏陪玩功能&#xff0c;系统还设置了单独的语…

SpringBlade dict-biz/list SQL 注入漏洞复现

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

Python LEGB规则

Python在查找“名称”时&#xff0c;是按照LEGB规则查找的&#xff1a; Local&#xff1a; 指的就是函数或者类的方法内部 Enclosed&#xff1a; 指的是嵌套函数&#xff08;一个函数包裹另一个函数&#xff0c;闭包&#xff09; Global&#xff1a; 指的是模块中的全局变量 Bu…

含多种需求响应及电动汽车的微网/虚拟电厂日前优化调度

1 主要内容 程序主要建立一个微网/虚拟电厂的日前优化调度模型&#xff0c;以燃气轮机运行成本、购售电费用、电动汽车电池损耗成本以及需求响应费用之和为目标&#xff0c;在日前经济调度模型中&#xff0c;加入了电动汽车模型&#xff0c;考虑了电动汽车出行规律以及充放电规…

python之flask安装以及使用

1 flask介绍 Flask是一个非常小的Python Web框架&#xff0c;被称为微型框架&#xff1b;只提供了一个稳健的核心&#xff0c;其他功能全部是通过扩展实现的&#xff1b;意思就是我们可以根据项目的需要量身定制&#xff0c;也意味着我们需要学习各种扩展库的使用。 2 python…

超越GPT-4V,苹果多模态大模型上新,神经网络形态加速MLLM(一)

4月8日&#xff0c;苹果发布了其最新的多模态大语言模型&#xff08;MLLM &#xff09;——Ferret-UI&#xff0c;能够更有效地理解和与屏幕信息进行交互&#xff0c;在所有基本UI任务上都超过了GPT-4V&#xff01; 苹果开发的多模态模型Ferret-UI增强了对屏幕的理解和交互&am…

【触想智能】如何选购到一款合适的工业电脑一体机

工业电脑一体机是专为工业环境而设计的一种工业计算机。工业电脑一体机和普通的计算机不一样&#xff0c;它对产品的参数性能要求很高&#xff0c;因为它们通常会运行在高低温、电磁干扰、高粉尘、湿度大的恶劣环境中&#xff0c;所以相应的要求工业电脑一体机必须具备良好的宽…

UE5下载与安装

官方网站&#xff1a;https://www.unrealengine.com/zh-CN 1、下载启动程序安装包。 登录官网后&#xff0c;点击首页右侧下载按钮下载Epic Games启动程序的安装包&#xff0c;如下图&#xff1a; 2、安装启动程序。 双击步骤1所下载安装软件&#xff0c;如下图&#xff1a;…

vivado AXI 接口事件

AXI 接口事件 在 Vivado 硬件管理器中 &#xff0c; 如果使用 System ILA IP 对设计 AXI 接口进行调试 &#xff0c; 那么“波形 (Waveform) ”窗口会显示对 应于 System ILA 所探测的接口的接口插槽、事件和信号组。正如下图所示 &#xff0c; “ Waveform ”窗口会显示…

中立分析腾讯云故障相关的事件

最近腾讯云的故障&#xff0c;让一堆云计算爱好者兴奋地远看指点江山、近看沐猴而冠。我比这群爱好者们更了解云计算&#xff0c;但是我尊重我的读者&#xff0c;你们从我这里看到的科普信息&#xff0c;不仅仅只有情绪价值。 在信息爆炸的时代&#xff0c;大家关注和信任某个媒…

三道模拟题

P1003 [NOIP2011 提高组] 铺地毯 题目描述 原题点这里-->P1003 [NOIP2011 提高组] 铺地毯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 为了准备一个独特的颁奖典礼&#xff0c;组织者在会场的一片矩形区域&#xff08;可看做是平面直角坐标系的第一象限&#xff09;铺…

【C++】哈希一

这篇博客要说的是哈希算法&#xff0c;哈希又称为散列&#xff0c;它是将存储的值和存储的位置建立起关联关系的一种算法&#xff0c;或者说是一种将任意长度的数据映射为固定长度的输出的算法。 什么意思呢&#xff1f;我们来看一个例子&#xff1a;比如说我们要存储1&#xf…

【SLAM】在Win10上实现Nerf-Pytorch【GPU版】

文章目录 ReadMe安装依赖运行下载两个示例数据集:lego和fern训练一个低分辨率的Lego NeRF:训练一个低分辨率蕨类植物NeRF:更多数据集预训练模型可复现实现1、下载nerf-pytorch工程2、安装依赖3、下载数据4、运行lego NeRF:ReadMe Github链接 NeRF (神经辐射场)是一种在合成…

基于变压器的手持式超声图像中乳腺病变的分类不一致性测量表征

超声成像作为一种替代的低成本、易于获取的非电离成像方式已显示出巨大的前景&#xff0c;可用于乳腺癌筛查。特别是&#xff0c;随着最近便携式设备的出现&#xff0c;超声检查预计将在中低收入国家中越来越普及。然而&#xff0c;超声成像在乳腺癌诊断中的可靠性高度依赖于操…

竞赛 基于GRU的 电影评论情感分析 - python 深度学习 情感分类

文章目录 1 前言1.1 项目介绍 2 情感分类介绍3 数据集4 实现4.1 数据预处理4.2 构建网络4.3 训练模型4.4 模型评估4.5 模型预测 5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于GRU的 电影评论情感分析 该项目较为新颖&#xff0c;适合作为竞…

【数据结构|C语言版】双向链表

前言1. 初步认识双向链表1.1 定义1.2 结构1.3 储存 2. 双向链表的方法&#xff08;接口函数&#xff09;2.1 动态申请空间2.2 创建哨兵位2.3 查找指定数据2.4 指定位置插入2.5 指定位置删除2.6 头部插入2.7 头部删除2.8 尾部插入2.9 尾部删除2.10 计算链表大小2.11 销毁链表 3.…

记录一下hive跑spark的insert,update语句报类找不到的问题

我hive能正常启动&#xff0c;建表没问题&#xff0c;我建了一个student表&#xff0c;没问题&#xff0c;但执行了下面一条insert语句后报如下错误&#xff1a; hive (default)> insert into table student values(1,abc); Query ID atguigu_20240417184003_f9d459d7-199…