📢📢📢📣📣📣
哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝
一位上进心十足的【Java ToB端大厂领域博主】!😜😜😜
喜欢java和python,平时比较懒,能用程序解决的坚决不手动解决😜😜😜
✨ 如果有对【java】感兴趣的【小可爱】,欢迎关注我❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
————————————————如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。
目录
🚗场景
现在有一个场景,现在需要对word进行编辑,需求是能够根据页眉中的变量,进行替换。指定的页眉或页脚的变量需要被传入的参数替换。达到动态替换的目的,整个word文档也就成了一个模版。
下面是一个word模板的部分截图,来明确需求
其中的${}$中的内容约定是一个标示,表示需要替换的部分,如果我们传入的参数是a.b=567,在渲染完成之后,文档中页眉这里的变量${a.b}$就会替换成567。
图片中圈起来的部分,文档中点内容,这里的文档中的内容属于文档体部分这篇文章暂时不介绍这部分的替换过程,只考虑文档中的页眉和页脚部分的替换。
由于这里只是介绍页眉页脚的替换,所以像需求的变量查找的匹配等就不细讲了,只是说一下POI对页眉和页脚的操作。
🚢实现方法
废话不多说 来讲解一下今天的正文,如何通过POI实现文档中页眉和页脚的替换工作。
🚗(1)引入的依赖
注意不同版本之间可能会有冲突这里都是4.1.2
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
🚚(2)代码实现
package com.demo;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.util.Units;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSettings;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.List;
public class CopyInstance {
public static void main(String[] args) throws Exception {
File is = new File("/Users/lee/Desktop/测试条款.docx");//文件路径
FileInputStream fis = new FileInputStream(is);
XWPFDocument docx = new XWPFDocument(fis);//文档对象
createHeader(docx, "测88888", "aaaa");
}
public static void createHeader(XWPFDocument doc, String orgFullName, String logoFilePath) throws Exception {
//获取页眉,判断页眉是否为空
List<XWPFHeader> pageHeaders = doc.getHeaderList();
if (CollectionUtils.isEmpty(pageHeaders)) {
return;
// //生成首页页眉
// XWPFParagraph paragraph = doc.createHeader(HeaderFooterType.FIRST).createParagraph();
// XWPFRun run = paragraph.createRun();
paragraph.setAlignment(ParagraphAlignment.RIGHT);
// run.setText(orgFullName);
// run.setFontFamily("C39HrP24DlTt");//设置页眉字体,这里是条形码字体
//
// //生成偶数页的页眉
// paragraph = doc.createHeader(HeaderFooterType.EVEN).createParagraph();
// run = paragraph.createRun();
paragraph.setAlignment(ParagraphAlignment.LEFT);
// run.setText(orgFullName);
// run.setFontSize(8);//设置页眉字体大小
//
// //生成奇数页的页眉
// paragraph = doc.createHeader(HeaderFooterType.DEFAULT).createParagraph();
// run = paragraph.createRun();
paragraph.setAlignment(ParagraphAlignment.LEFT);
// run.setText(orgFullName);//其它页页眉内容与首页不同,但奇数页和偶数页要单独设置成一样的内容
//
// Field filedSet = XWPFDocument.class.getDeclaredField("settings");
// filedSet.setAccessible(true);
// XWPFSettings xwpfsettings = (XWPFSettings) filedSet.get(doc);
//
// Field filedCtSet = XWPFSettings.class.getDeclaredField("ctSettings");
// filedCtSet.setAccessible(true);
// CTSettings ctSettings = (CTSettings) filedCtSet.get(xwpfsettings);
// ctSettings.addNewEvenAndOddHeaders();
} else {
//当合同文本有页眉时,内容不为空,将原内容进行替换
for (XWPFHeader pageHeader : pageHeaders) {
List<XWPFParagraph> paragraphs = pageHeader.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
//BOTH 之前的也会保留
//MEDIUM_KASHIDA 之前的也会保留
//DISTRIBUTE 两端对齐
//NUM_TAB 两端
//合同有页眉,但是内容可能为空,对照上面第2 点
//((XWPFParagraph) pageHeader.bodyElements.get(0)).getRuns()
if (!runs.isEmpty()) {
for (int i = 0; i < runs.size(); i++) {
//设置成一个run
XWPFRun run = runs.get(i);
//这里就是我们需要替换的内容
run.setText(orgFullName, 0);
paragraph.setAlignment(ParagraphAlignment.HIGH_KASHIDA);//设置页眉左对齐
// paragraph.setAlignment();
}
} else {
//生成首页页眉
XWPFParagraph paragraph2 = doc.createHeader(HeaderFooterType.FIRST).createParagraph();
XWPFRun run = paragraph2.createRun();
paragraph2.setAlignment(ParagraphAlignment.HIGH_KASHIDA);//设置页眉居中
run.setText(orgFullName);
run.setFontFamily("C39HrP24DlTt");
//生成偶数页的页眉
paragraph2 = doc.createHeader(HeaderFooterType.EVEN).createParagraph();
run = paragraph2.createRun();
// paragraph2.setAlignment(ParagraphAlignment.LEFT);
run.setText(orgFullName);
run.setFontSize(8);
//生成奇数页的页眉
paragraph2 = doc.createHeader(HeaderFooterType.DEFAULT).createParagraph();
run = paragraph2.createRun();
// paragraph2.setAlignment(ParagraphAlignment.LEFT);
run.setText(orgFullName);
Field filedSet = XWPFDocument.class.getDeclaredField("settings");
filedSet.setAccessible(true);
XWPFSettings xwpfsettings = (XWPFSettings) filedSet.get(doc);
Field filedCtSet = XWPFSettings.class.getDeclaredField("ctSettings");
filedCtSet.setAccessible(true);
CTSettings ctSettings = (CTSettings) filedCtSet.get(xwpfsettings);
ctSettings.addNewEvenAndOddHeaders();
//此处一定要断开循环
break;
}
}
}
}
//
// CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr();
// XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy( doc, sectPr );
//
// XWPFHeader header = headerFooterPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT);
//
// XWPFParagraph paragraph = header.createParagraph();
// paragraph.setAlignment( ParagraphAlignment.LEFT );
// paragraph.setBorderBottom( Borders.THICK );
// XWPFRun run = paragraph.createRun();
//
// String pic = XWDFClass.class.getClassLoader().getResource("").getPath()+"csdn-logo_.png";
String imgFile = pic.substring(1);
// String imgFile = pic;
//
// File file = new File( imgFile );
// InputStream is = new FileInputStream( file );
// XWPFPicture picture = run.addPicture( is, XWPFDocument.PICTURE_TYPE_JPEG, imgFile, Units.toEMU( 80 ), Units.toEMU( 45 ) );
// String blipID = "";
// for( XWPFPictureData picturedata : header.getAllPackagePictures() ) { // 这段必须有,不然打开的logo图片不显示
// blipID = header.getRelationId( picturedata );
// picture.getCTPicture().getBlipFill().getBlip().setEmbed( blipID );
// }
// run.addTab();
// is.close();
//
// run.setText( "你eeeee好" );
// String path = XWDFClass.class.getClassLoader().getResource("").getPath();
//
File file1 = new File(path+"wjh.doc");
// File file1 = new File("/Users/ligang/Desktop/a.docx");
//
// FileOutputStream os = new FileOutputStream(file1);
//
// doc.write( os );
// os.close();
doc.write(new FileOutputStream("/Users/ligang/Desktop/x.docx"));
doc.close();
System.out.println("OK");
}
}
✈️(3)结果:
源word文件
替换页眉的word图片
🚄(4)说明
POI对word文档的操作是相对支持很好的,使用非常方便。
我们每一个word文档读取之后都会生成一个XWPFDocument doc对象。这个对象记录了整个word文档的全部信息,例如页眉页脚等
获取页眉的方法
List<XWPFHeader> pageHeaders = doc.getHeaderList();
这里获取到的是整个word文档中的全部页眉。
一般情况下,这里的页眉其实在POI中也会当成段落进行处理
List<XWPFParagraph> paragraphs = pageHeader.getParagraphs()
接下来进行的操作就是像其他的poi对word文档的操作段落就好了,这就像数学中的转化方法,把陌生的东西转化成熟悉的东西,后续操作就和之前老的操作方法相同了。
如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。