POI给WORD添加水印(亲测可用)

2 篇文章 0 订阅

POI给WORD添加水印(亲测可用)

最近要做电子合同,客户提出为了安全性要将合同中都添加水印,这个之前在网上看到过,貌似使用POI很好加。去网上一搜发现,清一色的只有一篇文章,并且这段代码是用不了的;在文章下边的评论里也发现都说用不了,不能用。唉,木办法了,只能自己探索。

一、依赖

依赖当然是还就那些,demo里我用了Lombok打印日志了,依赖里我没写出来。

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>4.1.0</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>4.1.0</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml-schemas</artifactId>
	<version>4.1.0</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>ooxml-schemas</artifactId>
	<version>1.1</version>
</dependency>

二、Demo

废话不多说,上demo;将下边代码直接复制到自己创建的类中,改一下文件地址就可以直接测试。注意使用了lombok的@Slf4j注解,不想用可以删掉。

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlToken;

import javax.xml.namespace.QName;
import java.io.*;
import java.util.List;

@Slf4j
public class XWPFDocTest {
    private static String filePath = "C:\\tmp\\个人合同.docx";

    private static String waterMark = "<w:r><w:rPr><w:noProof/></w:rPr><w:pict w14:anchorId=\"58771E30\"><v:shapetype id=\"_x0000_t136\" coordsize=\"21600,21600\" o:spt=\"136\" adj=\"10800\" path=\"m@7,l@8,m@5,21600l@6,21600e\"><v:formulas><v:f eqn=\"sum #0 0 10800\"/><v:f eqn=\"prod #0 2 1\"/><v:f eqn=\"sum 21600 0 @1\"/><v:f eqn=\"sum 0 0 @2\"/><v:f eqn=\"sum 21600 0 @3\"/><v:f eqn=\"if @0 @3 0\"/><v:f eqn=\"if @0 21600 @1\"/><v:f eqn=\"if @0 0 @2\"/><v:f eqn=\"if @0 @4 21600\"/><v:f eqn=\"mid @5 @6\"/><v:f eqn=\"mid @8 @5\"/><v:f eqn=\"mid @7 @8\"/><v:f eqn=\"mid @6 @7\"/><v:f eqn=\"sum @6 0 @5\"/></v:formulas><v:path textpathok=\"t\" o:connecttype=\"custom\" o:connectlocs=\"@9,0;@10,10800;@11,21600;@12,10800\" o:connectangles=\"270,180,90,0\"/><v:textpath on=\"t\" fitshape=\"t\"/><v:handles><v:h position=\"#0,bottomRight\" xrange=\"6629,14971\"/></v:handles><o:lock v:ext=\"edit\" text=\"t\" shapetype=\"t\"/></v:shapetype><v:shape id=\"PowerPlusWaterMarkObject1584793859\" o:spid=\"_x0000_s2049\" type=\"#_x0000_t136\" style=\"position:absolute;left:0;text-align:left;margin-left:0;margin-top:0;width:470.5pt;height:115pt;rotation:315;z-index:-251657216;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin\" o:allowincell=\"f\" fillcolor=\"silver\" stroked=\"f\"><v:fill opacity=\".5\"/><v:textpath style=\"font-family:&quot;宋体&quot;;font-size:1pt\" string=\"水印\"/></v:shape></w:pict></w:r></xml-fragment>";

    public static void main(String[] args) throws Exception{
        String waterMarkValue = "传入水印";
        addWaterMark(filePath,waterMarkValue);
    }

    /**
     * 添加水印
     * 根据传入的word文档地址给word添加水印,添加完成后在相同路径下生成后缀为_after.docx的文件
     * 保留了源文件。如源文件为C:\tmp\个人合同.docx;添加水印后有水印的文件为C:\tmp\个人合同_after.docx;
     * @param filePath 要添加的水印word
     * @param waterMarkValue 水印字符串
     * @throws IOException
     * @throws XmlException
     */
    public static void addWaterMark(String filePath,String waterMarkValue) throws IOException,XmlException {
        InputStream in = new FileInputStream(new File(filePath));
        XWPFDocument document = new XWPFDocument(in);
        XWPFHeaderFooterPolicy xFooter = new XWPFHeaderFooterPolicy(document);
        XWPFHeader header = xFooter.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
        List<XWPFParagraph> paragraphs = header.getParagraphs();
        for(XWPFParagraph graph: paragraphs){
            String paraText = graph.getCTP().xmlText();
            //如果已经有水印了,那么就进行替换
            if(paraText.contains("id=\"PowerPlusWaterMarkObject")){
                replaceWaterMark(graph,waterMarkValue);
            }else {//如果没有水印就添加
                String newParaText = waterMark.replace("水印",waterMarkValue);
                String newText = paraText.replace("</xml-fragment>", newParaText);
                XmlToken token = XmlToken.Factory.parse(newText);
                graph.getCTP().set(token);
            }
        }
        String afterPath = filePath.substring(0, filePath.lastIndexOf(".")) + "_after.docx";
        OutputStream out = new FileOutputStream(new File(afterPath));
        document.write(out);
        out.flush();
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 将水印中的文字替换成传进来的字符串
     * @param graph 要替换的段落
     * @param waterMarkValue 水印文字
     * @throws IOException
     * @throws XmlException
     */
    public static void replaceWaterMark(XWPFParagraph graph,String waterMarkValue) throws IOException,XmlException{
        String paraText = graph.getCTP().xmlText();
        if(paraText.contains("id=\"PowerPlusWaterMarkObject")){//<v:shape id=\"PowerPlusWaterMarkObject
            String beginStr = "string=\"";
            int begin = paraText.indexOf(beginStr) + beginStr.length();
            int end = paraText.indexOf("\"", begin);
            String oldWaterMarkText = paraText.substring(begin, end);
            String newText = paraText.replace("string=\""+ oldWaterMarkText +"\"",
                    "string=\"" + waterMarkValue + "\"");
            XmlToken token = XmlToken.Factory.parse(newText);
            graph.getCTP().set(token);
        }
    }
}

三、总结

虽然实现了,但是还是比较简陋;水印的字体、大小、颜色等都木有设置,用的都是默认的;这是以后可以优化的地方。不过整体效果还是可以的,而且这样添加水印后生成pdf也是带有水印的。至于生成pdf的代码后边有时间再写吧,谁想要可以在评论区给我留言,我看到了就把demo发给你。

在这里插入图片描述

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
在使用POI操作Word文档之前,我们需要先添加POI的依赖,可以在pom.xml中添加如下代码: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> ``` 接下来,我们可以使用POI添加水印。代码示例如下: ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.xmlbeans.XmlCursor; public class AddWatermark { public static void main(String[] args) throws Exception { File file = new File("example.docx"); FileInputStream fis = new FileInputStream(file); XWPFDocument document = new XWPFDocument(fis); fis.close(); String watermark = "My Watermark"; for (XWPFParagraph p : document.getParagraphs()) { for (XWPFRun r : p.getRuns()) { XmlCursor cursor = r.getCTR().newCursor(); cursor.toParent(); cursor.insertElement("w:pPr"); cursor.toParent(); cursor.insertElement("w:r"); XWPFRun run = new XWPFRun(cursor, r.getCTR().copy()); run.setText(watermark); run.getCTR().getRPr().getRFonts().setAscii("Times New Roman"); run.getCTR().getRPr().getRFonts().setHAnsi("Times New Roman"); run.getCTR().getRPr().getRFonts().setCs("Times New Roman"); run.getCTR().getRPr().setColor(r.getColor()); run.getCTR().getRPr().setSz(r.getFontSize()); run.getCTR().getRPr().setB(r.isBold()); run.getCTR().getRPr().setI(r.isItalic()); r.setText("", 0); } } FileOutputStream fos = new FileOutputStream(file); document.write(fos); fos.close(); } } ``` 在代码中,我们首先通过FileInputStream读取Word文档,然后遍历所有的段落和文本内容,在每个文本内容上添加水印。最后,通过FileOutputStream将更新后的Word文档写回到磁盘上。 需要注意的是,POI目前还没有提供直接添加水印的API,我们需要通过在文本内容前插入一个段落来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值