以前写过用asposeword 替换文字和图片,但是后来遇到问题,有些word替换替换图片后会导致打开时弹出错误:此文件中检测到错误,单word可以通过进行一下修复来打开文件。
考虑可能是版本有bug,于是从官网下了最新的20.7版本。
新版替换字符为图片的方法有些不一样
使用方法:
package xf.test;
import com.aspose.words.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class TestAspose {
public static void main(String[] args) {
try {
//doc 和docx 都是可以的
Map<String,String>pmap = new HashMap<String,String>();
pmap.put("[编写签名区域]","$pic:D:/javatest/sign2.png");
pmap.put("$编号$","BH12345");
//replace("D:/javatest/test删除图片.doc","D:/javatest/aspose测试删除图片.doc",pmap);
// replace("D:/javatest/田清单A8.docx","D:/javatest/aspose测试删除图片.docx",pmap);
replace("D:/javatest/aspose测试删除图片.docx","D:/javatest/aspose测试删除图片2.docx",pmap);
}catch (Exception e){
e.printStackTrace();
}
}
public static boolean replace(String path, String outPath, Map<String,String> paramMap){
if(path == null || path.isEmpty()) return false;
if(outPath == null || outPath.isEmpty()) return false;
if(paramMap == null || paramMap.isEmpty()) return false;
try {
Document doc = new Document(path);
Iterator<String> paramKey = paramMap.keySet().iterator();
while(paramKey.hasNext()){
String key = paramKey.next();
String v = paramMap.get(key);
if(v.startsWith("$pic:")){
v = v.substring(5);
//如果key已经被替换成图片了,那就要将图片替换成新的图片,相当于重新插入图片
NodeCollection shapeCollection = doc.getChildNodes(NodeType.SHAPE, true);
Iterator<Shape> shapeIterate = shapeCollection.iterator();
java.util.List<Shape> shaplist = new ArrayList<Shape>();
while(shapeIterate.hasNext()){
Shape shape = shapeIterate.next();
if(key.equals(shape.getName())){
shaplist.add(shape);
}
}
DocumentBuilder builder = new DocumentBuilder(doc);
for(int i=0;i<shaplist.size();i++){
Shape shape = shaplist.get(i);
//将光标移动到指定节点
builder.moveTo(shape);
Shape img = builder.insertImage(v);
img.setName(key);
System.out.println("replace" +key);
shape.remove();
}
//替换文字为图片
doc.getRange().replace(key, "", new FindReplaceOptions(new ReplaceAndInsertImage(v,key)));
}else{
doc.getRange().replace(key,v);
}
}
doc.save(outPath);
}catch (Exception e){
e.printStackTrace();
return false;
}
return true;
}
}
class ReplaceAndInsertImage implements IReplacingCallback {
private String url;
private String name;
public ReplaceAndInsertImage(String url,String name){
this.url = url;
this.name = name;
}
@Override
public int replacing(ReplacingArgs e) throws Exception {
//获取当前节点
Node currentNode = e.getMatchNode();
//节点拆分处理当前匹配字段
splitRun(currentNode,e.getMatchOffset());
//获取当前文档
Document document = (Document) currentNode.getDocument();
DocumentBuilder builder = new DocumentBuilder(document);
//将光标移动到指定节点
builder.moveTo(currentNode);
//插入图片
Shape img = builder.insertImage(url);
img.setName(name);
return ReplaceAction.SKIP;
}
private void splitRun(Node currentNode ,int position){
String text = currentNode.getText();
Node newNode = currentNode.deepClone(true);
if(text.length() >= position+this.name.length()){
((Run)currentNode).setText (text.substring(position+this.name.length()));
}else{
int morlength = position+this.name.length() - text.length();
((Run)currentNode).setText ("");
Node tmpnode = currentNode;
for(int i=0;i<this.name.length();i++){
System.out.println(i);
tmpnode = tmpnode.getNextSibling();
String tmptext= tmpnode.getText();
System.out.println(tmptext);
System.out.println(morlength);
System.out.println("--------"+(tmptext.length() >= morlength));
if(tmptext.length() >= morlength){
((Run)tmpnode).setText(tmptext.substring(morlength));
break;
}else{
morlength = morlength - tmptext.length();
((Run)tmpnode).setText("");
}
}
}
if(position>0){
((Run)newNode).setText(text.substring(0, position));
currentNode.getParentNode().insertBefore(newNode, currentNode);
}
}
}
20200813更新:原方法处理doc时存在bug,替换占位符为图片后,图片不是在占位符所在的位置,而是在占位符所在的node的起始位置,增加splitRun方法分割node节点。