如何使用POI读取模板PPT填充数据并拼接至目标文件

POI是一个用于操作Microsoft Office格式文件的Java API库。它可用于读取、写入和操作Word、Excel和PowerPoint等Microsoft Office格式文件。在日常工作中,我们经常需要处理PPT文件,例如制作报告、演示文稿等。而对于一些重复性工作,使用POI库读取模板PPT并填充数据,再拼接至目标文件可以大大提高工作效率,减少手动操作的时间和错误率。

在本篇博客中,我们将分享如何使用POI库读取模板PPT并填充数据,最终生成目标文件。我们参考了CSDN上的其他博客,结合具体代码进行演示,展示使用POI库操作PPT文件的方法和技巧。

在使用POI库读取模板PPT并填充数据的过程中,我们需要先导入POI的相关jar包,然后通过SlideShow类读取模板文件,使用Slide类对PPT中的幻灯片进行操作,例如获取文本框、图片等元素,并使用TextRun类对文本框进行文本替换样式调整。在数据填充完成后,我们可以通过SlideShow类将填充好的幻灯片拼接至目标文件中,最终得到我们想要的PPT文件。在整个操作过程中,我们需要注意异常处理和代码优化,以保证代码的可靠性和效率。

通过本篇博客的学习和实践,我们可以掌握使用POI库读取模板PPT并填充数据的方法和技巧,提高工作效率,减少手动操作的时间和错误率。

接下来,我们将结合具体代码进行演示,展示如何使用POI库读取模板PPT并填充数据,最终生成目标文件。

  • HSLF教程
  • XSLF教程
  • poi5.x文档

一、PPT文件格式介绍

1、PPT文件格式的概述

PPT文件格式是Microsoft PowerPoint演示文稿的格式,用于存储幻灯片、文本、图形、图像、音频和视频等多媒体元素。PPT文件格式的扩展名为 **.ppt(PowerPoint 97-2003格式)**和 .pptx(PowerPoint 2007及以后版本格式)

PPT文件格式的基本结构由一系列XML文件和二进制数据组成。

  • 在.ppt文件中,每个幻灯片都被存储为一个二进制数据流,PPT文件的二进制数据包含了PPT文件的所有元素和布局信息。
  • 而在.pptx文件中,每个幻灯片都被存储为一个XML文件,PPTX文件的XML文件则将这些元素和布局信息以标记语言的形式存储。

PPT文件格式的版本和兼容性是需要注意的问题。在Microsoft PowerPoint 97至2003版本中,PPT文件格式使用二进制文件格式,而在Microsoft PowerPoint 2007及以后版本中,PPTX文件格式使用XML文件格式。由于这两个版本的PPT文件格式不兼容,使用不同版本的Microsoft PowerPoint软件打开PPT文件可能会导致文件格式错误或元素丢失等问题。

为了实现对PPT文件的操作和处理,可以使用POI类库。POI类库是一个Java类库,可以读取、写入和操作Microsoft Office格式的文档,包括PPT文件。POI类库支持HSLF和XSLF两种PPT文件格式的操作,提供了丰富的API和工具,可以方便地读取、修改、创建和保存PPT文件。

2、HSLF和XSLF的区别

HSLF(Horrible Slide Layout Format)和 XSLF(XML Slide Layout Format)是POI类库中用于操作PPT文件的两种不同的API。HSLF是用于操作PPT文件的旧API,而XSLF是用于操作PPTX文件的新API。

以下是HSLF和XSLF的区别:

  • 文件格式:HSLF是用于操作PPT文件的API,而XSLF是用于操作PPTX文件的API。PPT文件是二进制格式,而PPTX文件是基于XML的文件格式。
  • API:HSLF提供了对PPT文件的操作和处理,包括读取、修改和创建等;而XSLF则提供了对PPTX文件的操作和处理,也包括读取、修改和创建等。
  • 功能:XSLF相比HSLF提供了更多的功能和特性,如更好的文本和形状控制、更高的图像质量和更灵活的布局控制等。
  • 兼容性:XSLF可以处理PPTX文件的所有特性和功能,而HSLF则有一些限制,无法处理PPTX文件中的一些新特性和功能。
  • 性能:XSLF相比HSLF需要更多的内存和CPU资源,因为PPTX文件是基于XML的格式,需要解析和处理XML文件,而PPT文件则是二进制格式,相对来说更加高效。

总的来说,如果需要操作PPT文件,可以使用HSLF API,如果需要操作PPTX文件,可以使用XSLF API。然而,如果需要同时处理PPT和PPTX文件,则需要考虑两种API的差异性和兼容性,以确保代码的正确性和稳定性。

3、如何选择合适的POI类库

选择合适的POI类库取决于需要操作的文档类型和所需的功能。以下是选择适合的POI类库的一些考虑因素:

  1. 文档类型:首先需要确定需要操作的文档类型是PPT还是XLS或DOC等。如果需要操作PPT文件,则需要使用HSLF或XSLF API,如果需要操作XLS文件,则需要使用HSSF API,如果需要操作DOC文件,则需要使用HWPF API等。
  2. 功能需求:需要确定需要实现哪些功能,POI类库提供了丰富的API和工具,可以用于读取、写入、修改、创建和保存文档,包括文本、图像、图表、表格、公式等元素的操作。根据具体的需求选择相应的API。
  3. 兼容性:需要考虑POI类库的兼容性,POI类库支持的文档类型和版本可能有所不同,需要根据实际情况选择相应的API。
  4. 性能:需要考虑POI类库的性能,POI类库的性能可能会受到文档大小、复杂度和计算机配置等因素的影响。对于大型文档和复杂操作,需要选择具有更好性能的API。
  5. 学习曲线:需要考虑POI类库的学习曲线,POI类库提供了丰富的API和工具,但也需要一定的学习和实践才能熟练掌握。

综上所述,需要根据文档类型、功能需求、兼容性、性能和学习曲线等因素来选择适合的POI类库。同时,也需要考虑代码的可维护性、稳定性和可扩展性等方面,以确保代码质量和效率。

二、SlideShow

SlideShow 接口定义了一组方法,用于处理幻灯片演示文稿的数据。为了使用 SlideShow 接口,需要使用具体的实现类XMLSlideShow和HSLFSlideShow。这些实现类提供了 SlideShow 接口中定义的所有方法,并且可以用来读取、创建和编辑幻灯片演示文稿。它们分别用于打开PPT、pptX和老版本的PPT文件。

  • HSLFSlideShow 类用于处理 PowerPoint 97-2003 幻灯片演示文稿,即 PPT 文件。它使用 HSLF 模型来处理幻灯片演示文稿,HSLF 模型是基于 Microsoft OLE 2 Compound Document Format 的解析器,它可以解析幻灯片演示文稿中的所有元素,如幻灯片、文本框、形状、图像、音频、视频等等。HSLFSlideShow 类提供了一组方法,用于读取、创建和编辑 PPT 文件中的幻灯片。
  • XMLSlideShow 类用于处理 PowerPoint 2007 或更高版本的幻灯片演示文稿,即 PPTX 文件。它使用 XML 模型来处理幻灯片演示文稿,XML 模型是基于 OpenXML 文件格式的解析器,它可以解析幻灯片演示文稿中的所有元素,如幻灯片、文本框、形状、图像、音频、视频等等。XMLSlideShow 类提供了一组方法,用于读取、创建和编辑 PPTX 文件中的幻灯片。

总的来说,HSLFSlideShow 用于处理 PPT 文件,XMLSlideShow 用于处理 PPTX 文件。它们都提供了类似的方法,如 getSlides()、createSlide()、getPageSize() 等等,但是具体的实现略有不同。如果需要处理 PPT 文件,就应该使用 HSLFSlideShow 类;如果需要处理 PPTX 文件,就应该使用 XMLSlideShow 类。

引入依赖:本文版本4.1.2(pms引入的easyExcel依赖的poi版本是4.1.2)

    <dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>5.2.3</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>5.2.3</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-excelant</artifactId>
			<version>5.2.3</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-examples</artifactId>
			<version>5.2.3</version>
		</dependency>
		<dependency>
			<groupId>org.apache.xmlbeans</groupId>
			<artifactId>xmlbeans</artifactId>
			<version>5.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-scratchpad</artifactId>
			<version>5.2.3</version>
		</dependency>
		<dependency>
			<groupId>top.xtcoder.tools</groupId>
			<artifactId>xtpsd</artifactId>
			<version>0.0.1</version>
		</dependency>

三、读取PPT文件

1. 加载PPT文件

在使用这些类打开PPT文件之前,需要先使用Java IO类库中的FileInputStream类打开文件流,然后将文件流传递给相关的类来读取PPT文件。下面是一个简单的Java示例代码,演示如何使用HSLFSlideShow类和XMLSlideShow类来打开PPT和pptX文件:

    import java.io.FileInputStream;
    import java.io.IOException;
		import org.apache.poi.xslf.usermodel.XMLSlideShow;
    import org.apache.poi.xslf.usermodel.XSLFSlide;
		public class OpenPPTX {
			public static void main(String[] args) {
				try {
					FileInputStream fis = new FileInputStream("example.ppt"); // 打开ppt文件流
					HSLFSlideShow ppt = new HSLFSlideShow(fis); // 创建HSLFSlideShow对象
					fis.close(); // 关闭文件流
					// 处理ppt文件
				} catch (IOException e) {
					e.printStackTrace();
				}
				
				try {
					FileInputStream fis = new FileInputStream("example.pptx"); // 打开pptX文件流
					XMLSlideShow pptx = new XMLSlideShow(fis); // 创建XMLSlideShow对象
					fis.close(); // 关闭文件流
					// 处理pptX文件
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
    }

上述代码中,使用FileInputStream类打开PPT和pptX文件流,然后分别使用 HSLFSlideShow类 和 XMLSlideShow类 创建ppt和pptX文件的对象,并在文件处理完之后关闭文件流。需要注意的是,读取ppt和pptX文件时都需要使用try-catch语句来捕获IOException异常。

总的来说,HSLFSlideShow和XMLSlideShow是Apache POI库中用于处理PPT文件的类,它们分别用于打开PPT、pptX和老版本的PPT文件,使用时需要先使用Java IO类库中的FileInputStream类打开文件流,然后将文件流传递给相关的类来读取PPT文件。

2. 获取PPT文件中的幻灯片

要获取PPT文件中的幻灯片,可以使用SlideShow、XMLSlideShow和HSLFSlideShow类的getSlides() 方法来获取PPT文件中的所有幻灯片。

HSLFSlide

    HSLFSlideShow ppt = new HSLFSlideShow(fis); // 创建HSLFSlideShow对象
    for (HSLFSlide slide : ppt.getSlides()) {// 处理每个幻灯片
    }

XSLFSlide

    XMLSlideShow pptx = new XMLSlideShow(fis); // 创建XMLSlideShow对象
    for (XSLFSlide slide : pptx.getSlides()) {// 处理每个幻灯片
    }

3. 获取幻灯片中的形状元素

HSLFSlide 和 XSLFSlide 类都提供了一组方法来获取幻灯片中的形状元素。可以使用 getShapes() 方法来获取幻灯片中的所有形状,然后判断形状的类型进行相关类型的操作。下面分别介绍如何使用这两个类来获取这些元素。

HSLFShape

    // 如获取第一张幻灯片
    HSLFSlide slide = ppt.getSlides().get(0);
    // 获取幻灯片中的所有形状遍历
    for (HSLFShape shape : slide.getShapes()) {
			if (shape instanceof HSLFTextBox) {
				// 文本框
			}
			
			if (shape instanceof HSLFPictureShape) {
				// 图片
			}
			
			if (shape instanceof HSLFTable) {
				// 表格
			}
			
			//……
    }

XSLFShape

    // 如获取第一张幻灯片
    XSLFSlide slide = ppt.getSlides().get(0);
    // 获取幻灯片中的所有形状遍历
    for (XSLFShape shape : slide.getShapes()) {
			if (shape instanceof XSLFTextBox) {
				// 文本框
			}
			
			if (shape instanceof XSLFPictureShape) {
				// 图片
			}
			
			if (shape instanceof XSLFTable) {
				// 表格
			}
			
			//……
    }

四、修改PPT文件内容

1. 幻灯片操作

在使用POI读取模板PPT填充数据并拼接至目标文件时,您可能需要对幻灯片进行操作。如新增一张幻灯片、删除某张幻灯片、移动幻灯片到指定位置以及复制幻灯片。

1.1 新增幻灯片

HSLFSlideShow 和 XSLFSlideShow 类都提供了 createSlide() 方法,用于在最后新增一张空白的幻灯片。

    HSLFSlide slide = ppt.createSlide();
    XSLFSlide slide = pptx.createSlide();

1.2 删除幻灯片

HSLFSlideShow 和 XSLFSlideShow 类都提供了 removeSlide() 方法,用于删除指定位置或对象的幻灯片。

例如,要删除第二个幻灯片,可以使用以下代码:

    // 删除第二个幻灯片
    ppt.removeSlide(1);

注意,幻灯片的索引从 0 开始,因此第二个幻灯片的索引是 1。

1.3 移动幻灯片

使用 HSLFSlideShow 或 XSLFSlideShow 类的 getSlides() 方法获取幻灯片列表,然后使用 List 类的 add() 和 remove() 方法来实现幻灯片的移动。

例如,将第二个幻灯片移动到第四个位置,可以使用以下代码:

    List<XSLFSlide> slides = pptx.getSlides();
    slides.add(3, slides.get(1));
    slides.remove(1);

在上面的代码中,我们首先使用 HSLFSlideShow 的 getSlides() 方法获取幻灯片列表,然后获取第二个幻灯片对象,使用 List 类的 add() 方法将该幻灯片添加到第四个位置,最后使用 List 类的 remove() 方法将原来的第二个幻灯片删除。

在这里插入图片描述

在这里插入图片描述

1.4 复制幻灯片

使用 HSLFSlide 或 XSLFSlide 类的 createSlide() 方法新增一张幻灯片,并将需要复制的幻灯片中所有的形状复制至新增的幻灯片,即完成复制操作。

HSLF

    /** 复制ppt单页
		* @param template 模板页
		* @param ppt      HSLFSlideShow ppt
		* @param index    移动到指定下标
		* @return 复制页
		**/
    public static HSLFSlide copySlide(HSLFSlide template, HSLFSlideShow ppt, int index) {
			// 创建新的一页PPT,按模板的布局母页
			HSLFSlide newSlide = ppt.createSlide();// 复制模板页中的shapes
			List<HSLFShape> shapes = template.getShapes();
			shapes.forEach(shape -> {
				newSlide.addShape(shape);
			});// 排序(在PPT中的第几页)
			List<HSLFSlide> slides = ppt.getSlides();
			slides.add(index, newSlide);
			slides.remove(ppt.getSlides().size() - 1);
			return newSlide;
    }

XSLF

    /** 复制ppt单页
		* @param template 模板页
		* @param ppt      ppt
		* @param newIndex 复制页放置位置
		* @return 复制页
		**/
    private XSLFSlide copySlide(XSLFSlide template, XMLSlideShow ppt, int newIndex) {
			// 创建新幻灯片且填充内容
			XSLFSlide newSlide = ppt.createSlide().importContent(template);// 排序(在PPT中的第几页)
			ppt.setSlideOrder(newSlide, newIndex);
			return newSlide;
    }

2. 设置幻灯片中的形状元素的属性

在使用POI读取模板PPT填充数据并拼接至目标文件时,您可能需要对幻灯片中的形状元素进行属性修改。这些属性包括形状大小、形状文本、形状填充和形状边框等。您可以使用POI的相应方法来修改这些属性,以满足您的实际需求。

注:以下内容基于XSLF

2.1 形状的位置以及大小

可以使用POI的setAnchor方法来修改形状的大小和位置。例如:

    XSLFSlide slide = ...; // 获取幻灯片
    XSLFTextShape shape = ...; // 获取文本框形状
    Rectangle2D anchor = new Rectangle2D.Double(x, y, width, height); // 新的位置和大小
    shape.setAnchor(anchor); // 设置新的位置和大小

2.2 形状的文本

在POI中,用于表示PPT中的文本框的类主要包括以下几个类:

  1. XSLFTextShape:表示PPT中的形状中的文本框,是XSLFShape的子类。
  2. XSLFTextBox:表示PPT中的文本框,是XSLFTextShape的子类。
  3. XSLFTextParagraph:表示文本框中的段落,每个段落可以包含多个文本片段。
  4. XSLFTextRun:表示文本框中的文本片段,每个文本片段可以设置不同的字体、字号、颜色等属性。
  5. XSLFTextShapeAutoFit:用于设置文本框的自适应大小方式。
  6. XSLFTextShape.TextDirection:用于设置文本框中文本的方向。
  7. XSLFTextShape.TextDecoration:用于设置文本框中文本的装饰效果,例如下划线、删除线等。
  8. XSLFTextShape.TextPlaceholder:用于设置文本框的占位符属性,例如标题、正文、页脚等。

其中,XSLFTextShapeXSLFTextBox都是用于表示PPT中的文本框的类。它们的主要区别在于它们继承的类不同,以及它们可以应用的场景不同。

  • XSLFTextShape是XSLFShape的子类,可以表示PPT中的各种形状(包括文本框)以及组合形状等。它具有更广泛的应用场景,可以用于表示任何形状中的文本内容,例如矩形、梯形、圆形等。相对于XSLFTextBox,XSLFTextShape的API更加丰富,可以设置更多的属性,例如字体、字号、颜色等。
  • XSLFTextBox是XSLFTextShape的子类,专门用于表示PPT中的文本框。它可以包含多行文本,并且可以自动调整大小以适应文本内容。相对于XSLFTextShape,XSLFTextBox的API更加简洁,可以更方便地操作文本框的内容和属性。

因此,当您需要在PPT中添加文本框时,可以选择使用XSLFTextShape或XSLFTextBox,具体取决于您的实际需求。如果您需要在形状中添加文本内容,可以选择XSLFTextShape;如果您需要添加一个自适应大小的文本框,可以选择XSLFTextBox。

1、XSLFTextShape设置新的文本内容:

    XSLFTextShape shape = ...; // 获取文本框形状
    String text = "新的文本"; // 新的文本内容
    shape.setText(text); // 设置新的文本内容

2、XSLFTextBox 设置新的文本内容

    XSLFTextBox textBox = ...; 						// 获取文本框形状
    String text = "新的文本"; 						 // 新的文本内容
    textBox.setText(text);								// 设置新的文本内容
    textBox.setVerticalAlignment(VerticalAlignment.MIDDLE);		// 设置垂直对齐方式(例如:垂直居中)

2.3 形状文本属性

在POI中,可以通过XSLFTextRun类来设置形状文本的字体颜色、加粗、字号等属性。XSLFTextRun类表示文本框中的文本片段,每个文本片段可以设置不同的字体、字号、颜色等属性。

1、设置字体颜色:使用setFontColor方法设置文本片段的字体颜色,参数为一个XSLFColor对象。

    XSLFTextRun textRun = ...;
    textRun.setFontColor(new XSLFColor(Color.RED));

2、设置加粗:使用setBold方法设置文本片段是否加粗,参数为true或false。

    XSLFTextRun textRun = ...;
    textRun.setBold(true);

3、设置字号:使用setFontSize方法设置文本片段的字号,参数为一个float类型的数值。

    XSLFTextRun textRun = ...;
    textRun.setFontSize(14.0);

4、设置字体:使用setFontFamily方法设置文本片段的字体,参数为字体名称字符串。

    XSLFTextRun textRun = ...;
    textRun.setFontFamily("Arial");

2.4 形状填充

可以使用POI的setFillColor方法来修改形状的填充颜色。例如:

XSLFTextShape

    XSLFTextShape shape = ...; // 获取形状
    Color fillColor = Color.RED; // 新的填充颜色
    shape.setFillColor(fillColor); // 设置新的填充颜色

XSLFTextBox

    XSLFTextBox textBox = ...; 						// 获取文本框形状
    Color color = new Color(0, 0, 0, 40); // 新的填充颜色(如透明色)
    textBox.setFillColor(color);					// 设置新的填充颜色

2.5 形状边框

可以使用POI的setLineColor方法来修改形状的边框颜色,以及使用setLineWidth方法来修改边框的宽度。例如:

XSLFTextShape

    XSLFTextShape shape = ...; // 获取形状
    Color lineColor = Color.BLUE; // 新的边框颜色
    int lineWidth = 2; // 新的边框宽度
    shape.setLineColor(lineColor); // 设置新的边框颜色
    shape.setLineWidth(lineWidth); // 设置新的边框宽度

XSLFTextBox

    XSLFTextBox textBox = ...; // 获取形状
    Color lineColor = Color.BLUE; // 新的边框颜色
    int lineWidth = 2; // 新的边框宽度
    textBox.setLineColor(lineColor); // 设置新的边框颜色
    textBox.setLineWidth(lineWidth); // 设置新的边框宽度

2.6 形状对齐方式

在POI中,可以通过XSLFTextShape、XSLFTextBox类的setVerticalAlignmentsetHorizontalCentered方法来设置形状中内容的垂直对齐方式和水平对齐方式。

  • 垂直对齐方式:setTextVerticalAlignment方法可以设置文本框中文本的垂直对齐方式,方法的参数是VerticalAlignment枚举类,常用的对齐方式包括:

    • VerticalAlignment.TOP:文本框中文本向上对齐;
    • VerticalAlignment.MIDDLE:文本框中文本垂直居中对齐;
    • VerticalAlignment.BOTTOM:文本框中文本向下对齐。
    • VerticalAlignment.JUSTIFIED:文本框中文本两端对齐
    • VerticalAlignment.DISTRIBUTED:文本框中文本分散对齐

    前三个值是常用的对齐方式。JUSTIFY和DISTRIBUTED一般用于多行文本的对齐,可以使文本在每行末尾对齐或者分散对齐。

  • 水平对齐方式:setTextHorizontalCentered方法可以设置文本框中文本的水平对齐方式,常用的对齐方式包括:

    • true:文本框中文本水平居中对齐。
    • false:文本框中文本左对齐。

XSLFTextShape

    XSLFTextShape shape =  ...; 													// 获取形状
    shape.setVerticalAlignment(VerticalAlignment.TOP);		// 垂直对齐方式
    shape.setHorizontalCentered(true);												// 设置水平对齐方式

XSLFTextBox

    XSLFTextBox textBox =  ...; 														// 获取形状
    textBox.setVerticalAlignment(VerticalAlignment.MIDDLE); // 垂直对齐方式
    textBox.setHorizontalCentered(false);										// 设置水平对齐方式

实战:在生成招商PPT需求时为展位图片添加指定标题的方法

    /*** 指定幻灯片案例图片加上标题
		* @param slide          XSLFSlide 幻灯片
		* @param x              新建矩形的左上角的X坐标
		* @param y              新建矩形的左上角的y坐标
		* @param w              新建矩形的宽度
		* @param h              新建矩形的高度
		* @param fontSize       字号
		* @param transparentRed 背景色
		* @param context        内容
		**/
    private void addActivityPictureTitle(XSLFSlide slide, double x, double y, double w, double h, Double fontSize, Color transparentRed, String context) {
			XSLFTextBox textBox = slide.createTextBox();
			textBox.setText(context);
			textBox.setFillColor(transparentRed);
			textBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
			Rectangle2D anchor = new Rectangle2D.Double(x, y, w, h);
			textBox.setAnchor(anchor);
			XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
			paragraph.setTextAlign(TextParagraph.TextAlign.CENTER);
			XSLFTextRun textRun = paragraph.getTextRuns().get(0);
			textRun.setFontColor(Color.white);
			textRun.setBold(true);
			textRun.setFontSize(fontSize);
    }

3. 添加新的形状

3.1 添加新的文本框

使用createTextBox方法在幻灯片中添加新的文本框。可以通过setAnchor方法设置文本框的位置和大小,通过setText方法设置文本框中的文本内容。

    XSLFSlide slide = ...;
    XSLFTextBox textBox = slide.createTextBox();		//创建新的文本框
    textBox.setAnchor(new Rectangle2D.Double(x, y, width, height));
    textBox.setText("Hello, World!");

3.2 添加新的图片

使用createPicture方法在幻灯片中添加新的图像。

    XSLFSlide slide = ...;
    InputStream pictureData = ...; // 图像的输入流
    XSLFPictureData pictureData =  slide.addPicture(pictureData), PictureData.PictureType.PNG);	//给幻灯片添加图片
    pictureData.setAnchor(new Rectangle(470, 54, 386, 236));	// 指定图片的位置和大小

3.3 添加新的表格

添加表格:使用createTable方法在幻灯片中添加新的表格。可以通过setAnchor方法设置表格的位置和大小,通过getCell方法获取单元格,并通过setText方法设置单元格中的文本内容。

    XSLFSlide slide = ...;
    XSLFTable table = slide.createTable();
    table.setAnchor(new Rectangle2D.Double(x, y, width, height));
    XSLFTableCell cell = table.getCell(0, 0);
    cell.setText("Cell 1,1");

五、拼接PPT文件以及导出和保存

1. 拼接PPT文件

1.1 将填充好的幻灯片拼接至目标文件

    XMLSlideShow ppt = new XMLSlideShow();	// 需要拼接至目标文件
    XSLFSlide slide = ...;	// 填充好的幻灯片
    ppt.createSlide().importContent(slide);	// 拼接至目标文件

1.2 实现PPT文件的合并和拼接

    // 目标ppt
    XMLSlideShow targetPpt = ...;
    // 来源ppt
    XMLSlideShow sourcePpt = ...;
    for (XSLFSlide slide : sourcePpt.getSlides()) {
			targetPpt.createSlide().importContent(slide);
    }

1.3 将多个演示文稿合并在一起

    // 目标ppt
    XMLSlideShow ppt = new XMLSlideShow();
    // 需要合并的ppt文件路径
    String[] inputs = {"presentations1.pptx", "presentation2.pptx"};
    for(String arg : inputs){
			FileInputStream is = new FileInputStream(arg);
			XMLSlideShow src = new XMLSlideShow(is);
			is.close();// 遍历ppt文件中的每张幻灯片
			
			for(XSLFSlide srcSlide : src.getSlides()){
				// 目标ppt新建幻灯片且导入幻灯片内容
				ppt.createSlide().importContent(srcSlide);
			}
    }
    FileOutputStream out = new FileOutputStream("merged.pptx");
    ppt.write(out);
    out.close();

2. PPT文件的导出和保存

2.1 将PPT文件导出为PDF、图片等格式

将PPT文件导出为PDF

Apache POI 库主要用于读写 Microsoft Office 格式的文档,例如 Word、Excel 和 PowerPoint 文件,不支持直接操作 PDF 文件。如果您需要操作 PDF 文件,可以使用其他的 Java PDF 库,例如 iText、PDFBox 等。

1、引入依赖

iText 和 Apache POI 的兼容版本依赖关系如下:

  • iText 5.x 与 POI 3.x 兼容。
  • iText 7.x 与 POI 4.x 兼容。
    <dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itext7-core</artifactId>
			<version>7.1.16</version>
    </dependency>

2、编写方法

    public static byte[] pptxToPdf(InputStream src) {
			Document document = null;
			XMLSlideShow slideShow = null;
			FileOutputStream fileOutputStream = null;
			PdfWriter pdfWriter = null;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] resBytes = null;
			try {
				//使用输入流pptx文件
				slideShow = new XMLSlideShow(src);
				//获取幻灯片的尺寸
				Dimension dimension = slideShow.getPageSize();
				//创建一个写内容的容器
				document = new Document(PageSize.A3, 72, 72, 72, 72);
				//使用输出流写入
				pdfWriter = PdfWriter.getInstance(document, baos);
				//使用之前必须打开
				document.open();
				pdfWriter.open();
				PdfPTable pdfPTable = new PdfPTable(1);
				//获取幻灯片
				java.util.List<XSLFSlide> slideList = slideShow.getSlides();
				for (int i = 0, row = slideList.size(); i < row; i++) {
					//获取每一页幻灯片
					XSLFSlide slide = slideList.get(i);
					for (XSLFShape shape : slide.getShapes()) {
						//判断是否是文本
						if(shape instanceof XSLFTextShape){
							// 设置字体, 解决中文乱码
							XSLFTextShape textShape = (XSLFTextShape) shape;
							for (XSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
								for (XSLFTextRun textRun : textParagraph.getTextRuns()) {
									textRun.setFontFamily("宋体");
								}
							}
						}
					}
					
					//根据幻灯片尺寸创建图形对象
					BufferedImage bufferedImage = new BufferedImage((int)dimension.getWidth(), (int)dimension.getHeight(), BufferedImage.TYPE_INT_RGB);
					Graphics2D graphics2d = bufferedImage.createGraphics();
					graphics2d.setPaint(Color.white);
					graphics2d.setFont(new java.awt.Font("宋体", java.awt.Font.PLAIN, 12));
					//把内容写入图形对象
					slide.draw(graphics2d);
					graphics2d.dispose();
					//封装到Image对象中
					Image image = Image.getInstance(bufferedImage, null);
					image.scalePercent(50f);
					// 写入单元格
					pdfPTable.addCell(new PdfPCell(image, true));
					document.add(image);
				}
				document.close();
				pdfWriter.close();
				resBytes = baos.toByteArray();
			} catch (Exception e) {
				log.error("pptx转pdf异常:{}",e);
			} finally {
				try {
					if (baos != null) {
						baos.close();
					}
				} catch (IOException e) {
					log.error("pptx转pdf关闭io流异常:{}",e);
				}
			}
			return resBytes;
    }

将PPT文件导出为图片

    /**
		* 将后缀为.pptx的PPT转换为图片
		* @param pptFile PPT的路径
		* @param imgFile 将PPT转换为图片后的路径
		* @return
		**/
    public List<String> PptToPdfConverter(File pptFile, String imgFile) {
			List<String> list = new ArrayList<>();
			FileInputStream is = null ;
			try {
				is = new FileInputStream(pptFile);
				XMLSlideShow xmlSlideShow = new XMLSlideShow(is);
				is.close();
				// 获取大小
				Dimension pgsize = xmlSlideShow.getPageSize();
				// 获取幻灯片
				List<XSLFSlide> slides = xmlSlideShow.getSlides();
				for (int i = 0 ; i < slides.size() ; i++) {
					// 解决乱码问题
					List<XSLFShape> shapes1 = slides.get(i).getShapes();
					for (XSLFShape shape : shapes1) {
						if (shape instanceof XSLFTextShape) {
							XSLFTextShape sh = (XSLFTextShape) shape;
							List<XSLFTextParagraph> textParagraphs = sh.getTextParagraphs();
							for (XSLFTextParagraph xslfTextParagraph : textParagraphs) {
								List<XSLFTextRun> textRuns = xslfTextParagraph.getTextRuns();
								for (XSLFTextRun xslfTextRun : textRuns) {
									xslfTextRun.setFontFamily("宋体");
								}
							}
						}
					}
					//根据幻灯片大小生成图片
					BufferedImage img = new BufferedImage(pgsize.width,pgsize.height, BufferedImage.TYPE_INT_RGB);
					Graphics2D graphics = img.createGraphics();
					graphics.setPaint(Color.white);
					graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width,pgsize.height));
					// 最核心的代码
					slides.get(i).draw(graphics);
					//图片将要存放的路径
					String absolutePath = imgFile+"/"+DateUtils.datePath() +"/"+ (i + 1) + ".jpeg";
					File jpegFile = new File(absolutePath);
					// 图片路径存放
					list.add((i + 1) + ".jpeg");
					//如果图片存在,则不再生成
					if (jpegFile.exists()) {
						continue;
					}
					// 这里设置图片的存放路径和图片的格式(jpeg,png,bmp等等),注意生成文件路径
					FileOutputStream out = new FileOutputStream(jpegFile);
					// 写入到图片中去
					ImageIO.write(img, "jpeg", out);
					out.close();
				}
				return list;
			} catch (Exception e) {
			
			}
			return list;
    }

2.2 PPT文件保存

使用 FileOutputStream 类将 PPT 文件保存到本地磁盘、OSS中。

本地保存

    XMLSlideShow ppt = ...; 
    FileOutputStream fos = new FileOutputStream("文件路径.ppptx");
    ppt.write(fos);
    fos.close();

上传七牛云

    QiNiuOSS service = SpringUtil.getBean(QiNiuOSS.class);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    originalPpt.write(bos);
    String key = LocalDateTimeUtil.format(LocalDate.now(), DatePattern.PURE_DATETIME_MS_PATTERN) +RandomStringUtils.randomAlphabetic(6) + ".pptx";
    return service.uploadStream("bucketName", "dir", new ByteArrayInputStream(bos.toByteArray()), key);