Java 根据模板文件生成新的PPT

简介: Java 根据模板文件生成新的PPT

项目需求

最近项目中有一个需求就是让Java代码去代替人工操作,自动生成PPT,具体就是查询数据库数据,然后根据模板文件(PPT),将数据库数据与模板文件(PPT),进行组合一下。生成新的PPT文件。


模板文件如下:

image.png

将模板文件中的姓名,进步率,连续进步次数,图片。替换为具体的人员信息。


实现过程:

1.引入第三方依赖

<dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml</artifactId>
     <version>3.15</version>
</dependency>

Apache POI   是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。

HSSF-提供读写MicrosoftExcelXLS格式档案的功能
XSSF-提供读写MicrosoftExcelOOXMLXLSX格式档案的功能
HWPF-提供读写MicrosoftWordDOC格式档案的功能
HSLF-提供读写MicrosoftPowerPoint格式档案的功能
HDGF-提供读MicrosoftVisio格式档案的功能
HPBF-提供读MicrosoftPublisher格式档案的功能
HSMF-提供读MicrosoftOutlook格式档案的功能

2.编写业务代码

import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import java.io.*;
import java.util.List;
/**
 * 读取模板PPT生成新的PPT文件
 *
 * @author Promsing(张有博)
 * @version 1.0.0
 * @since 2022/2/11 - 15:37
 */
public class RenderPowerPointTemplate extends BasePowerPointFileUtil {
    /**
     * 读取PPT模板
     * @param powerPoint
     * @param 
     * @throws IOException
     */
    public static void renderPowerPointTemplateOfCertificate(InputStream powerPoint, List<WeekAnalyseModel> lists, String rankType) throws IOException {
        //List<WeekAnalyseModel>是我们项目自己定义的model,可改成其他业务的model
        if(powerPoint == null) {
            return;
        }
        //创建一个幻灯片
        XMLSlideShow slideShow = new XMLSlideShow(powerPoint);
        //从幻灯片中获取每个页
        List slides = slideShow.getSlides();
        //遍历每一页PPT
        for (int i = 0 ; i < slides.size() ; i++) {
            //幻灯片布局,文本框,矩形框之类的,遍历一页PPT中的所有控件
            List shapes = ((Slide)slides.get(i)).getShapes();
            for (int j = 0 ; j < shapes.size() ; j++) {
                Shape shape = (Shape) shapes.get(j);
                RenderPowerPointTemplate.renderShapeAndPicture(shape, lists.get(i),rankType);
            }
        }
        //新PPT的位置,file就是新的PPT文件
        File file=new File(rankType+"test.pptx");
        OutputStream outputStreams = new FileOutputStream(file);
        slideShow.write(outputStreams);
       // FileUpLoadUtil.T_THREAD_LOCAL.set(file.getAbsolutePath());
        System.out.println("新文件的路径:"+file.getAbsolutePath());
    }
}
import com.tfjybj.integral.constant.CommonConstant;
import com.tfjybj.integral.model.WeekAnalyseModel;
import com.tfjybj.integral.utils.SimplifiedDate;
import org.apache.commons.io.FileUtils;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.apache.poi.xslf.usermodel.XSLFTextShape;
import java.awt.*;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
 * <p>PowerPoint文件工具基类
 * <p>
 * <p>通用的PowerPoint文件工具基类,可用于从PowerPoint文档中抽取文本信息
 */
public class BasePowerPointFileUtil {
    /**
     * 渲染、绘制文本框
     *
     * @param shape
     * @param data
     */
    public static void renderShapeAndPicture(Shape shape, WeekAnalyseModel data,String rankType) {
        //判断是否是文本框
        if (shape instanceof TextShape) {
            BasePowerPointFileUtil.replace(shape, data,rankType);
        } else if (shape instanceof GroupShape) {
            Iterator groupShapes = ((GroupShape) shape).iterator();
            while (groupShapes.hasNext()) {
                Shape groupShape = (Shape) groupShapes.next();
                BasePowerPointFileUtil.renderShapeAndPicture(groupShape, data,rankType);
            }
        } else if (shape instanceof TableShape) {
            TableShape tableShape = ((TableShape) shape);
            int column = tableShape.getNumberOfColumns();
            int row = tableShape.getNumberOfRows();
            for (int r = 0; r < row; r++) {
                for (int c = 0; c < column; c++) {
                    BasePowerPointFileUtil.replace(tableShape.getCell(r, c), data,rankType);
                }
            }
        } else if (shape instanceof PictureShape) {
            //判断是否是图片框
            PictureShape pictureShape = (PictureShape) shape;
            PictureData pictureData = pictureShape.getPictureData();
            byte[] bytes = BufferStreamForByte(URLToFile(data.getPictureURL()), 1024);
            try {
                pictureData.setData(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 替换模板PPT中的值
     *
     * @param shape
     * @param weekAnalyseModel
     */
    public static void replace(Shape shape, WeekAnalyseModel weekAnalyseModel,String rankType) {
         //List<WeekAnalyseModel>是我们项目自己定义的model,可改成其他业务的model
        if (shape instanceof TextShape) {
            String replaceText = ((XSLFTextShape) shape).getText();
            XSLFTextRun xslfTextRun = null;
            //替换数据的业务逻辑,待优化
            switch (replaceText) {
                case "姓名:闪耀姓名1":
                    xslfTextRun = ((XSLFTextShape) shape).setText("姓名:" + weekAnalyseModel.getUserName());
                    break;
                case "积分:闪耀分数1":
                    xslfTextRun = ((XSLFTextShape) shape).setText("积分:" + weekAnalyseModel.getWeekData());
                    break;
                case "闪耀1连击ヾ":
                    xslfTextRun = ((XSLFTextShape) shape).setText("闪耀" + weekAnalyseModel.getListNumber() + "连击ヾ");
                    break;
                case "姓名:闪耀姓名2":
                    xslfTextRun = ((XSLFTextShape) shape).setText("姓名:" + weekAnalyseModel.getUserName());
                    break;
                case "积分:闪耀分数2":
                    xslfTextRun = ((XSLFTextShape) shape).setText("积分:" + weekAnalyseModel.getWeekData());
                    break;
                case "闪耀2连击ヾ":
                    xslfTextRun = ((XSLFTextShape) shape).setText("闪耀" + weekAnalyseModel.getListNumber() + "连击ヾ");
                    break;
            }
            //空值过滤,设置样式
            if (xslfTextRun != null) {
                if (rankType.equals("闪耀之星")||rankType.equals("进步之星")){
                    setTextStyle(xslfTextRun);
                }else if (rankType.equals("闪耀之星荣誉证书")||rankType.equals("进步之星荣誉证书")){
                    setTextStyleCertificate(xslfTextRun);
                }
            }
        }
    }
    /**
     * 设置字体样式
     *
     * @param xslfTextRun
     */
    private static void setTextStyle(XSLFTextRun xslfTextRun) {
        xslfTextRun.setFontFamily("等线(正文)");
        Color color = new Color(255, 255, 255);
        xslfTextRun.setFontColor(color);
        xslfTextRun.setFontSize(40.0);
        xslfTextRun.setBold(true);
    }
    /**
     * 设置证书字体样式
     *
     * @param xslfTextRun
     */
    private static void setTextStyleCertificate(XSLFTextRun xslfTextRun) {
        xslfTextRun.setFontFamily("宋体");
        Color color = new Color(0, 0, 0);
        xslfTextRun.setFontColor(color);
        xslfTextRun.setFontSize(32.0);
        xslfTextRun.setBold(true);
    }
    /**
     * 将文件转为字节数组
     * @param file
     * @param size
     * @return
     */
    public static byte[] BufferStreamForByte(File file, int size) {
        byte[] content = null;
        try {
            BufferedInputStream bis = null;
            ByteArrayOutputStream out = null;
            try {
                FileInputStream input = new FileInputStream(file);
                bis = new BufferedInputStream(input, size);
                byte[] bytes = new byte[1024];
                int len;
                out = new ByteArrayOutputStream();
                while ((len = bis.read(bytes)) > 0) {
                    out.write(bytes, 0, len);
                }
                bis.close();
                content = out.toByteArray();
            } finally {
                if (bis != null) {
                    bis.close();
                }
                if (out != null) {
                    out.close();
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return content;
    }
    /**
     * 读取网络中的图片
     * @param url https://www.kziyue.com/wp-content/uploads/2019/06/5bca-hxyuaph9825616.jpg
     * @return
     */
    public static File URLToFile(String url){
        File file1 = new File("test.mp4");
        try {
            URL url1 = new URL(url);
            FileUtils.copyURLToFile(url1,file1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        File absoluteFile = file1.getAbsoluteFile();
        return file1;
    }
}

3.根据模板生成新的PPT

image.png

相关文章
|
24天前
|
Java Apache 开发工具
【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存
【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存
|
13天前
|
Arthas Java 测试技术
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
Java字节码文件、组成、详解、分析;常用工具,jclasslib插件、阿里arthas工具;如何定位线上问题;Java注解
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
|
12天前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
10天前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!
|
11天前
|
算法 Java
Java 压缩文件
在Java中压缩文件是一个常见的需求,通常可以通过使用Java自带的`java.util.zip`包来实现。这个包提供了`ZipOutputStream`类来创建ZIP格式的压缩文件。以下是一个简单的示例,展示了如何将多个文件压缩到一个ZIP文件中。 ### 示例:将多个文件压缩到一个ZIP文件中 ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipFilesExample { public static vo
|
23天前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
19天前
|
小程序 Java
【aspose-words】Aspose.Words for Java模板语法详细剖析
本文通过详细分析Aspose.Words for Java模板语法,介绍了使用条件块、变量和动态合并表格单元格三个常用模板标签,并结合实际案例进行演示。通过这三个标签的实操,帮助读者更好地掌握Aspose.Words的使用技巧。此外,还提供了官方文档链接以便进一步学习。
59 0
【aspose-words】Aspose.Words for Java模板语法详细剖析
|
23天前
|
Java 程序员
Java系统中的错误码设计问题之实现一个基于properties文件的错误消息管理系统如何解决
Java系统中的错误码设计问题之实现一个基于properties文件的错误消息管理系统如何解决
12 1
|
17天前
|
Java Apache Maven
Java中使用poi+poi-tl实现根据模板导出word文档
这个过程不仅简化了文档生成的工作,而且保证了生成文档的一致性与准确性,特别适合于那些需要生成大量文档的自动化场景。通过以上步骤,Java开发人员可以实现高效、可靠的Word文档导出功能。
56 0
|
18天前
|
Java
java判断文件内容不为空
请注意,在实际的生产环境中,处理文件时需要考虑异常处理。在上述代码中,如果在文件读取过程中发生 `IOException`,则会被捕获,并在控制台打印堆栈跟踪信息。在更复杂的系统中,可能还需要更精细的异常处理策略。
28 0