模板样式:
生成效果:
上代码:
package kbaseSync.Base;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import kbaseSync.config.ChromeDriverConf;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.springframework.util.ResourceUtils;
/**
* 通过word模板生成新的word工具类
* @author SongBin on 2019/9/5.
*/
public class WorderToNewWordUtils {
/**
* 根据模板生成新word文档
* 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
* @param inputUrl 模板存放地址
* @param outputUrl 新文档存放地址
* @param textMap 需要替换的信息集合
* @param tableList 需要插入的表格信息集合
* @return 成功返回true,失败返回false
*/
public static boolean changWord(String inputUrl, String outputUrl,
Map<String, String> textMap, List<String[]> tableList, Map<String ,String> imgMap) {
//模板转换默认成功
boolean changeFlag = true;
try {
//获取docx解析对象
XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
//解析替换文本段落对象
WorderToNewWordUtils.changeText(document, textMap,imgMap);
//解析替换表格对象
WorderToNewWordUtils.changeTable(document, textMap, tableList);
//生成新的word
File file = new File(outputUrl);
FileOutputStream stream = new FileOutputStream(file);
document.write(stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
changeFlag = false;
}
return changeFlag;
}
/**
* 根据无表格模板生成新word文档
* @param inputUrl 模板存放地址
* @param outputUrl 新文档存放地址
* @param textMap 需要替换的信息集合
* @return 成功返回true,失败返回false
*/
public static boolean changWord(String inputUrl, String outputUrl,
Map<String, String> textMap, Map<String ,String> imgMap) {
//模板转换默认成功
boolean changeFlag = true;
try {
//获取docx解析对象
XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
//解析替换文本段落对象
WorderToNewWordUtils.changeText(document, textMap,imgMap);
//生成新的word
File file = new File(outputUrl);
FileOutputStream stream = new FileOutputStream(file);
document.write(stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
changeFlag = false;
}
return changeFlag;
}
/**
* 遍历word获取每种农产品需要统计的菜品类型
* @param inputUrl 模板地址
* @return
*/
public static Map<String,String> getClassifyObj(String inputUrl){
Map<String,String> map = new HashMap<>();
try {
//获取docx解析对象
XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
//获取段落集合
List<XWPFParagraph> paragraphs = document.getParagraphs();
int i = 1;
for (XWPFParagraph paragraph : paragraphs) {
//判断此段落时候需要进行替换
String text = paragraph.getText();
Matcher m = Pattern.compile("(?d)——(.+?))$").matcher(text);
if (m.find()) {
Matcher matcher=Pattern.compile("(?d)((.+?))$").matcher(text);
if (matcher.find()){
String objstr = matcher.group(1).replace('、',',');
map.put("obj0"+i,objstr);
i++;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
/**
* 替换段落文本
* @param document docx解析对象
* @param textMap 需要替换的信息集合
*/
public static void changeText(XWPFDocument document, Map<String, String> textMap, Map<String ,String> imgMap){
//获取段落集合
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
//判断此段落时候需要进行替换
String text = paragraph.getText();
if(checkText(text)){
List<XWPFRun> runs = paragraph.getRuns();
XWPFRun run0 = runs.get(0);
if(text.matches("(?d)^\\$img0[1-5]")){//插入图片
for (XWPFRun run : runs) {
//替换模板原来位置
run.setText("",0);
}
changeParagraphImg(run0,imgMap.get(text));
}else{
if (text.indexOf(":")!= -1&&runs.size()>1){
run0.setText(text.substring(0,text.indexOf(":")+1),0);
XWPFRun run1 = runs.get(1);
for (int i=1;i<runs.size();i++) {
//替换模板原来位置
XWPFRun run = runs.get(i);
run.setText("",0);
}
text = text.replaceAll("(?d)^(.+?):","");
//替换模板原来位置
run1.setText(changeValue(text, textMap),0);
run1.setBold(false);
}else{
for (XWPFRun run : runs) {
//替换模板原来位置
run.setText("",0);
}
//替换模板原来位置
run0.setText(changeValue(text, textMap),0);
}
}
}
}
}
/**
* 插入图片
* @param run
* @param imgGuid
*/
public static void changeParagraphImg(XWPFRun run, String imgGuid){
try {
String basePath =StringUtil.isBlank(ChromeDriverConf.picSavePath)?"D:/imgupload/":ChromeDriverConf.picSavePath;
String imgFile = basePath + imgGuid +".jpg";
System.out.println("插入图表图片:" + imgFile);
FileInputStream is = new FileInputStream(imgFile);
run.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, imgFile, Units.toEMU(400), Units.toEMU(300)); // 100x100 pixels
is.close();
run.setText("",0);
} catch (Exception e) {
System.out.println("Error: ======== 插入单个图片时出错了:可能是图片路径不存在。不影响主流程");
e.printStackTrace();
}
}
/**
* 替换表格对象方法
* @param document docx解析对象
* @param textMap 需要替换的信息集合
* @param tableList 需要插入的表格信息集合
*/
public static void changeTable(XWPFDocument document, Map<String, String> textMap,
List<String[]> tableList){
//获取表格对象集合
List<XWPFTable> tables = document.getTables();
for (int i = 0; i < tables.size(); i++) {
//只处理行数大于等于2的表格,且不循环表头
XWPFTable table = tables.get(i);
if(table.getRows().size()>1){
//判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
if(checkText(table.getText())){
List<XWPFTableRow> rows = table.getRows();
//遍历表格,并替换模板
eachTable(rows, textMap);
}else{
// System.out.println("插入"+table.getText());
insertTable(table, tableList);
}
}
}
}
/**
* 遍历表格
* @param rows 表格行对象
* @param textMap 需要替换的信息集合
*/
public static void eachTable(List<XWPFTableRow> rows ,Map<String, String> textMap){
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
//判断单元格是否需要替换
if(checkText(cell.getText())){
List<XWPFParagraph> paragraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
run.setText(changeValue(run.toString(), textMap),0);
}
}
}
}
}
}
/**
* 为表格插入数据,行数不够添加新行
* @param table 需要插入数据的表格
* @param tableList 插入数据集合
*/
public static void insertTable(XWPFTable table, List<String[]> tableList){
//创建行,根据需要插入的数据添加新行,不处理表头
for(int i = 1; i < tableList.size(); i++){
XWPFTableRow row =table.createRow();
}
//遍历表格插入数据
List<XWPFTableRow> rows = table.getRows();
for(int i = 1; i < rows.size(); i++){
XWPFTableRow newRow = table.getRow(i);
List<XWPFTableCell> cells = newRow.getTableCells();
for(int j = 0; j < cells.size(); j++){
XWPFTableCell cell = cells.get(j);
cell.setText(tableList.get(i-1)[j]);
}
}
}
/**
* 判断文本中是否包含$
* @param text 文本
* @return 包含返回true,不包含返回false
*/
public static boolean checkText(String text){
boolean check = false;
if(text.indexOf("$")!= -1){
check = true;
}
return check;
}
/**
* 匹配传入信息集合与模板
* @param value 模板需要替换的区域
* @param textMap 传入信息集合
* @return 模板需要替换区域信息集合对应值
*/
public static String changeValue(String value, Map<String, String> textMap){
Set<Entry<String, String>> textSets = textMap.entrySet();
for (Entry<String, String> textSet : textSets) {
//匹配模板与替换值 格式${key}
String key = "${"+textSet.getKey()+"}";
String regexstr = "(?d)\\$\\{"+textSet.getKey()+"\\}";
if(value.indexOf(key)!= -1){
value = value.replaceAll(regexstr,textSet.getValue());
}
}
//模板未匹配到区域替换为空
if(checkText(value)){
value = value.replaceAll("(?d)\\$\\{(.+?)\\}","");
}
return value;
}
public static void main(String[] args) {
// 测试1
//模板文件地址
/*String inputUrl = "C:\\Users\\SongBin\\Desktop\\demo\\001.docx";
//新生产的模板文件
String outputUrl = "C:\\Users\\SongBin\\Desktop\\demo\\test.docx";
Map<String, String> testMap = new HashMap<String, String>();
testMap.put("name", "小明");
testMap.put("sex", "男");
testMap.put("age", "30");
testMap.put("like", "IT");
testMap.put("birthday", "2019-02-18");
testMap.put("address", "软件园");
testMap.put("phone", "18612100611");
testMap.put("email", "1370811553@qq.com");
List<String[]> testList = new ArrayList<String[]>();
testList.add(new String[]{"1","1AA","1BB","1CC"});
testList.add(new String[]{"2","2AA","2BB","2CC"});
testList.add(new String[]{"3","3AA","3BB","3CC"});
testList.add(new String[]{"4","4AA","4BB","4CC"});
WorderToNewWordUtils.changWord(inputUrl, outputUrl, testMap, testList);*/
// 测试2
//模板文件地址
String inputUrl2 = "C:\\Users\\SongBin\\Desktop\\demo\\报告模板-价格.docx";
//新生产的模板文件
String outputUrl2 = "C:\\Users\\SongBin\\Desktop\\demo\\test.docx";
Map<String, String> testMap2 = new HashMap<String, String>();
testMap2.put("datetime", "2019-02-06");
testMap2.put("粳米(普通)","粳米(普通)25元/公斤;");
testMap2.put("大米","大米25元/公斤;");
testMap2.put("week","07.16-7-22 ");
Map<String ,String> imgMap = new HashMap<>();
imgMap.put("$img01","3f956a32-f236-4baa-a8be-f465fa844580");
imgMap.put("$img02","3f956a32-f236-4baa-a8be-f465fa844580");
imgMap.put("$img03","3f956a32-f236-4baa-a8be-f465fa844580");
imgMap.put("$img04","3f956a32-f236-4baa-a8be-f465fa844580");
imgMap.put("$img05","3f956a32-f236-4baa-a8be-f465fa844580");
WorderToNewWordUtils.changWord(inputUrl2, outputUrl2, testMap2,imgMap);
String content = "在一些字里面放进去高中这两个字";
Matcher matcher = Pattern.compile("高中").matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
//判断此段落时候需要进行替换
/*String text = "近一周09.05-09.11农产品价格走势图——蔬菜(大白菜、小白菜、油菜、白萝卜、西红柿、黄瓜、茄子、香菇、平菇)";
Matcher m = Pattern.compile("(?d)——(.+?))$").matcher(text);
if (m.find()) {
Matcher matcher=Pattern.compile("(?d)((.+?))$").matcher(text);
if (matcher.find()){
String objstr = matcher.group(1).replace('、',',');
System.out.println(objstr);
}
}*/
//测试但斜杠转转双斜杠
//模板文件地址
/*String inputUrl = null;
try {
inputUrl = ResourceUtils.getURL("classpath:static/wordmodel/报告模板-价格.docx").getPath().substring(1);
inputUrl = inputUrl.replaceAll("/", "\\\\\\\\");
try {
inputUrl = java.net.URLDecoder.decode(inputUrl,"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(inputUrl);
} catch (FileNotFoundException e) {
e.printStackTrace();
}*/
}
}
更多内容请访问:IT源点
注意:本文归作者所有,未经作者允许,不得转载