使用Apache POI在word文档中添加水印

时间:2018-01-14 09:36:41

标签: java ms-word apache-poi

我想使用Apache POI在word文档中添加文字水印。

我使用了headerFooterPolicy.createWatermark("Watermark");但是没有显示对角灰色文字。

3 个答案:

答案 0 :(得分:2)

private XWPFParagraph getWatermarkParagraph(String text, int idx)直到现在才完成。您可以等到它准备好或在创建默认值后使用低级对象操作它。

所需的设置位于CTShape

示例:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;

public class CreateWordHeaderFooterWatermark {

 public static void main(String[] args) throws Exception {

  XWPFDocument doc= new XWPFDocument();

  // the body content
  XWPFParagraph paragraph = doc.createParagraph();
  XWPFRun run=paragraph.createRun();  
  run.setText("The Body:");

  // create header-footer
  XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
  if (headerFooterPolicy == null) headerFooterPolicy = doc.createHeaderFooterPolicy();

  // create default Watermark - fill color black and not rotated
  headerFooterPolicy.createWatermark("Watermark");

  // get the default header
  // Note: createWatermark also sets FIRST and EVEN headers 
  // but this code does not updating those other headers
  XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
  paragraph = header.getParagraphArray(0);

  // get com.microsoft.schemas.vml.CTShape where fill color and rotation is set
  org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
    new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape"));

  if (xmlobjects.length > 0) {
   com.microsoft.schemas.vml.CTShape ctshape = (com.microsoft.schemas.vml.CTShape)xmlobjects[0];
   // set fill color
   ctshape.setFillcolor("#d8d8d8");
   // set rotation
   ctshape.setStyle(ctshape.getStyle() + ";rotation:315");
   //System.out.println(ctshape);
  }

  doc.write(new FileOutputStream("CreateWordHeaderFooterWatermark.docx"));
  doc.close();

 }
}

答案 1 :(得分:0)

import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.office.office.STConnectType;
import com.microsoft.schemas.vml.CTFormulas;
import com.microsoft.schemas.vml.CTGroup;
import com.microsoft.schemas.vml.CTH;
import com.microsoft.schemas.vml.CTHandles;
import com.microsoft.schemas.vml.CTPath;
import com.microsoft.schemas.vml.CTShape;
import com.microsoft.schemas.vml.CTShapetype;
import com.microsoft.schemas.vml.CTTextPath;
import com.microsoft.schemas.vml.STExt;
import com.microsoft.schemas.vml.STTrueFalse;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
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 org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;

public class MYXWPFHeaderFooterPolicy extends XWPFHeaderFooterPolicy {

    XWPFDocument doc;

    public MYXWPFHeaderFooterPolicy(XWPFDocument doc, CTSectPr sectPr) {
        super(doc, sectPr);
        this.doc = doc;
    }

    @Override
    public void createWatermark(String text) {
        XWPFParagraph[] pars = new XWPFParagraph[1];
        pars[0] = getWatermarkParagraph(text, 1);
        createHeader(DEFAULT, pars);
        pars[0] = getWatermarkParagraph(text, 2);
        createHeader(FIRST, pars);
        pars[0] = getWatermarkParagraph(text, 3);
        createHeader(EVEN, pars);
    }

    /*
     * This is the default Watermark paragraph; the only variable is the text message
     * TODO: manage all the other variables
     */
    private XWPFParagraph getWatermarkParagraph(String text, int idx) {
        CTP p = CTP.Factory.newInstance();
        byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
        byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
        p.setRsidP(rsidr);
        p.setRsidRDefault(rsidrdefault);
        CTPPr pPr = p.addNewPPr();
        pPr.addNewPStyle().setVal("Header");
        // start watermark paragraph
        CTR r = p.addNewR();
        CTRPr rPr = r.addNewRPr();
        rPr.addNewNoProof();
        CTPicture pict = r.addNewPict();
        CTGroup group = CTGroup.Factory.newInstance();
        CTShapetype shapetype = group.addNewShapetype();
        shapetype.setId("_x0000_t136");
        shapetype.setCoordsize("1600,21600");
        shapetype.setSpt(136);
        shapetype.setAdj("10800");
        shapetype.setPath2("m@7,0l@8,0m@5,21600l@6,21600e");
        CTFormulas formulas = shapetype.addNewFormulas();
        formulas.addNewF().setEqn("sum #0 0 10800");
        formulas.addNewF().setEqn("prod #0 2 1");
        formulas.addNewF().setEqn("sum 21600 0 @1");
        formulas.addNewF().setEqn("sum 0 0 @2");
        formulas.addNewF().setEqn("sum 21600 0 @3");
        formulas.addNewF().setEqn("if @0 @3 0");
        formulas.addNewF().setEqn("if @0 21600 @1");
        formulas.addNewF().setEqn("if @0 0 @2");
        formulas.addNewF().setEqn("if @0 @4 21600");
        formulas.addNewF().setEqn("mid @5 @6");
        formulas.addNewF().setEqn("mid @8 @5");
        formulas.addNewF().setEqn("mid @7 @8");
        formulas.addNewF().setEqn("mid @6 @7");
        formulas.addNewF().setEqn("sum @6 0 @5");
        CTPath path = shapetype.addNewPath();
        path.setTextpathok(STTrueFalse.T);
        path.setConnecttype(STConnectType.CUSTOM);
        path.setConnectlocs("@9,0;@10,10800;@11,21600;@12,10800");
        path.setConnectangles("270,180,90,0");
        CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();
        shapeTypeTextPath.setOn(STTrueFalse.T);
        shapeTypeTextPath.setFitshape(STTrueFalse.T);
        CTHandles handles = shapetype.addNewHandles();
        CTH h = handles.addNewH();
        h.setPosition("#0,bottomRight");
        h.setXrange("6629,14971");
        CTLock lock = shapetype.addNewLock();
        lock.setExt(STExt.EDIT);
        CTShape shape = group.addNewShape();
        shape.setId("PowerPlusWaterMarkObject" + idx);
        shape.setSpid("_x0000_s102" + (4 + idx));
        shape.setType("#_x0000_t136");
        shape.setStyle("opacity: 0.5;position:absolute;margin-left:0;margin-top:0;width:415pt;height:207.5pt;rotation:315;z-index:-251654144;mso-wrap-edited:f;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin;rotation:315");
        shape.setWrapcoords("616 5068 390 16297 39 16921 -39 17155 7265 17545 7186 17467 -39 17467 18904 17467 10507 17467 8710 17545 18904 17077 18787 16843 18358 16297 18279 12554 19178 12476 20701 11774 20779 11228 21131 10059 21248 8811 21248 7563 20975 6316 20935 5380 19490 5146 14022 5068 2616 5068");
        shape.setFillcolor("#F8F8F8");
        shape.setStroked(STTrueFalse.FALSE);
        CTTextPath shapeTextPath = shape.addNewTextpath();
        shapeTextPath.setStyle("font-family:"Cambria";font-size:1pt");
        shapeTextPath.setString(text);
        pict.set(group);
        // end watermark paragraph
        return new XWPFParagraph(p, doc);
    }

}

答案 2 :(得分:0)

我使用了上面的示例:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;

public class CreateWordHeaderFooterWatermark {

 public static void main(String[] args) throws Exception {

  XWPFDocument doc= new XWPFDocument();

  // the body content
  XWPFParagraph paragraph = doc.createParagraph();
  XWPFRun run=paragraph.createRun();  
  run.setText("The Body:");

  // create header-footer
  XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
  if (headerFooterPolicy == null) headerFooterPolicy = doc.createHeaderFooterPolicy();

  // create default Watermark - fill color black and not rotated
  headerFooterPolicy.createWatermark("Watermark");

  // get the default header
  // Note: createWatermark also sets FIRST and EVEN headers 
  // but this code does not updating those other headers
  XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
  paragraph = header.getParagraphArray(0);

  // get com.microsoft.schemas.vml.CTShape where fill color and rotation is set
  org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
    new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape"));

  if (xmlobjects.length > 0) {
   com.microsoft.schemas.vml.CTShape ctshape = (com.microsoft.schemas.vml.CTShape)xmlobjects[0];
   // set fill color
   ctshape.setFillcolor("#d8d8d8");
   // set rotation
   ctshape.setStyle(ctshape.getStyle() + ";rotation:315");
   //System.out.println(ctshape);
  }

  doc.write(new FileOutputStream("CreateWordHeaderFooterWatermark.docx"));
  doc.close();

 }
}

但是,如果您的Apache-POI版本使用以下功能:

XWPFHeader getHeader(int pageNumber)

您不能在其中使用枚举XWPFHeaderFooterPolicy.DEFAULT

XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);

所以您需要将此功能替换为

XWPFHeader header = headerFooterPolicy.getDefaultHeader();