在使用poi操作docx模板文件时,总会出现需要插入类似印章签名的图片。poi直接插入图片是插入内嵌图片 这个图片是占位置的。
会撑高当前的那一行类似效果编辑
行使得制作出来的word样式辣眼睛。
一般印章签名效果要求的是 1.在指定位置插入 2.不影响原有模板内容
解决方案:
1.图片替换
实现思路:在原有模板上要插入图片的位置插入一张图片这个图片可以设置文字环绕编辑
然后docx重命名zip 查看document.xml 找到图片的rId 可以通过替换图片数据的方式实现使图片出现在你想要的位置
实现代码:
WordUtil.replaceImg(doc, signet.getBase64(), "rId8");//替换印章
public static void replaceImg(XWPFDocument document, String base64, String rid) {
ByteArrayInputStream byteArrayInputStream = getBase64Input(base64);
String ind = "";
//已经改好了不用动了。
try {
document.getPackagePart().removeRelationship(rid);//删除原有印章
ind = document.addPictureData(byteArrayInputStream,
XWPFDocument.PICTURE_TYPE_PNG);//在word插入一张没有关系的图片数据
//将新插入的图片关系替换到模板图片上,替换的只是图片数据,大小位置还是原来模板的
document.getPackagePart().addRelationship(document.getPackagePart().
getRelationship(ind).getTargetURI(), TargetMode.INTERNAL,
XWPFRelation.IMAGES.getRelation(), rid);
} catch (InvalidFormatException e) {
e.printStackTrace();
throw new BizException("替换图片失败");
}
}
复制代码
缺陷:替换后的图片大小是你模板的图片大小一致,也就是说当你模板的图片和你替换的图片不一大小时,你替换后的结果图片大小是模板图片大小。会出现签名图片不一样大的情况。
2.操作xml实现图片定位
实现思路:在指定位置插入一张行内图片,拿到这种图片对象,给图片设置anchor 锚的属性。
编辑
编辑
可以看到图片的定位属性就两种 行内和锚
添加后删除原来的行内关系inline
实现代码:
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import java.io.*;
/**
* created by ldl 2018/12/12
*/
public class Test3 {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
document.createParagraph().createRun().setText("测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试");
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
// 设置图片
run.setText("测试图片: ");
// 添加浮动图片
run = paragraph.createRun();
InputStream in = new FileInputStream("C:\Users\hasee\Desktop\word\下载.png");
run.addPicture(in, Document.PICTURE_TYPE_PNG, "TEST", Units.toEMU(100), Units.toEMU(30));
in.close();
// 2. 获取到图片数据
CTDrawing drawing = run.getCTR().getDrawingArray(0);
CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();
//拿到新插入的图片替换添加CTAnchor 设置浮动属性 删除inline属性
CTAnchor anchor = getAnchorWithGraphic(graphicalobject, "TEST1",
Units.toEMU(100), Units.toEMU(30),//图片大小
Units.toEMU(50), Units.toEMU(0), false);//相对当前段落位置 需要计算段落已有内容的左偏移
drawing.setAnchorArray(new CTAnchor[]{anchor});//添加浮动属性
drawing.removeInline(0);//删除行内属性
run.setText("测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试");
document.write(new FileOutputStream("C:\Users\hasee\Desktop\word\WordInsertPictures1.docx"));
document.close();
}
/**
* @param ctGraphicalObject 图片数据
* @param deskFileName 图片描述
* @param width 宽
* @param height 高
* @param leftOffset 水平偏移 left
* @param topOffset 垂直偏移 top
* @param behind 文字上方,文字下方
* @return
* @throws Exception
*/
public static CTAnchor getAnchorWithGraphic(CTGraphicalObject ctGraphicalObject,
String deskFileName, int width, int height,
int leftOffset, int topOffset, boolean behind) {
String anchorXML =
"<wp:anchor xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" "
+ "simplePos="0" relativeHeight="0" behindDoc="" + ((behind) ? 1 : 0) + "" locked="0" layoutInCell="1" allowOverlap="1">"
+ "<wp:simplePos x="0" y="0"/>"
+ "<wp:positionH relativeFrom="column">"
+ "<wp:posOffset>" + leftOffset + "</wp:posOffset>"
+ "</wp:positionH>"
+ "<wp:positionV relativeFrom="paragraph">"
+ "<wp:posOffset>" + topOffset + "</wp:posOffset>" +
"</wp:positionV>"
+ "<wp:extent cx="" + width + "" cy="" + height + ""/>"
+ "<wp:effectExtent l="0" t="0" r="0" b="0"/>"
+ "<wp:wrapNone/>"
+ "<wp:docPr id="1" name="Drawing 0" descr="" + deskFileName + ""/><wp:cNvGraphicFramePr/>"
+ "</wp:anchor>";
CTDrawing drawing = null;
try {
drawing = CTDrawing.Factory.parse(anchorXML);
} catch (XmlException e) {
e.printStackTrace();
}
CTAnchor anchor = drawing.getAnchorArray(0);
anchor.setGraphic(ctGraphicalObject);
return anchor;
}
}
复制代码
编辑
实现效果 可以通过微调位置来达到你最终想要的结果
缺陷:当有多张签名的时候需要计算位置,插入位置是从插入位置段落开始算起
欢迎交流在指定位置插入多张张图片的方案