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. Delphi MaskEdit 组件

  2. elastic 基本操作

    官方参考文档: https://www.elastic.co/guide/cn/elasticsearch/guide/current/index-doc.html 1.查看 有哪些索引: curl ...

  3. nginx服务学习第一章

    一.ubuntu系统安装nginx服务 # apt-get install nginx 二.nginx.config配置文件详解 配置文件结构: 全局块(全局变量) events{ } http{ h ...

  4. Markdown,让你的代码高亮起来

    当你的审美提高或者习惯了Linux下的黑色代码高亮,已经不满足与博客园原有的代码高亮,那么这篇博客就是你的选择. 代码块高亮 代码块Highlight /* 使用了Monokai Sublime的黑色 ...

  5. Jmeter 常见逻辑控制器详解

    简介 Jmeter有很多逻辑控制器,可以控制请求的执行顺序和执行逻辑,本文就Jmeter常见的逻辑控制器做一个详细的描述,并通过示例让大家了解逻辑控制器的作用.   代码的逻辑分支通常有: 条件判断I ...

  6. LocalDatetime 与 mybatis、json的坑

    总所周知,localdatetime是jdk8 推出的关于日期计算非常方便地一个类,一旦开始用上就欲罢不能.但是在使用的时候,坑还是蛮多的. 一.mybatis与LocalDatetime 如果直接将 ...

  7. python 继承:重写、拓展(六)

    1.继承:父类有的子类也有 2.多继承:若继承多个父类有相同的函数,则继承前面的函数,传递参数的个数也与继承的函数位置有关 3.超继承:针对继承一个父类使用,不仅有父类的特写同时也有自己的新特性  s ...

  8. Acwing-119-袭击(分治)

    链接: https://www.acwing.com/problem/content/121/ 题意: 在与联盟的战斗中屡战屡败后,帝国撤退到了最后一个据点. 依靠其强大的防御系统,帝国击退了联盟的六 ...

  9. qt5--鼠标操作

    #include "mylabel.h" #include <QDebug> #include <QPointF> #include <QPoint& ...

  10. 【Winform-ComboBox】实现ComboBox下拉框与数据库的绑定

    实现效果如下: 1.设计窗体 下拉框的名称cmbName 2.连接数据库 DBHelper类代码: class DBHelper { /// <summary> /// 创建静态连接字符串 ...