前置说明:
yaml
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.1</version>
</dependency>
模板文件:
image_test.docx
java
package run.siyuan.poi.tl.policy;
import cn.hutool.core.util.ReUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.converter.ObjectToPictureRenderDataConverter;
import com.deepoove.poi.converter.ToRenderDataConverter;
import com.deepoove.poi.data.Paragraphs;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.style.PictureStyle;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.BufferedImageUtils;
import com.deepoove.poi.util.RegexUtils;
import com.deepoove.poi.util.SVGConvertor;
import com.deepoove.poi.util.UnitUtils;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.WidthScalePattern;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Pattern;
/**
* @ClassName CustomPictureRenderPolicy
* @Description TODO
* @Author siyuan
* @Date 2024/3/3 12:53
*/
public class CustomPictureRenderPolicy extends PictureRenderPolicy {
public static void main(String[] args) throws IOException {
// 读取模板文件
FileInputStream fileInputStream = new FileInputStream("/Users/wuzhiqian/Desktop/HY/image_test.docx");
// 创建模板配置
ConfigureBuilder configureBuilder = Configure.builder();
// configureBuilder.buildGrammerRegex(RegexUtils.createGeneral("{{", "}}"));
// configureBuilder.buildGrammerRegex("((%)?[\\w\\u4e00-\\u9fa5]+(\\.[\\w\\u4e00-\\u9fa5]+)*(\\[\\d,\\d\\])?)?");
configureBuilder.setValidErrorHandler(new Configure.DiscardHandler());
configureBuilder.addPlugin('%', new CustomPictureRenderPolicy());
// 创建模板上下文
Map<String, Object> context = new HashMap<>();
context.put("aaaa", Pictures.ofStream(Files.newInputStream(Paths.get("/Users/wuzhiqian/Desktop/HY/11111.png"))).create());
context.put("name2", Pictures.ofStream(Files.newInputStream(Paths.get("/Users/wuzhiqian/Desktop/HY/11111.png"))).create());
// 使用模板引擎替换文本标签
XWPFTemplate compile = XWPFTemplate.compile(fileInputStream, configureBuilder.build());
compile.render(context);
// 保存生成的文档
FileOutputStream outputStream = new FileOutputStream("/Users/wuzhiqian/Desktop/HY/image_test" + System.currentTimeMillis() + ".docx");
compile.write(outputStream);
outputStream.close();
compile.close();
fileInputStream.close();
}
private static ToRenderDataConverter<Object, PictureRenderData> converter = new ObjectToPictureRenderDataConverter();
public CustomPictureRenderPolicy() {
}
public PictureRenderData cast(Object source) throws Exception {
return (PictureRenderData)converter.convert(source);
}
protected boolean validate(PictureRenderData data) {
return null != data;
}
protected void afterRender(RenderContext<PictureRenderData> context) {
this.clearPlaceholder(context, false);
}
protected void reThrowException(RenderContext<PictureRenderData> context, Exception e) {
this.logger.info("Render picture " + context.getEleTemplate() + " error: {}", e.getMessage());
String alt = ((PictureRenderData)context.getData()).getAltMeta();
context.getRun().setText(alt, 0);
}
public void beforeRender(RenderContext<PictureRenderData> context) {
System.out.println("================");
XWPFRun run = context.getRun();
String source = context.getEleTemplate().getSource();
String tagName = context.getEleTemplate().getTagName();
System.out.println(source);
Pattern pattern = Pattern.compile( "(.*)\\{\\{%"+tagName+"}}\\[\\d+,\\d+](.*)");
XWPFParagraph parent = (XWPFParagraph) run.getParent();
IBody body = parent.getBody();
for (XWPFParagraph paragraph : body.getParagraphs()) {
String text = paragraph.getText();
System.out.println(text + "-------------------------------");
if (text.contains(source) && ReUtil.isMatch(pattern,text) ) {
String s = ReUtil.get("\\{\\{%"+tagName+"}}\\[\\d+,\\d+]", text, 0);
System.out.println(s);
s = ReUtil.get("\\[\\d+,\\d+]", s, 0);
System.out.println(s);
String[] split = s.replace("[", "").replace("]", "").split(",");
Integer w = Integer.valueOf(split[0]);
Integer h = Integer.valueOf(split[1]);
PictureStyle pictureStyle = new PictureStyle();
pictureStyle.setWidth(w);
pictureStyle.setHeight(h);
context.getData().setPictureStyle(pictureStyle);
for (XWPFRun xwpfRun : paragraph.getRuns()) {
if (s.equals(xwpfRun.text())){
System.out.println(xwpfRun.text()+" clean");
// 删除[200,214] 格式字符
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(xwpfRun);
bodyContainer.clearPlaceholder(xwpfRun);
}
}
}
}
}
public void doRender(RenderContext<PictureRenderData> context) throws Exception {
CustomPictureRenderPolicy.Helper.renderPicture(context.getRun(), (PictureRenderData) context.getData());
}
public static class Helper {
public Helper() {
}
public static void renderPicture(XWPFRun run, PictureRenderData picture) throws Exception {
byte[] imageBytes = picture.readPictureData();
if (null == imageBytes) {
throw new IllegalStateException("Can't read picture byte arrays!");
} else {
// 根据图片流 设置图片类型
PictureType pictureType = picture.getPictureType();
if (null == pictureType) {
pictureType = PictureType.suggestFileType(imageBytes);
}
// 图片类型为空,报错
if (null == pictureType) {
throw new RenderException("PictureRenderData must set picture type!");
} else {
PictureStyle style = picture.getPictureStyle();
if (null == style) {
style = new PictureStyle();
}
int width = style.getWidth();
int height = style.getHeight();
if (pictureType == PictureType.SVG) {
imageBytes = SVGConvertor.toPng(imageBytes, (float) width, (float) height);
pictureType = PictureType.PNG;
}
if (!isSetSize(style)) {
BufferedImage original = BufferedImageUtils.readBufferedImage(imageBytes);
width = original.getWidth();
height = original.getHeight();
if (style.getScalePattern() == WidthScalePattern.FIT) {
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
int pageWidth = UnitUtils.twips2Pixel(bodyContainer.elementPageWidth((IBodyElement) run.getParent()));
if (width > pageWidth) {
double ratio = (double) pageWidth / (double) width;
width = pageWidth;
height = (int) ((double) height * ratio);
}
}
}
InputStream stream = new ByteArrayInputStream(imageBytes);
try {
PictureStyle.PictureAlign align = style.getAlign();
if (null != align && run.getParent() instanceof XWPFParagraph) {
((XWPFParagraph) run.getParent()).setAlignment(ParagraphAlignment.valueOf(align.ordinal() + 1));
}
run.addPicture(stream, pictureType.type(), "Generated", Units.pixelToEMU(width), Units.pixelToEMU(height));
} catch (Throwable var13) {
try {
stream.close();
} catch (Throwable var12) {
var13.addSuppressed(var12);
}
throw var13;
}
stream.close();
}
}
}
private static boolean isSetSize(PictureStyle style) {
return (style.getWidth() != 0 || style.getHeight() != 0) && style.getScalePattern() == WidthScalePattern.NONE;
}
}
}