1,需要的jar:
2,替换docx文档的文字、图片实例
* 注意事项:
* word中的替换的文字replaceStr一定是从普通txt文本中粘贴过来的,这样才可以保证这些replaceStr的所有属性一致
* 才能保证这些replaceStr在同一个XWPFRun中。
public class WordTest2 {
String templatePathX = "D:/temp/打印样本/poi/打印样本.docx";
String savePath = "D:/temp/打印样本/poi/打印样本-temp.docx";
//image
String logoImagePath = "D:/temp/打印样本/forest_logo.png";
String IconImagePath = "D:/temp/打印样本/icon.jpg";
@Test
public void testDocx() {
try {
WordDocxUtil wordDocxUtil=new WordDocxUtil(templatePathX);
// ArrayList
// for(String replaceEle:replaceEles){
// System.out.println(replaceEle);
// }
//替换文字
// Map
// map.put("${orderId}", "B123123");
// map.put("${boxName}", "王五");
// map.put("${course-1}", "语文");
// map.put("${score}", "85");
// wordDocxUtil.replaceText(map);
//单个文字替换
// wordDocxUtil.replaceText("${course}", "语文");
//正则表达式文字替换
// wordDocxUtil.replaceTextByRegex("\\$\\{course-\\d\\}", "[-_-]");
//替换图片
// Map
// imageMap.put("width", "50");
// imageMap.put("height", "50");
// imageMap.put("imageType", WordDocxUtil.getSuffix(logoImagePath));
// imageMap.put("content", WordDocxUtil.inputStream2ByteArray(new FileInputStream(logoImagePath), true));
// wordDocxUtil.replaceImage("${forestLogo}", imageMap);
//
// imageMap = new HashMap
// imageMap.put("width", "50");
// imageMap.put("height", "50");
// imageMap.put("imageType", WordDocxUtil.getSuffix(IconImagePath));
// imageMap.put("content", WordDocxUtil.inputStream2ByteArray(new FileInputStream(IconImagePath), true));
// wordDocxUtil.replaceImage("${icon}", imageMap);
// setComboboxV alue("paytype", "1,3,5,6");
// setComboboxV alue("makeType", "aa,vv");
wordDocxUtil.save(savePath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2,导入docx文档的操作帮助类
package com.util;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.POIXMLDocument;
import https://www.doczj.com/doc/4717880868.html,ermodel.UnderlinePatterns;
import https://www.doczj.com/doc/4717880868.html,ermodel.VerticalAlign;
import https://www.doczj.com/doc/4717880868.html,ermodel.XWPFDocument;
import https://www.doczj.com/doc/4717880868.html,ermodel.XWPFParagraph;
import https://www.doczj.com/doc/4717880868.html,ermodel.XWPFRun;
import https://www.doczj.com/doc/4717880868.html,ermodel.XWPFTable;
import https://www.doczj.com/doc/4717880868.html,ermodel.XWPFTableCell;
import https://www.doczj.com/doc/4717880868.html,ermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
/**
* @author longlin
* 注意事项:
* 1,替换的特殊文字replaceStr一定是从普通txt文本中粘贴过来的,这样才可以保证这些replaceStr的所有属性一致
* 才能保证这些replaceStr在同一个XWPFRun中。
public class WordDocxUtil {
XWPFDocument document = null;
String suffix;
public WordDocxUtil(String filePath) {
try {
String[] p = filePath.split("\\.");
// 判断文件扩展名
if (p.length > 0 && p[p.length - 1].equalsIgnoreCase("docx")) {
suffix = p[p.length - 1];
document = new XWPFDocument(POIXMLDocument.openPackage(filePath));
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 返回Docx中需要替换的特殊字符,没有重复项推荐传入正则表达式参数"\\$\\{[^{}]+\\}
* @param regex
* @return Docx中需要替换的特殊字符
*/
public ArrayList
ArrayList
// 遍历段落
Iterator
while (itPara.hasNext()) {
XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
al.addAll(getReplaceElements(regex,paragraph));
}
// 遍历表
Iterator
while (itTable.hasNext()) {
XWPFTable table = (XWPFTable) itTable.next();
int rcount = table.getNumberOfRows();
for (int i = 0; i < rcount; i++) {
XWPFTableRow row = table.getRow(i);
List
for (XWPFTableCell cell : cells) {
List
for(XWPFParagraph paragraph:paraList){
al.addAll(getReplaceElements(regex,paragraph));
}
}
}
}
return al;
}
/**
* 返回Docx中需要替换的特殊字符,没有重复项推荐传入正则表达式参数"\\$\\{[^{}]+\\}
* @param regex
* @param al
* @param paragraph
*/
private ArrayList
ArrayList
List
for (int i = 0; i < runs.size(); i++) {
XWPFRun run=runs.get(i);
String runString = run.getText(run.getTextPosition());
// System.out.println("run["+i+"]:"+runString);
if(runString!=null){
Pattern pattern = https://www.doczj.com/doc/4717880868.html,pile(regex);
Matcher matcher = pattern.matcher(runString);
while (matcher.find()) {
if (!al.contains(matcher.group())) {
al.add(matcher.group());
}
}
}
}
return al;
}
/**
* 把word文档中key替换为value
* @param map 需要替换的文字如:把${name}替换为“小明”
* @return
*/
public boolean replaceText(Map
try {
// 替换段落中的指定文字
Iterator
while (itPara.hasNext()) {
XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
replaceText(map, paragraph);
}
// 替换表格中的指定文字
Iterator
while (itTable.hasNext()) {
XWPFTable table = (XWPFTable) itTable.next();
int rcount = table.getNumberOfRows();
for (int i = 0; i < rcount; i++) {
XWPFTableRow row = table.getRow(i);
List
for (XWPFTableCell cell : cells) {
List
for(XWPFParagraph paragraph:paraList){
replaceText(map, paragraph);
}
}
}
}
return true;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
/**
* 把XWPFParagraph中key替换为value
* @param map 需要替换的文字如:把${name}替换为“小明”
* @param paragraph
*/
private void replaceText(Map
for (int i = 0; i < runs.size(); i++) {
XWPFRun run=runs.get(i);
String oneparaString = run.getText(run.getTextPosition());
if(oneparaString!=null){
for (Map.Entry
oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
}
run.setText(oneparaString,0);
}
}
}
/**
* 根据正则表达式替换字符串
* @param regex
* @param newText
* @return
*/
public boolean replaceText(String oldText,String newText) {
try {
Map
replaceMap.put(oldText, newText);
return replaceText(replaceMap);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 根据正则表达式替换字符串
* @param regex
* @param newText
* @return
*/
public boolean replaceTextByRegex(String regex,String newText) { try {
Map
List
for(String replaceEle:replaceEles){
map.put(replaceEle, newText);
}
return replaceText(map);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
*
* @param imageReplaceStr 被图片替换的文字
* @param imageMap 图片数据需要包括:
* width:图片宽
* height:图片高
* imageType:图片类型
* content:图片的具体数据(二进制数据)
* @return
*/
public boolean replaceImage(String imageReplaceStr,Map
// 替换段落中的指定文字
Iterator
while (itPara.hasNext()) {
XWPFParagraph paragraph =(XWPFParagraph)itPara.next();
replaceImage(imageReplaceStr,imageMap, paragraph);
}
// 替换表格中的指定文字
Iterator
while (itTable.hasNext()) {
XWPFTable table = (XWPFTable) itTable.next();
int rcount = table.getNumberOfRows();
for (int i = 0; i < rcount; i++) {
XWPFTableRow row = table.getRow(i);
List
for (XWPFTableCell cell : cells) {
String cellTextString = cell.getText();
if(cellTextString.indexOf(imageReplaceStr)>-1){
List
for(XWPFParagraph paragraph:paraList){
replaceImage(imageReplaceStr,imageMap, paragraph);
}
}
}
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 在XWPFParagraph中替换图片
* @param imageReplaceStr 被图片替换的文字
* @param imageMap 图片数据:
* width:图片宽
* height:图片高
* imageType:图片类型
* content:图片的具体数据(二进制数据)
* @param paragraph
* @throws Exception
*/
private void replaceImage(String imageReplaceStr,Map
List
for (int i = 0; i < runs.size(); i++) {
XWPFRun run=runs.get(i);
String oneparaString = run.getText(run.getTextPosition());
if(oneparaString!=null){
if(oneparaString.indexOf(imageReplaceStr)>-1){
//清除原有数据
Map
paragraph.removeRun(i);
//得到要添加的图片数据
int width = Integer.parseInt(imageMap.get("width").toString());
int height = Integer.parseInt(imageMap.get("height").toString());
String imageType=(String) imageMap.get("imageType");
byte[] byteArray = (byte[]) imageMap.get("content");
//向word中插入图片。注:当图片数据byteArray相同时,word插入byteArray后得到的图片ID--picId相同
int picType=getPictureType(imageType);
String picId=document.addPictureData(new ByteArrayInputStream(byteArray), picType);
System.out.println(imageReplaceStr+":picId="+picId);
//由paragraph.insertNewRun(i)可知:越先插入的越在右边
//故从右到左分析oneparaString字符串。找到noReplaceText并填充text,找到imageReplaceStr并填充image
int lastIndex=oneparaString.length(),startIndex;
int replaceKeyLength=imageReplaceStr.length();
String noReplaceText="";
while((startIndex=https://www.doczj.com/doc/4717880868.html,stIndexOf(imageReplaceStr,lastIndex-1))>-1){
noReplaceText=oneparaString.substring(startIndex+replaceKeyLength, lastIndex);
if(noReplaceText.length()>0){
run = paragraph.insertNewRun(i);
setWordXWPFRunStyle(run, oldRunStyle, noReplaceText, false);
}
run = paragraph.insertNewRun(i);
createPicture(picId, width, height, imageType, run);
lastIndex=startIndex;
}
noReplaceText=oneparaString.substring(0,lastIndex);
if(noReplaceText.length()>0){
run = paragraph.insertNewRun(i);
setWordXWPFRunStyle(run, oldRunStyle, noReplaceText, false);
}
}
}
}
}
/**
* 在XWPFRun中添加图片
* @param picId 图片id
* @param width 宽
* @param height 高
* @param paragraph 段落
*/
public void createPicture(String picId, int width, int height,String imageType,XWPFRun paraRun) {
final int EMU = 9525;
width *= EMU;
height *= EMU;
String blipId=document.getPictureDataByID(picId).getPackageRelationship().getId();
CTInline inline = paraRun.getCTR().addNewDrawing().addNewInline();
String picXml =
" uri=\"https://www.doczj.com/doc/4717880868.html,/drawingml/2006/picture\">"+ " xmlns:pic=\"https://www.doczj.com/doc/4717880868.html,/drawingml/2006/picture\">"+ " " " " ""+ ""+ " " " " ""+ " " ""+ ""+ " "
"";
inline.addNewGraphic().addNewGraphicData();
XmlToken xmlToken = null;
try {
xmlToken = XmlToken.Factory.parse(picXml);
} catch (XmlException xe) {
xe.printStackTrace();
}
inline.set(xmlToken);
inline.setDistT(0);
inline.setDistB(0);
inline.setDistL(0);
inline.setDistR(0);
CTPositiveSize2D extent = inline.addNewExtent();
extent.setCx(width);
extent.setCy(height);
CTNonVisualDrawingProps docPr = inline.addNewDocPr();
docPr.setDescr("替换图片");
}
/**
* 根据图片类型,取得对应的图片类型代码
* @param picType
* @return int
*/
private static int getPictureType(String picType) {
int res = XWPFDocument.PICTURE_TYPE_PICT;
if (picType != null) {
if (picType.equalsIgnoreCase("png")) {
res = XWPFDocument.PICTURE_TYPE_PNG;
} else if (picType.equalsIgnoreCase("dib")) {
res = XWPFDocument.PICTURE_TYPE_DIB;
} else if (picType.equalsIgnoreCase("emf")) {
res = XWPFDocument.PICTURE_TYPE_EMF;
} else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) { res = XWPFDocument.PICTURE_TYPE_JPEG;
} else if (picType.equalsIgnoreCase("wmf")) {
res = XWPFDocument.PICTURE_TYPE_WMF;
}
}
return res;
}
/**
* 得到XWPFRun的Style
* @param runOld
* @return
*/
public static Map
mapAttr.put("Color", runOld.getColor());
if (-1 == runOld.getFontSize()) {
mapAttr.put("FontSize", 12);
} else {
mapAttr.put("FontSize", runOld.getFontSize());
}
mapAttr.put("Subscript", runOld.getSubscript());
mapAttr.put("Underline", runOld.getUnderline());
mapAttr.put("FontFamily", runOld.getFontFamily());
return mapAttr;
}
/**
* 设置XWPFRunde 的style和值
* @param runNew
* @param mapAttr
* @param text
* @param flag
* @return
*/
public static XWPFRun setWordXWPFRunStyle(XWPFRun runNew, Map
runNew.setColor((String) mapAttr.get("Color"));
if ("-1".equals(mapAttr.get("FontSize").toString())) {// 处理小四字号读取为-1的问题runNew.setFontSize(12);
} else {
runNew.setFontSize((Integer) mapAttr.get("FontSize"));
}
runNew.setBold(flag);
runNew.setUnderline((UnderlinePatterns) mapAttr.get("Underline"));
runNew.setText(text);
runNew.setSubscript((VerticalAlign) mapAttr.get("Subscript"));
runNew.setFontFamily((String) mapAttr.get("FontFamily"));
return runNew;
}
/**
* 得到后缀
* @param name
* @return
*/
public static String getSuffix(String name){
return name.substring(https://www.doczj.com/doc/4717880868.html,stIndexOf(".") + 1);
}
/**
* 保存
*
* @param destPath
* 保存的路径
* @throws Exception
*/
public void save(String destPath) throws Exception {
FileOutputStream outStream = new FileOutputStream(destPath);
document.write(outStream);
outStream.close();
}
/**
* 保存
*
* @param destPath
* 保存的路径
* @throws Exception
*/
public void save(OutputStream outputStream) throws Exception { document.write(outputStream);
}
/**
* 将输入流中的数据写入字节数组
*
* @param in
* @return
*/
public static byte[] inputStream2ByteArray(InputStream in, boolean isClose) { byte[] byteArray = null;
try {
int total = in.available();
byteArray = new byte[total];
in.read(byteArray);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (isClose) {
try {
in.close();
} catch (Exception e2) {
System.out.println("关闭流失败");
}
}
}
return byteArray;
}
}