前置说明:
<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version>
</dependency>
模板文件:
image_test.docx
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;}}}