package com.sisa.auweb.tools.bookmarkprocess;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.impl.piccolo.io.FileFormatException; import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import static feign.Util.toByteArray; /**
* Created by clyan on 2019/7/2 15:15.
*/
public class Word2007 {
private String wordPath = "";
private String writeFilePath = "";
private Object obj = null;
Map<String, Object> map = new HashMap<String, Object>(); /*
path:文件路径
dataSource/objectMap:数据源.
*/
public Word2007(String path, String newFilePath, Object dataSource, Map<String, Object> objectMap) throws IOException { File file = new File(path); if (file.exists() == false || file.isFile() == false) {
throw new FileNotFoundException("文件不存在");
} InputStream is = new FileInputStream(file);
byte[] bytes = new byte[10]; if (is.read(bytes, 0, bytes.length) == -1) {
is.close();
throw new FileFormatException("文件格式错误,本文件只能解析docx文件");
}
String fileCode = bytesToHexString(bytes).toLowerCase(); if (fileCode.length() > 1) {
if (fileCode.equals("504b0304140006000800") == false) {
is.close();
throw new FileFormatException("文件格式错误,本文件只能解析docx文件");
}
}
is.close(); wordPath = path;
writeFilePath = newFilePath;
obj = dataSource; if (dataSource != null) {
pickFields();
} else {
this.map = objectMap;
}
} public void parseTemplate() { try {
InputStream is = new FileInputStream(wordPath);
XWPFDocument doc = new XWPFDocument(OPCPackage.open(is));
List<XWPFParagraph> list = doc.getParagraphs(); for (int i = 0; i < list.size(); i++) {
XWPFParagraph graph = list.get(i);
replaceInXWPFParagraph(graph, map);
}
replaceTables(map, doc);
OutputStream os = new FileOutputStream(writeFilePath);
doc.write(os);
os.flush();
close(os);
close(is); } catch (Exception ex) {
System.out.print(ex.getStackTrace());
}
} private void replaceInXWPFParagraph(XWPFParagraph para, Map<String, Object> params) { List<XWPFRun> runs = null;
Matcher matcher;
String runText = ""; if (matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
if (runs.size() > 0) {
int j = runs.size();
for (int i = 0; i < j; i++) {
XWPFRun run = runs.get(i);
String i1 = run.toString();
runText += i1;
}
}
int replaceCount = runText.trim().split("\\$").length - 1;
matcher = matcher(runText);
if (matcher.find()) {
while ((matcher = matcher(runText)).find()) {
runText = String.valueOf(params.get(matcher.group(1)));
}
//数据源不存在时跳过,以便检查
if (runText.equals("null")) {
runText = "";
}
if (runs.size() > 0) {
boolean handler = false;
for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i);
String temp = run.toString(); if (handler == false && temp.indexOf("$") >= 0) {
handler = true;
}
if (handler == true) {
if (temp.equals("$") || temp.indexOf("$") == 0) {
if (temp.indexOf("}") >= 0) {
run.setText(runText, 0);
handler = false;
//一行有多个${情况
replaceCount--;
if (replaceCount > 0) {
runText = "";
int j = runs.size();
for (int x = 0; x < j; x++) {
XWPFRun run1 = runs.get(x);
String i1 = run1.toString();
runText += i1;
}
matcher = matcher(runText);
if (matcher.find()) {
while ((matcher = matcher(runText)).find()) {
runText = String.valueOf(params.get(matcher.group(1)));
}
}
}
} else {
run.setText("", 0);
}
continue;
}
if (temp.indexOf("}") < 0) {
run.setText("", 0);
continue;
}
if (temp.indexOf("}") >= 0) {
run.setText(runText, 0);
handler = false;
//一行有多个${情况
replaceCount--;
if (replaceCount > 0) {
runText = "";
int j = runs.size();
for (int x = 0; x < j; x++) {
XWPFRun run1 = runs.get(x);
String i1 = run1.toString();
runText += i1;
} matcher = matcher(runText);
if (matcher.find()) {
while ((matcher = matcher(runText)).find()) {
runText = String.valueOf(params.get(matcher.group(1)));
}
}
}
}
}
}
}
}
}
} private void pickFields() {
Class dataClass = (Class) obj.getClass();
Field[] fs = dataClass.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
Field f = fs[i];
f.setAccessible(true);
Object val = new Object();
try {
val = f.get(obj);
map.put(f.getName(), val);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
} private byte[] generalFileContent() throws IOException {
InputStream is = new FileInputStream(writeFilePath);
byte[] data = toByteArray(is);
is.close();
return data;
} private void close(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} private void close(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} private String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (null == src || src.length < 1)
return null;
for (byte b : src) {
int v = b & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2)
stringBuilder.append(0);
stringBuilder.append(hv);
}
return stringBuilder.toString();
} private static Matcher matcher(String str) {
Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher;
} private void replaceTable(Map<String, Object> params, XWPFTable table) {
int count = table.getNumberOfRows();
for (int i = 0; i < count; i++) {
XWPFTableRow row = table.getRow(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
List<XWPFParagraph> list = cell.getParagraphs();
for (int j = 0; j < list.size(); j++) {
replaceInXWPFParagraph(list.get(j), params);
}
}
}
} private void replaceTables(Map<String, Object> params, XWPFDocument document) {
Iterator<XWPFTable> itTable = document.getTablesIterator();
while (itTable.hasNext()) {
XWPFTable table = itTable.next();
replaceTable(params, table);
}
}
}

Word模板替换的更多相关文章

  1. C#读取Word模板替换相应的字符串(标签)生成新的Word

    在平常工作中,生成word的方式主要是C#读取html的模板文件处理之后保存为.doc文件,这样的好处是方便,快捷,能满足大部分的需求.不过有些特殊的需求并不能满足,如要生成的Word为一个表格,只是 ...

  2. 利用POI 技术动态替换word模板内容

    项目中需要实现一个功能,动态替换给定模板里面的内容,生成word文档提供下载功能. 中间解决了问题有: 1.页眉的文档logo图片解决,刚开始的时候,HWPFDocument 对象无法读取图片对象(已 ...

  3. POI Word 模板 文字 图片 替换

    实验环境:POI3.7+Word2007 Word模板: 替换后效果: 代码: 1.入口文件 public class Test { public static void main(String[] ...

  4. POI不同版本替换Word模板时的问题

    一.问题描述 通过POI,把Word中的占位符替换为实际的值,以生成复杂结构的业务报告. 在POI 3.9上,功能正常.由于某些原因升级到POI 3.10.1后,项目组反馈说Word模板出错,无法生成 ...

  5. word模板导出的几种方式:第一种:占位符替换模板导出(只适用于word中含有表格形式的)

    1.占位符替换模板导出(只适用于word中含有表格形式的): /// <summary> /// 使用替换模板进行到处word文件 /// </summary> public ...

  6. JAVA Freemarker + Word 模板 生成 Word 文档 (普通的变量替换,数据的循环,表格数据的循环,以及图片的东替换)

    1,最近有个需求,动态生成 Word 文当并供前端下载,网上找了一下,发现基本都是用 word 生成 xml 然后用模板替换变量的方式 1.1,这种方式虽然可行,但是生成的 xml 是在是太乱了,整理 ...

  7. C# 操作word 模板 值 替换

    1.引用 aspose.words   dll 2.word 使用doc 3.给word 模板中添加要替换位置的 书签 .引用 aspose.words dll .word 使用doc .给word ...

  8. tp5 使用phpword 替换word模板并利用com组件转换pdf

    tp5   使用phpword 替换word模板并利用com组件转换pdf 一.首先composer安装PHPword,就不多说了 二.然后是把模板中要替换的部分用变量代替 三.把原始的模板文件放入项 ...

  9. poi 针对word模板内容替换

    最近多了一个需求,需要对word模板内容进行替换,一开始用的是word03版的,替换起来比较简单,主要是range对像替换非常方便,而且可以保留替换前的字体样式. InputStream is = n ...

随机推荐

  1. DHCP服务部署

    目录 DHCP服务部署 一. 简介 二. 用途及功能 三. 原理+示意图 四. 实战搭建 相关文件 配置基础DHCP服务器 配置DHCP保留地址 配置DHCP超级作用域 配置DHCP中继 五. 小结 ...

  2. 51单片机通过ESP8266模块与手机进行通讯(单片机)

    相关连接和资料下载: 个人博客 资料下载 Step1:配置ESP8266 通过USB转TTL模块把ESP8266模块和电脑连接起来,如图: 把ESP8266模块的VCC,GND,CH_PD,UTXD, ...

  3. PAT Basic 1002 写出这个数 (20 分)

    读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值.这里保证 n 小于 1. 输出格式: 在一行内输出 n 的 ...

  4. 防sql注入方法

    mysql_escape_string(strip_tags($arr)) /** * 函数名称:post_check() * 函数作用:对提交的编辑内容进行处理 * 参 数:$post: 要提交的内 ...

  5. 多线程之CountDownLatch

    下面请看一个应用场景:有1个driver和5个worker,需要满足以下两点要求: 当driver完成了全部的工作之后才允许worker们开始工作: 当所有的worker都完成了自己的工作之后,dri ...

  6. 【BZOJ1049】【Luogu P2501】 [HAOI2006]数字序列 DP,结论,LIS

    很有(\(bu\))质(\(hui\))量(\(xie\))的一个题目. 第一问:求最少改变几个数能把一个随机序列变成单调上升序列. \(Solution:\)似乎是一个结论?如果两个数\(A_i\) ...

  7. loj2589 「NOIP2009」Hankson 的趣味题

    对于质因数分解理解还不到位. 此题可知$lcm$是$x$的倍数,$x$是$lcm$的约数,只要在$lcm$的分解质因数里对每一个质因子讨论种数即可. 具体来说,对于$lcm$的一个质因子$p$,讨论$ ...

  8. DevExpress ASP.NET v19.1版本亮点:发布全新的Gantt控件

    行业领先的.NET界面控件DevExpress 发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Controls v19.1中新增的一些控件及增强的控件功能 ...

  9. 零拷贝的原理及Java实现

    在谈论Kafka高性能时不得不提到零拷贝.Kafka通过采用零拷贝大大提供了应用性能,减少了内核和用户模式之间的上下文切换次数.那么什么是零拷贝,如何实现零拷贝呢? 什么是零拷贝 WIKI中对其有如下 ...

  10. [洛谷P1712] NOI2016 区间

    问题描述 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一 ...