【Poi-tl Documentation】自定义占位符来设置图片大小

前置说明:

<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version>
</dependency>

模板文件:
image_test.docx

image.png

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;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2868792.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Internet协议的安全性

Internet协议的安全性 文章目录 Internet协议的安全性1. 网络层1. IP*62. ARP*33. ICMP * 3 2. 传输层协议1. TCP1. * SYN-Flood攻击攻击检测* 防御 2. TCP序号攻击攻击 3. 拥塞机制攻击 2. UDP 3. 应用层协议1. DNS攻击*3防范*3: 2. FTP3. TELNET: 改用ssh4. 电子邮件1. 攻击2…

set与zset数据类型

set类型基础 redis集合(set)类型和list列表类型类似&#xff0c;都可以用来存储多个字符串元素的 集合。但是和list不同的是set集合当中不允许重复的元素。而且set集合当中元素是没有顺序的&#xff0c;不存在元素下标。 redis的set类型是使用哈希表构造的&#xff0c;因此复…

每日OJ题_简单多问题dp⑥_力扣714. 买卖股票的最佳时机含手续费

目录 力扣714. 买卖股票的最佳时机含手续费 状态机分析 解析代码 力扣714. 买卖股票的最佳时机含手续费 714. 买卖股票的最佳时机含手续费 难度 中等 给定一个整数数组 prices&#xff0c;其中 prices[i]表示第 i 天的股票价格 &#xff1b;整数 fee 代表了交易股票的手续…

Linux远程连接本地数据库(docker)

1. 安装docker 参考上一篇文章 CentOS安装Docker 2. Linux中安装Mysql 2.1 docker拉取mysql镜像 拉取镜像 docker pull mysql查看镜像列表 docker images2.2 运行mysql容器 运行一个名字为mysql的mysql容器&#xff0c;其连接端口号为3306&#xff0c;密码为123456 docker r…

口腔管理平台 |基于springboot框架+ Mysql+Java+B/S结构的口腔管理平台 设计与实现(可运行源码+数据库+lw文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 会员功能 系统功能设计 数据库E-R图设计 lunwen参考…

RT-Thread之USB组件的使用记录(SD卡和USB同时挂载)

前言 使用usb-host组件读取u盘记录同时挂载sd和u盘用到的芯片为stm32f407zgt6u盘的格式为fat 组件选择 文件相关的宏定义 /* DFS: device virtual file system */ /* 设备虚拟文件系统 */ #define RT_USING_DFS #define DFS_USING_WORKDIR #define DFS_FILESYSTEMS_MAX 3 //…

Pikachu 靶场搭建

文章目录 环境说明1 Pikachu 简介2 Pikachu 安装 环境说明 操作系统&#xff1a;Windows 10PHPStudy 版本: 8.1.1.3Apache 版本&#xff1a;2.4.39MySQL 版本 5.7.26 1 Pikachu 简介 Pikachu是一个使用“PHP MySQL” 开发、包含常见的Web安全漏洞、适合Web渗透测试学习人员练…

印度交易所股票行情数据API接口

1. 历史日线 # Restful API https://tsanghi.com/api/fin/stock/XNSE/daily?token{token}&ticker{ticker}默认返回全部历史数据&#xff0c;也可以使用参数start_date和end_date选择特定时间段。 更新时间&#xff1a;收盘后3~4小时。 更新周期&#xff1a;每天。 请求方式…

python二级备考(3)-综合应用

1 《命运》是著名科幻作家倪匡的作品。这里给出《命运》的一个网络版本文件&#xff0c;文件名为“命运. txt”。 问题1 (5分) :在PY301-1. py文件中修改代码&#xff0c;对“命运. txt”文件进行字符频次统计&#xff0c;输出频次最高的中文字符(不包含标点符号)及其频次&…

初学者必看的python中类型转换

Python中常见的类型转换 int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 complex(real [,imag ]) 创建一个复数 str(x ) 将对象 x 转换为字符串 repr(x ) 将对象 x 转换为表达式字符串 eval(str ) 用来计算在字符串中…

05-延迟任务精准发布文章-黑马头条

延迟任务精准发布文章 1)文章定时发布 2)延迟任务概述 2.1)什么是延迟任务 定时任务&#xff1a;有固定周期的&#xff0c;有明确的触发时间延迟队列&#xff1a;没有固定的开始时间&#xff0c;它常常是由一个事件触发的&#xff0c;而在这个事件触发之后的一段时间内触发…

Docker----Dockerfile构建微服务镜像

目录 一、关键步骤 二、具体步骤 1、准备后端jar包(这里以java后端演示) 2、编写Dockerfile 3、构建镜像 4、运行镜像容器 5、测试是否成功 一、关键步骤 1、准备后端jar包(这里以java后端演示) 2、编写Dockerfile 3、构建镜像 4、运行镜像容器 5、测试是否成功 二…

软件工程(Software Engineering)

一、软件工程概述 1.软件生存周期 软件&#xff1a; 包含程序、数据及相关文档 软件工程&#xff1a; 涉及到软件开发、维护、管理等多方面的原理、工具与环境。最终的目的是开发高质量的软件。 目的&#xff1a; 提高软件生产率、提高软件质量、降低软件成本。 文档的作用&…

2024 Mazing 3 中文版新功能介绍Windows and macOS

iMazing 3中文版(ios设备管理软件)是一款管理苹果设备的软件&#xff0c; Windows 平台上的一款帮助用户管理 IOS 手机的应用程序。iMazing中文版与苹果设备连接后&#xff0c;可以轻松传输文件&#xff0c;浏览保存信息等&#xff0c;软件功能非常强大&#xff0c;界面简洁明晰…

力扣965单值二叉树的小细节

这一段的两个判断条件&#xff0c;一定要root->left!NULL在前 如果root->val!root->left->val在前&#xff0c;root->left为空的时候&#xff0c;就无法拿出root->left->val&#xff0c;在一个NULL的指针里拿不出val。 把root->left!NULL放在前面&am…

文才与口才:谁才是成功的关键因素?

文才与口才&#xff1a;谁才是成功的关键因素&#xff1f; 自古以来&#xff0c;文才与口才一直是人们关注的重要议题。在追求成功的道路上&#xff0c;文才与口才究竟谁才是关键因素&#xff1f;这是一个值得深入探讨的问题。本文将从多个维度出发&#xff0c;分析文才与口才…

01背包 与 emo题目背景(周超人的遗憾) 的爱恨情仇

本题背景有意思&#xff0c;大家当乐子看&#xff0c;目前没有找到题目原题&#xff0c;也没有写过完全是01背包模板的题目&#xff0c;该篇文章大家注意其01背包一维写法的模板就好&#xff0c;注意各个关键点 ✨欢迎来到脑子不好的小菜鸟的文章✨ &#x1f388;创作不易&…

力扣L13--- 409.最长回文串(JAVA版)-2024年3月1日

1.题目描述 2.知识点 注1&#xff1a;向下取整是将一个数值向下舍入到最接近的整数&#xff0c;但不超过这个数值的整数。具体规则如下&#xff1a; 对于正数&#xff0c;向下取整后得到的整数是不大于原数值的最大整数&#xff1b; 对于负数&#xff0c;向下取整后得到的整数…

Java手写简易数据库--持续更新中

MYDB 0. 项目结构0.1 引用计数缓存框架为什么不使用LRU引用计数缓存缓存框架实现 0.2 共享内存数组 1. 事务管理器--TM1.1 XID 文件XID 规则XID 文件结构读取方式事务状态 1.2 代码实现 2. 数据管理器--DM2.1 页面缓存页面结构页面缓存数据页管理第一页普通页 2.2 日志文件 3. …

一文搞懂PCL中自定义点云类型的构建与函数使用

上周猛男快乐开发时遇到个bug&#xff0c;要用pcl的函数对自定义的点云进行处理。一起解决问题时遇到了很多问题&#xff0c;解决后整理出来分享给各位参考&#xff0c;以免踩一样的坑&#x1f60a;。文章中自定义的点我用PointT来表示&#xff0c;自定义点云一般指的是pcl::Po…