当前位置: 首页 > news >正文

poi生成的ppt,powerPoint打开提示内容错误解决方案

poi生成的ppt,powerPoint打开提示内容错误解决方案

最近做了ppt的生成,使用poi制作ppt,出现一个问题。微软的powerPoint打不开,提示错误信息

在这里插入图片描述

通过xml对比工具发现只需要删除幻灯片的某些标签即可解决。

用的是XML Notepand
在这里插入图片描述

分析思路:

1.把poi生成的pptx用wps打开,正常,但是poi生成的pptx在powerPoint打不开。尝试用wps另存一份,ok,wps另存后的ppt,powerPoint可以打开了。然后ppt的大小也有了变化,肯定是wps对这个ppt做了一些格式化操作。具体是啥呢,不清楚,只能用这个 XML Notepand 对比看看吧。
2. ppt本质上是xml的压缩包集合。我们对ppt进行解压。

在这里插入图片描述

3.里面的东西挺多了,我自己也不怎么懂,但是我想既然是ppt的某个幻灯片打不开,那我就对比一下能幻灯片,看看poi生成的ppt和wps另存后的ppt的幻灯片有哪些区别。

我们进入这个目录
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

4.这个就是放置幻灯片的位置。

我们通过这个XML Notepand 进行一个对比观察,
在这里插入图片描述
我们先用xml notePand打开poi生成的一个幻灯片,我打开的是wsp另存的解压后的第4个幻灯片,ppt\slides\slide4.xml
在这里插入图片描述

在这里插入图片描述

然后选择这个,再次选择一个poi生成的ppt,选择同一个幻灯片,进行一个对比
在这里插入图片描述
然后进行两个文件对比
在这里插入图片描述

最后对比发现这个标签可能不可以被powerPoint正确识别,我们就把这个标签删除

在这里插入图片描述

<p:custDataLst><p:tags r:id="rId1"/>
</p:custDataLst>

最关键的来了,直接上代码

package com.ruoyi.ppt.utilsService;import com.ruoyi.ppt.aopCustom.customAnnotations.LogExecutionTime;
import com.ruoyi.ppt.config.ThreadPoolDealTask;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.w3c.dom.*;import javax.annotation.Resource;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;@Slf4j
@Component
public class PptXmlFormate {@Resourceprivate ThreadPoolDealTask threadPoolDealTask;@LogExecutionTime("PPT XML标签调整耗时")public void xmlFormate(String pptxFilePath, String useFont) {useFont = StringUtils.isBlank(useFont) ? "宋体" : useFont;// 使用 try-with-resources 自动关闭临时文件和 Zip 流try {// 创建临时文件来存储更新后的 PPTX 文件File tempFile = File.createTempFile("pptx_temp" + UUID.randomUUID(), ".zip");tempFile.deleteOnExit();// 读取 PPTX 文件并更新 XMLtry (FileInputStream fis = new FileInputStream(pptxFilePath);ZipInputStream zis = new ZipInputStream(fis);FileOutputStream fos = new FileOutputStream(tempFile);ZipOutputStream zos = new ZipOutputStream(fos)) {ZipEntry entry;Map<String, ByteArrayOutputStream> updatedFiles = new HashMap<>();// 遍历 PPTX 文件中的每个条目while ((entry = zis.getNextEntry()) != null) {String entryName = entry.getName();ByteArrayOutputStream entryData = new ByteArrayOutputStream();// 读取条目内容byte[] buffer = new byte[1024];int len;while ((len = zis.read(buffer)) > 0) {entryData.write(buffer, 0, len);}// 仅处理幻灯片 XML 文件if (entryName.startsWith("ppt/slides/slide") && entryName.endsWith(".xml")) {// 解析 XMLtry (ByteArrayInputStream bais = new ByteArrayInputStream(entryData.toByteArray());ByteArrayOutputStream updatedXml = new ByteArrayOutputStream()) {DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();factory.setNamespaceAware(true);DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(bais);// 异步任务,并确保异常捕获CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {// 删除标签String custDataLstXpath = "//*[local-name()='custDataLst']";removeNodesUsingXPath(document, custDataLstXpath);}, threadPoolDealTask.getThreadPoolExecutor());// 捕获并处理异步任务中的异常future.exceptionally(ex -> {log.error("处理 XML 异步任务时发生错误: {}", ex.getMessage(), ex);return null;}).join(); // 等待任务完成// 写入修改后的 XML 内容TransformerFactory transformerFactory = TransformerFactory.newInstance();Transformer transformer = transformerFactory.newTransformer();transformer.setOutputProperty(OutputKeys.INDENT, "yes");DOMSource source = new DOMSource(document);StreamResult result = new StreamResult(updatedXml);transformer.transform(source, result);updatedFiles.put(entryName, updatedXml);}} else {// 对于其他条目,保持原样updatedFiles.put(entryName, entryData);}}// 写入更新后的 PPTX 文件for (Map.Entry<String, ByteArrayOutputStream> fileEntry : updatedFiles.entrySet()) {String entryName = fileEntry.getKey();ByteArrayOutputStream fileData = fileEntry.getValue();zos.putNextEntry(new ZipEntry(entryName));fileData.writeTo(zos);zos.closeEntry();}zos.finish();}// 将临时文件移动到原始 PPTX 文件路径,替换原文件Files.move(tempFile.toPath(), new File(pptxFilePath).toPath(), StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {log.error("处理文件时发生 IO 错误: {}", e.getMessage(), e);} catch (Exception e) {log.error("处理过程中发生错误: {}", e.getMessage(), e);}}public void removeNodesUsingXPath(Document document, String xpathExpression) {XPath xPath = XPathFactory.newInstance().newXPath();// 设置命名空间前缀和 URINamespaceContext nsContext = new NamespaceContext() {public String getNamespaceURI(String prefix) {switch (prefix) {case "a":return "http://schemas.openxmlformats.org/drawingml/2006/main";case "p":return "http://schemas.openxmlformats.org/presentationml/2006/main";default:return XMLConstants.NULL_NS_URI;}}public String getPrefix(String namespaceURI) {return null;}public Iterator getPrefixes(String namespaceURI) {return null;}};xPath.setNamespaceContext(nsContext);try {NodeList nodes = (NodeList) xPath.evaluate(xpathExpression, document, XPathConstants.NODESET);for (int i = nodes.getLength() - 1; i >= 0; i--) { // 从后向前遍历Node node = nodes.item(i);Node parentNode = node.getParentNode();if (parentNode != null) {parentNode.removeChild(node);}}} catch (Exception e) {log.error("Error removing nodes using XPath: {}", e.getMessage());}}}

注意哈,这里使用了线程池,不需要的可以删除,需要的话不会配置的,这里也给出代码

package com.ruoyi.ppt.config;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;import javax.annotation.Resource;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;@Slf4j
@Configuration
@Data
public class ThreadPoolDealTask {private volatile ThreadPoolExecutor threadPool;// 自定义 ThreadFactory,为线程池中的线程指定名称private ThreadFactory createThreadFactory(String poolName) {AtomicInteger counter = new AtomicInteger(0);return r -> {Thread thread = new Thread(r);thread.setName(poolName + "-thread-" + counter.incrementAndGet());return thread;};}// 懒加载线程池,只有在第一次使用时才会创建 用于 业务处理public void initializeThreadPool() {if (this.threadPool == null) {synchronized (this) {if (this.threadPool == null) { // 双重检查锁定this.threadPool = new ThreadPoolExecutor(2,10,30L,TimeUnit.SECONDS,new LinkedBlockingQueue<>(50),createThreadFactory("CustomThreadPool"), // 使用自定义的 ThreadFactorynew ThreadPoolExecutor.CallerRunsPolicy());// 启用核心线程超时this.threadPool.allowCoreThreadTimeOut(false);}}}}public ThreadPoolExecutor getThreadPoolExecutor() {return this.threadPool;}// 输出任务队列状态private void printQueueStatus() {if (threadPool instanceof ThreadPoolExecutor) {ThreadPoolExecutor executor = (ThreadPoolExecutor) threadPool;System.out.println("Submitting task to thread: " + Thread.currentThread().getName());System.out.println("当前任务队列大小: " + executor.getQueue().size());System.out.println("当前任务队列大小: " + executor.getQueue().size());System.out.println("当前活动线程数: " + executor.getActiveCount());System.out.println("当前线程池大小: " + executor.getPoolSize());}}// 提交任务并返回Future对象public <T> Future<T> submitTask(Callable<T> task) {initializeThreadPool(); // 确保线程池已初始化return threadPool.submit(task);}// 提交Runnable任务并返回Futurepublic Future<?> submitTask(Runnable task) {initializeThreadPool(); // 确保线程池已初始化return threadPool.submit(task);}// 优雅地关闭线程池public void shutdown() {if (threadPool != null) {threadPool.shutdown();try {// 等待现有任务执行完毕if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {threadPool.shutdownNow(); // 强制关闭// 等待任务响应中断if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {System.err.println("线程池未能在指定时间内关闭");}}} catch (InterruptedException ie) {// 在当前线程被中断时,也强制关闭线程池threadPool.shutdownNow();// 保留中断状态Thread.currentThread().interrupt();} finally {threadPool = null; // 关闭后将线程池引用置为空}}}}

现在解决了xml的标签问题,

最后只需要生成后的ppt地址,传入这个方法,执行一次标签删除即可

处理前效果:
在这里插入图片描述

处理后效果:
在这里插入图片描述

相关文章:

poi生成的ppt,powerPoint打开提示内容错误解决方案

poi生成的ppt&#xff0c;powerPoint打开提示内容错误解决方案 最近做了ppt的生成&#xff0c;使用poi制作ppt&#xff0c;出现一个问题。微软的powerPoint打不开&#xff0c;提示错误信息 通过xml对比工具发现只需要删除幻灯片的某些标签即可解决。 用的是XML Notepand 分…...

基于stm32物联网身体健康检测系统

在当今社会&#xff0c;由于经济的发展带来了人们生活水平不断提高&#xff0c;但是人们的健康问题却越来越突出了&#xff0c;各种各样的亚健康随处可在&#xff0c;失眠、抑郁、焦虑症&#xff0c;高血压、高血糖等等侵袭着人们的健康&#xff0c;人们对健康的关注达到了一个…...

BeautifulSoup4在爬虫中的使用

一、Beautiful Soup4简介 Beautiful Soup 提供一些简单的python函数来处理导航、搜索等功能。 它是一个工具箱&#xff0c;是python的一个库&#xff0c;最主要的功能是从网页获取数据。 二、Beautiful Soup4安装 在cmd下安装 pip install beautifulsoup4三、BeautifulSou…...

Laya2.x出包alipay小游戏

小游戏开发者工具&#xff0c;支付宝官方已经出了&#xff0c;不说了。 1.LAYA2.X打出得小游戏包中my-adapter.js这个文件需要替换&#xff0c;或者自行修改&#xff0c;替换3.x得&#xff1b; 2.unity导包出得模型文件命名需要注意&#xff0c;避免太长&#xff0c;路径也不…...

Vue极简入门

1.注册路由&#xff0c;如果是子路由&#xff0c;就加一个children import Vue from vue import Router from vue-router import Main from ../views/Main.vue import Login from ../views/Login.vueimport UserProfile from "../views/user/Profile.vue" import Us…...

系统敏感信息搜索工具(支持Windows、Linux)

目录 工具介绍 使用说明 search模块 browser模块 下载地址 工具介绍 可以快速搜索服务器中的有关username,passsword,账号,口令的敏感信息还有浏览器的账户密码。 使用说明 search模块 searchall64.exe search -p 指定路径 searchall64.exe search -p 指定路径 -s &q…...

Fyne ( go跨平台GUI )中文文档-容器和布局 (四)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…...

文心智能体 恐怖类游戏

智能体名称&#xff1a;孤岛惊魂 链接&#xff1a;文心智能体平台AgentBuilder | 想象即现实 (baidu.com)https://agents.baidu.com/center/agent/preview/MFhBvA0K9EXXVdjHCcUumadWmWesKvw2 角色与目标设定 &#x1f9d1;&#x1f3fb; 角色&#xff1a;孤岛惊魂是一位虚拟…...

智慧城市运营模式--政府和社会资本合作

1、主要特征 政府和社会资本合作模式是政府与社会资本长期合作提供公共产品和服务的一种创新模式,主要集中在纯公共领域和准公共领域,通过建立“利益共享、风险共担”的长期合作伙伴关系,在增加公共产品和服务供给数量和提升质量的同时,达到减少财政资金支出、降低企业投资…...

【Python报错已解决】ValueError: cannot convert float NaN to integer

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…...

ClickHouse 与 Quickwit 集成实现高效查询

1. 概述 在当今大数据分析领域&#xff0c;ClickHouse 作为一款高性能的列式数据库&#xff0c;以其出色的查询速度和对大规模数据的处理能力&#xff0c;广泛应用于在线分析处理 (OLAP) 场景。ClickHouse 的列式存储和并行计算能力使得它在处理结构化数据查询时极具优势&…...

Facebook Marketplace无法使用的原因及解决方案

Facebook Marketplace是一项广受欢迎的买卖平台&#xff0c;然而&#xff0c;有时候用户可能会遇到无法访问或使用该功能的问题。通常&#xff0c;这些问题可以归结为以下几类原因&#xff1a; 地理位置限制&#xff1a; Facebook Marketplace并非在全球每个地区都可用。在某些…...

uboot — uboot命令的使用

uboot的命令繁多&#xff0c;下文只对工作中常用到的命令进行记录&#xff0c;其余命令待用到时再查查资料也不迟 一、环境变量操作命令 1、printenv 打印环境变量 2、setenv 修改环境变量/新建环境变量 3、saveenv 保存环境变量/删除环境变量&#xff08;给环境变量赋空值…...

基础漏洞——SSRF

目录 一.原理 二.引起ssrf的函数 三.这些函数具体作用 &#xff08;1&#xff09;File_get_content() &#xff08;2&#xff09;Fsockopen() &#xff08;3&#xff09;Curl_exec() 四.常见的业务场景&#xff08;可能出现的漏洞的地方&#xff0c;漏洞挖掘&#xff09…...

报错解决方案

大模型-报错解决方案 百度千帆大模型 仅个人笔记使用&#xff0c;感谢点赞关注 百度千帆大模型 未开通付费模型 qianfan.errors.APIError: api return error, req_id: code: 17, msg: Open api daily request limit reached 可能的原因: 未开通所调用服务的付费权限&#xff0…...

机器人的动力学——牛顿欧拉,拉格朗日,凯恩

机器人的动力学推导方法有很多&#xff0c;常用得有牛顿&#xff0c;拉格朗日&#xff0c;凯恩等方法&#xff0c;接下来&#xff0c;简单说说他们之间的使用。注&#xff1a;这里不考虑怎么来的&#xff0c;只说怎么应用。 参考1&#xff1a;4-14动力学分析方法-牛顿—欧拉方…...

【AI写作】解释区块链技术的应用场景和优势

【AI写作】解释区块链技术的应用场景和优势 浅浅的玩一下这个 AI 写作&#xff0c;本内容全为 AI 生成&#xff0c;仅为 AI 观点&#xff0c;无作者本人的观点。 区块链技术是一种去中心化的分布式账本技术&#xff0c;具有以下应用场景和优势&#xff1a; 金融领域&#xff…...

IPsec-Vpn

网络括谱图 IPSec-VPN 配置思路 1 配置IP地址 FWA:IP地址的配置 [FW1000-A]interface GigabitEthernet 1/0/0 [FW1000-A-GigabitEthernet1/0/0]ip address 10.1.1.1 24 [FW1000-A]interface GigabitEthernet 1/0/2 [FW1000-A-GigabitEthernet1/0/2]ip address...

一日连发两款视频大模型,火山引擎杀疯了!

9月24日&#xff0c;字节跳动旗下火山引擎在深圳举办AI创新巡展&#xff0c;并首次对外发布豆包视频生成-PixelDance、豆包视频生成-Seaweed两款AI大模型&#xff0c;并公布了多项AI大模型的全新升级&#xff0c;以一种全新的姿态迎接AI时代的到来。 雷科技此次受邀参与巡展&a…...

JavaScript --数字Number的常用方法

toFixed(保留几位小数) <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthde…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...