docx4j 单独添加页眉页脚、水印的代码一搜一大堆,但很少有人把页眉+水印、奇偶页眉页脚、首页页眉页脚全面实现,最近在做相关的内容,经过大量的查阅资料,总算完成了,分享记录一下。

先看效果:

水印在word文档中,也属于Header的一部分,在此实现中,是用画布画出一大片水印,生成图片。

奇偶页眉页脚设置:

在word文档中 setting.xml 中需要有 <w:evenAndOddHeaders>属性

首页页眉页脚设置:

在word文档中 document.xml <w:sectPr>标签中需要有<w:titlePg/>属性

代码:

package com.maqi.html2word;import org.apache.commons.lang3.StringUtils;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.model.structure.DocumentModel;
import org.docx4j.model.structure.PageSizePaper;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.*;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.Color;
import org.docx4j.wml.*;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;/*** @author maqi* @date 2020/11/16 11:49*/
public class Docx4jTest {private static final ObjectFactory factory = Context.getWmlObjectFactory();private WordprocessingMLPackage wordMLPackage;private MainDocumentPart mainDocumentPart;private DocumentModel documentModel;public static void main(String[] args) throws Exception {Docx4jTest docx4jTest = new Docx4jTest();WordprocessingMLPackage wordprocessingMLPackage = WordprocessingMLPackage.createPackage(PageSizePaper.valueOf("A4"), false); // A4纸,//横版:truedocx4jTest.wordMLPackage = wordprocessingMLPackage;docx4jTest.mainDocumentPart = wordprocessingMLPackage.getMainDocumentPart();docx4jTest.documentModel = wordprocessingMLPackage.getDocumentModel();SectPr sectPr = docx4jTest.wordMLPackage.getDocumentModel().getSections().get(docx4jTest.wordMLPackage.getDocumentModel().getSections().size() - 1).getSectPr();if (sectPr == null) {sectPr = factory.createSectPr();docx4jTest.mainDocumentPart.addObject(sectPr);docx4jTest.documentModel.getSections().get(docx4jTest.documentModel.getSections().size() - 1).setSectPr(sectPr);}String watermark = "水印水印";// 修改值为 first even default 测试String hdrFtrRef = "first";// header footer 判断规则 规则为: first even defaultif (hdrFtrRef.equals("first")) {// first:设置 first、default两个headerdocx4jTest.createHeader(sectPr, "first", watermark);docx4jTest.createFooter(sectPr, "first");//首页不同时sectPr.setTitlePg(new BooleanDefaultTrue());} else if (hdrFtrRef.equals("even")) {// even: 设置even default 两个header 并在 setting.xml 设置 evenAndOddHeadersdocx4jTest.createHeader(sectPr, "even", watermark);docx4jTest.createFooter(sectPr, "even");DocumentSettingsPart documentSettingsPart = docx4jTest.mainDocumentPart.getDocumentSettingsPart();CTSettings contents = documentSettingsPart.getContents();//奇偶不同时设置contents.setEvenAndOddHeaders(new BooleanDefaultTrue());}// default,增加一个header footer 设置为rels为defaultdocx4jTest.createHeader(sectPr, "default", watermark);docx4jTest.createFooter(sectPr, "default");docx4jTest.mainDocumentPart.addObject(makePageBr());// end cover pagedocx4jTest.mainDocumentPart.addStyledParagraphOfText("Heading1", "页面内容");docx4jTest.mainDocumentPart.addObject(makePageBr());docx4jTest.mainDocumentPart.addStyledParagraphOfText("Normal", "页面内容11111");docx4jTest.mainDocumentPart.addObject(makePageBr());docx4jTest.wordMLPackage.save(new java.io.File("headerfooterwatermark_test.docx"));}private void createFooter(SectPr sectPr, String type) throws Exception {FooterPart footerPart = new FooterPart(new PartName("/word/footer-" + type + ".xml"));Ftr ftr = factory.createFtr();// Bind the header JAXB elements as representing their header partsfooterPart.setJaxbElement(ftr);Relationship relationship = mainDocumentPart.addTargetPart(footerPart);wordMLPackage.getParts().put(footerPart);FooterReference footerReference = factory.createFooterReference();footerReference.setType(HdrFtrRef.fromValue(type));footerReference.setId(relationship.getId());P paragraph = factory.createP();if ("first".equals(type)) {createHeaderFooterThreePart1(paragraph);} else {createHeaderFooterThreePart(paragraph);}ftr.getContent().add(paragraph);sectPr.getEGHdrFtrReferences().add(footerReference);}private void createHeader(SectPr sectPr, String type, String watermark) throws Exception {HeaderPart headerPart = new HeaderPart(new PartName("/word/heade-" + type + ".xml"));Relationship relationship = this.mainDocumentPart.addTargetPart(headerPart);Hdr hdr = null;if (StringUtils.isNoneBlank(watermark)) {setWatermarkHdr(headerPart, watermark);hdr = headerPart.getJaxbElement();} else {hdr = factory.createHdr();}// Bind the header JAXB elements as representing their header partsheaderPart.setJaxbElement(hdr);P paragraph = factory.createP();if ("first".equals(type)) {createHeaderFooterThreePart1(paragraph);} else {createHeaderFooterThreePart(paragraph);}hdr.getContent().add(paragraph);// headerPart.getJaxbElement().getContent().add(e)// Add the reference to both header parts to the Main Document PartHeaderReference headerReference = factory.createHeaderReference();headerReference.setType(HdrFtrRef.fromValue(type));headerReference.setId(relationship.getId());sectPr.getEGHdrFtrReferences().add(headerReference);}/*** 添加页眉页脚,左中右 三部分内容** @return 页脚对象*/private void createHeaderFooterThreePart(P paragraph) {RPr fontRPr = getRPr("宋体", "000000", "22", STHint.EAST_ASIA, true, false, false, false);R run = factory.createR();run.setRPr(fontRPr);paragraph.getContent().add(run);// tabparagraph.getContent().add(getTextField("left少时诵诗书"));R r1 = factory.createR();R.Ptab rPtab = factory.createRPtab();rPtab.setAlignment(STPTabAlignment.CENTER);rPtab.setRelativeTo(STPTabRelativeTo.MARGIN);rPtab.setLeader(STPTabLeader.NONE);r1.getContent().add(rPtab);paragraph.getContent().add(r1);// 中间内容SdtContentBlock sdtContentBlock = factory.createSdtContentBlock();sdtContentBlock.getContent().add(getTextField("第"));sdtContentBlock.getContent().add(getFieldBegin());sdtContentBlock.getContent().add(getPageNumberField());sdtContentBlock.getContent().add(getFieldEnd());sdtContentBlock.getContent().add(getTextField("页"));sdtContentBlock.getContent().add(getTextField(" 总共"));sdtContentBlock.getContent().add(getFieldBegin());sdtContentBlock.getContent().add(getTotalPageNumberField());sdtContentBlock.getContent().add(getFieldEnd());sdtContentBlock.getContent().add(getTextField("页"));paragraph.getContent().add(sdtContentBlock);// tabR r2 = factory.createR();R.Ptab rPtab1 = factory.createRPtab();rPtab1.setAlignment(STPTabAlignment.RIGHT);rPtab1.setRelativeTo(STPTabRelativeTo.MARGIN);rPtab1.setLeader(STPTabLeader.NONE);r2.getContent().add(rPtab1);// 右边内容paragraph.getContent().add(r2);paragraph.getContent().add(getTextField("right塑料袋"));}/*** 添加页眉页脚,左中右 三部分内容** @return 页脚对象*/private void createHeaderFooterThreePart1(P paragraph) {RPr fontRPr = getRPr("宋体", "000000", "22", STHint.EAST_ASIA, true, false, false, false);R run = factory.createR();run.setRPr(fontRPr);paragraph.getContent().add(run);// tabparagraph.getContent().add(getTextField("9990090"));R r1 = factory.createR();R.Ptab rPtab = factory.createRPtab();rPtab.setAlignment(STPTabAlignment.CENTER);rPtab.setRelativeTo(STPTabRelativeTo.MARGIN);rPtab.setLeader(STPTabLeader.NONE);r1.getContent().add(rPtab);paragraph.getContent().add(r1);// 中间内容SdtContentBlock sdtContentBlock = factory.createSdtContentBlock();sdtContentBlock.getContent().add(getTextField("第"));sdtContentBlock.getContent().add(getFieldBegin());sdtContentBlock.getContent().add(getPageNumberField());sdtContentBlock.getContent().add(getFieldEnd());sdtContentBlock.getContent().add(getTextField("页"));sdtContentBlock.getContent().add(getTextField(" 总共"));sdtContentBlock.getContent().add(getFieldBegin());sdtContentBlock.getContent().add(getTotalPageNumberField());sdtContentBlock.getContent().add(getFieldEnd());sdtContentBlock.getContent().add(getTextField("页"));paragraph.getContent().add(sdtContentBlock);// tabR r2 = factory.createR();R.Ptab rPtab1 = factory.createRPtab();rPtab1.setAlignment(STPTabAlignment.RIGHT);rPtab1.setRelativeTo(STPTabRelativeTo.MARGIN);rPtab1.setLeader(STPTabLeader.NONE);r2.getContent().add(rPtab1);// 右边内容paragraph.getContent().add(r2);paragraph.getContent().add(getTextField("uuuuuuuu"));}private R getTextField(String content) {Text text = factory.createText();R run = factory.createR();text.setValue(content);run.getContent().add(text);return run;}private static R getPageNumberField() {R run = factory.createR();Text txt = new Text();txt.setSpace("preserve");txt.setValue("PAGE \\* MERGEFORMAT");run.getContent().add(factory.createRInstrText(txt));return run;}private static R getTotalPageNumberField() {R run = factory.createR();Text txt = new Text();txt.setSpace("preserve");txt.setValue(" NUMPAGES \\* MERGEFORMAT ");run.getContent().add(factory.createRInstrText(txt));return run;}private static R getFieldBegin() {R run = factory.createR();FldChar fldchar = factory.createFldChar();fldchar.setFldCharType(STFldCharType.BEGIN);run.getContent().add(fldchar);return run;}private R getFieldEnd() {FldChar fldcharend = factory.createFldChar();fldcharend.setFldCharType(STFldCharType.END);R run = factory.createR();run.getContent().add(fldcharend);return run;}public RPr getRPr(String fontFamily, String colorVal, String fontSize, STHint sTHint, boolean isBlod,boolean isUnderLine, boolean isItalic, boolean isStrike) {RPr rPr = factory.createRPr();RFonts rf = new RFonts();rf.setHint(sTHint);rf.setAscii(fontFamily);rf.setHAnsi(fontFamily);rPr.setRFonts(rf);BooleanDefaultTrue bdt = factory.createBooleanDefaultTrue();rPr.setBCs(bdt);if (isBlod) {rPr.setB(bdt);}if (isItalic) {rPr.setI(bdt);}if (isStrike) {rPr.setStrike(bdt);}if (isUnderLine) {U underline = new U();underline.setVal(UnderlineEnumeration.SINGLE);rPr.setU(underline);}Color color = new Color();color.setVal(colorVal);rPr.setColor(color);HpsMeasure sz = new HpsMeasure();sz.setVal(new BigInteger(fontSize));rPr.setSz(sz);rPr.setSzCs(sz);return rPr;}private void setWatermarkHdr(HeaderPart headerPart, String text) throws Exception {ImagePngPart imagePart = new ImagePngPart(new PartName("/media/background.png"));ByteArrayOutputStream out = new ByteArrayOutputStream();ImageIO.write(createWaterMark(text), "png", out);byte[] imagebytes = out.toByteArray();imagePart.setBinaryData(imagebytes);Relationship rel = headerPart.addTargetPart(imagePart, RelationshipsPart.AddPartBehaviour.REUSE_EXISTING);String openXML = "<w:hdr mc:Ignorable=\"w14 wp14\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">"+ "<w:p>"+ "<w:pPr>"+ "<w:pStyle w:val=\"Header\"/>"+ "</w:pPr>"+ "<w:r>"+ "<w:rPr>"+ "<w:noProof/>"+ "</w:rPr>"+ "<w:pict>"+ "<v:shapetype coordsize=\"21600,21600\" filled=\"f\" id=\"_x0000_t75\" o:preferrelative=\"t\" o:spt=\"75\" path=\"m@4@5l@4@11@9@11@9@5xe\" stroked=\"f\">"+ "<v:stroke joinstyle=\"miter\"/>"+ "<v:formulas>"+ "<v:f eqn=\"if lineDrawn pixelLineWidth 0\"/>"+ "<v:f eqn=\"sum @0 1 0\"/>"+ "<v:f eqn=\"sum 0 0 @1\"/>"+ "<v:f eqn=\"prod @2 1 2\"/>"+ "<v:f eqn=\"prod @3 21600 pixelWidth\"/>"+ "<v:f eqn=\"prod @3 21600 pixelHeight\"/>"+ "<v:f eqn=\"sum @0 0 1\"/>"+ "<v:f eqn=\"prod @6 1 2\"/>"+ "<v:f eqn=\"prod @7 21600 pixelWidth\"/>"+ "<v:f eqn=\"sum @8 21600 0\"/>"+ "<v:f eqn=\"prod @7 21600 pixelHeight\"/>"+ "<v:f eqn=\"sum @10 21600 0\"/>"+ "</v:formulas>"+ "<v:path gradientshapeok=\"t\" o:connecttype=\"rect\" o:extrusionok=\"f\"/>"+ "<o:lock aspectratio=\"t\" v:ext=\"edit\"/>"+ "</v:shapetype>"+ "<v:shape id=\"WordPictureWatermark835936646\" o:allowincell=\"f\" o:spid=\"_x0000_s2050\" style=\"position:absolute;margin-left:0;margin-top:0;width:467.95pt;height:615.75pt;z-index:-251657216;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin\" type=\"#_x0000_t75\">"+ "<v:imagedata blacklevel=\"22938f\" gain=\"19661f\" o:title=\"docx4j-logo\" r:id=\"" + rel.getId() + "\"/>"+ "</v:shape>"+ "</w:pict>"+ "</w:r>"+ "</w:p>"+ "</w:hdr>";Hdr hdr = (Hdr) XmlUtils.unmarshalString(openXML);headerPart.setJaxbElement(hdr);}private static BufferedImage createWaterMark(String content) {Integer width = 1000;Integer height = 1360;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取bufferedImage对象String fontType = "宋体";Integer fontStyle = Font.PLAIN;Integer fontSize = 30;Font font = new Font(fontType, fontStyle, fontSize);Graphics2D g2d = image.createGraphics(); // 获取Graphics2d对象image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));g2d.dispose();for (int i = 1; i <= 20; i += 2) {for (int j = 1; j <= 10; j += 2) {int px = j * 100;int py = i * 100;g2d = image.createGraphics();g2d.setColor(java.awt.Color.black);g2d.setStroke(new BasicStroke(1)); // 设置字体g2d.setFont(font); // 设置字体类型 加粗 大小g2d.translate(px, py);// 设置原点g2d.rotate(Math.toRadians(-30));// 设置倾斜度FontRenderContext context = g2d.getFontRenderContext();Rectangle2D bounds = font.getStringBounds(content, context);g2d.drawString(content, 0, 0);g2d.dispose();}}return image;}private static P makePageBr() throws Exception {P p = factory.createP();R r = factory.createR();Br br = factory.createBr();br.setType(STBrType.PAGE);r.getContent().add(br);p.getContent().add(r);return p;}
}

pom:

<dependency><groupId>org.docx4j</groupId><artifactId>docx4j</artifactId><version>6.0.1</version></dependency><dependency><groupId>org.docx4j</groupId><artifactId>docx4j-ImportXHTML</artifactId><version>6.0.1</version></dependency><dependency><groupId>org.docx4j</groupId><artifactId>xhtmlrenderer</artifactId><version>3.0.0</version></dependency>

参考文档:https://python-docx.readthedocs.io/en/latest/dev/analysis/features/header.html?highlight=footer

docx4j生成Word添加页眉页脚水印 页眉页脚奇偶显示首页显示相关推荐

  1. Docx4j生成word表格(无问题),用Libreoffice转换为pdf格式乱掉问题

    缘起 最近做了一个项目,用Docx4j生成word,然后转换为pdf展示,在前面的博文java docx4j动态生成表格,保存为word,并通过Libreoffice转PDF已经给过较为完美的解决方案 ...

  2. 用docx4j生成word之后转成pdf

    所需Jar包 (注意,jar不能少,版本也要对应,否则会报错,类似:org/plutext/jaxb/xslfo/ObjectFactory 这样的错误都是因为缺少jar包) 注意:下面字体格式设置可 ...

  3. Docx4j生成word文件转PDF乱码问题

    问题描述 最近做一个租房系统,需要在线生成合同预览,用word模板参数加载真实参数后转PDF发现中文乱码,排查发现只有在word转pdf文件的时候才乱码 解决思路 常规思路: 先从代码层处理,在转PD ...

  4. poi生成word文档,插入图片,echar报表生成到word,word表格

    poi生成word文档,word表格,将echar报表生成到word 项目中用到生成word报表,报表中有表格的合并 .页眉.表格中会有报表图片.然后查找了网上的资料,利用echar生成柱状图,然后已 ...

  5. Freemarker生成word文件,打开后页眉和页脚图片不显示

    Freemarker生成word文件,打开后页眉和页脚图片不显示 在我们开发过程中通常会把模板文件Ctrl+Alt+L格式化,方便处理.这样就造成word的标签格式产生多余的换行或者空白,但是word ...

  6. 使用FreeMarker生成word文件自定义每页页眉或页脚

    最新工作中遇到生成word中表格时,要求文档中每页头部和底部都是固定格式的表格,但是内容不一样,头部信息在word中画样式的时候就可以设置为"在各页顶端以标题形式重复出现",而底部 ...

  7. Java 利用poi给word添加页眉页脚,页眉左边为公司logo图片,右为公司全称,页脚左为公司地址,右为页码总页数

    参考链接: http://www.it1352.com/219785.html 1. 生成带公司logo的页眉 public void createHeader(XWPFDocument doc, S ...

  8. Docx4j替换word文档的页眉

    Docx4j替换word文档的页眉 目前国内关于Docx4j的帖子少的可怜,看来看去都是那几个.本人使用Docx4j也有一段时间,虽然还有许多东西没了解全,但在这边想分享我的学习经验,互相交流,也方便 ...

  9. C# 复制Word(复制全部内容、部分内容、页眉页脚)

    本篇示例将介绍C# 复制Word文档的方法.根据不同的需要,我们将复制Word文档分三种情况来讲述,具体包括以下几点: 复制整个Word文档 复制文档中的部分内容 复制页眉或者页脚 工具使用 Free ...

最新文章

  1. 文本处理相关资料整理
  2. C++ Primer 5th笔记(7)chapter7 类:编译相关
  3. 截取字符串指定内容,并用*号代替
  4. 【NLP】Transformer的中年危机?
  5. 解决firefox不能安装Flash插件
  6. I00037 亏数(Deficient number)
  7. Linux学习总结(22)——CentOS7.2安装Nginx
  8. 通俗易懂!视觉slam第九部分——光流(Optical Flow)
  9. Linux系统管理系列(1)——文件管理权限详解 chgrp chown chmod rwx等等
  10. 基于云端的通用权限管理系统,SAAS服务,基于SAAS的权限管理,基于SAAS的单点登录SSO,企业单点登录,企业系统监控,企业授权认证中心...
  11. Composer最近升级后导致无法下载包的问题解决办法
  12. Atitit uke人才分类 杰出人才 高级人才、专业技术人才、技能人才 杰出人才移民共包含科技丶艺术丶工商丶运动及教育五大领域 杰出人才定义 编辑 联邦移民法规定「杰出能力」是指在科学丶艺
  13. mysql授权远程访问 网段_MySQL授权和开启远程访问
  14. JPA如何查询部分字段
  15. Requests爬取chinadaily海量新闻数据
  16. isPrime 判断素数的函数
  17. Android之Keystore文件签名(获取查看apk签名)
  18. 京东平台小家电用户画像分析报告
  19. Java多线程学习详细学习及扩展
  20. coreldraw x4离线激活_coreldraw x4怎么激活 coreldraw x4注册机使用方法

热门文章

  1. mysql 1265警告
  2. 华为云ECS下安装MySQL
  3. 婴幼儿呼吸道感染和发烧
  4. FME助力新型基础测绘之存量测绘成果数据转换地理实体
  5. ubuntu系统安装时 MBR和GPT的区别
  6. MT4如何设置手机app通知
  7. 西游记笔记与想法(4)
  8. 49个终身受用的世界顶级思维(收藏)
  9. php培训月度总结,PHP常量,数组和分支语句小结--PHP培训十期线上班
  10. vue打包This is probably not a problem with npm. There is likely additional logging output above