上次我们讲的用POI操作excel。Java操作Excel(Apache Poi详解)
那么java怎么操作ppt呢,其实poi也提供了操作ppt的sdk,现在我们来直接用Apache的poi操作ppt
首先我们要知道的是PPT有两种,一种格式是PPT,一种格式是PPTX,PPTX就是2007年之后的新的PPT协议。也就是说PPT和PPTX是PowerPoint的两种文件格式,PPT为旧版本格式,PPTX为新版本格式。 PPTX具有更好的兼容性、更小的文件大小、更高的安全性和更丰富的功能,而PPT格式功能相对简单。
所以在POI里面也有两种不同的sdk去操作对应的两种格式。在官网的介绍中可以得知,使用hslf操作ppt格式,使用xslf操作pptx格式
那么我们现在就介绍一下poi操作ppt的一些sdk
第一步,导入依赖
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.5</version>
</dependency>
第二步就可以开始使用sdk了,我们先来看pptx格式的sdk
添加图片
package com.example.aivideo.test3;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureData;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class addpic {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
XSLFSlide slide = ppt.createSlide();
byte[] pictureData = IOUtils.toByteArray(new FileInputStream("C:\\Users\\PC\\Pictures\\Saved Pictures\\d5e28fc20a5a41e8997691134bed79f4.png"));
XSLFPictureData pd = ppt.addPicture(pictureData, PictureData.PictureType.PNG);
XSLFPictureShape pic = slide.createPicture(pd);
FileOutputStream out = new FileOutputStream("slideshow2.ppt");
ppt.write(out);
out.close();
}
}
读取一个PPTX文件,向其中添加一张来自指定路径的PNG图片,然后将含有新图片的幻灯片保存为另一个PPT文件。它使用Apache POI库操作PPTX文件。
添加一张幻灯片
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class append {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
//append a new slide to the end
XSLFSlide blankSlide = ppt.createSlide();
FileOutputStream out = new FileOutputStream("slideshow3.ppt");
ppt.write(out);
out.close();
}
}
将一个已存在的PPTX演示文稿进行扩展。它首先打开一个名为"test2.pptx"的文件,然后在该文稿的末尾添加一个新的空白幻灯片。添加新幻灯片后,程序将整个修改后的演示文稿保存到名为"slideshow3.ppt"的新文件中。
添加有内容的幻灯片
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.SlideLayout;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
import org.apache.poi.xslf.usermodel.XSLFTextShape;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class appendnew {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
// first see what slide layouts are available :
System.out.println("Available slide layouts:");
for(XSLFSlideMaster master : ppt.getSlideMasters()){
for(XSLFSlideLayout layout : master.getSlideLayouts()){
System.out.println(layout.getType());
}
}
// blank slide
XSLFSlide blankSlide = ppt.createSlide();
// there can be multiple masters each referencing a number of layouts
// for demonstration purposes we use the first (default) slide master
XSLFSlideMaster defaultMaster = ppt.getSlideMasters().get(0);
// title slide
XSLFSlideLayout titleLayout = defaultMaster.getLayout(SlideLayout.TITLE);
// fill the placeholders
XSLFSlide slide1 = ppt.createSlide(titleLayout);
XSLFTextShape title1 = slide1.getPlaceholder(0);
title1.setText("First Title");
// title and content
XSLFSlideLayout titleBodyLayout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT);
XSLFSlide slide2 = ppt.createSlide(titleBodyLayout);
XSLFTextShape title2 = slide2.getPlaceholder(0);
title2.setText("Second Title");
XSLFTextShape body2 = slide2.getPlaceholder(1);
body2.clearText(); // unset any existing text
body2.addNewTextParagraph().addNewTextRun().setText("First paragraph");
body2.addNewTextParagraph().addNewTextRun().setText("Second paragraph");
body2.addNewTextParagraph().addNewTextRun().setText("Third paragraph");
FileOutputStream out = new FileOutputStream("slideshow2.ppt");
ppt.write(out);
out.close();
}
}
这里打开了一个现有的PowerPoint文件(“C:\Users\PC\Documents\test2.pptx”),查看可用的幻灯片布局,并创建了三个新幻灯片,每个幻灯片使用不同的布局。第一个幻灯片是一个空白幻灯片,第二个幻灯片是一个只有标题的幻灯片,第三个幻灯片是一个包含标题和内容的幻灯片。最后,该程序将修改后的PowerPoint文件保存为"slideshow2.ppt"。
删除幻灯片
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class delete {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
ppt.removeSlide(2); // 0-based index of a slide to be removed
FileOutputStream out = new FileOutputStream("slideshow3.ppt");
ppt.write(out);
out.close();
}
}
注意这里的索引是从0开始的哦,如果大家有把一个大ppt按每一页切割成一个小的ppt可以使用下面的方案去切割:
package com.example.aivideo.split;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* 最终版
*/
public class SplitPPT {
public static void main(String[] args) throws Exception {
FileInputStream stream = new FileInputStream("C:\\Users\\PC\\Documents\\A.pptx");
XMLSlideShow ppt = new XMLSlideShow(stream);
int numSlides = ppt.getSlides().size();
System.out.println(numSlides);
for (int i = 0; i < numSlides; i++) {
// 删除新PPT中除了当前幻灯片之外的其他幻灯片
for (int j = numSlides - 1; j >= 0; j--) {
if (j != i) {
ppt.removeSlide(j);
}
}
// 输出为单个ppt
FileOutputStream out = new FileOutputStream("te9_" + (i + 1) + ".pptx");
ppt.write(out);
out.close();
// 恢复原始幻灯片列表,以便下一次循环
stream = new FileInputStream("C:\\Users\\PC\\Documents\\A.pptx");
ppt = new XMLSlideShow(stream);
}
ppt.close();
}
}
或者你也可以使用这种复制的方案:
package com.example.aivideo.split;
import org.apache.poi.xslf.usermodel.SlideLayout;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* 最终版
*/
public class SplitPPTcopy {
public static void main(String[] args) throws Exception {
try (FileInputStream stream = new FileInputStream("C:\\Users\\PC\\Documents\\A.pptx");
XMLSlideShow ppt = new XMLSlideShow(stream);) {
int numSlides = ppt.getSlides().size();
List<XSLFSlideMaster> slideMasters = ppt.getSlideMasters();
List<XSLFSlideLayout> xslfSlideLayouts = new ArrayList<>();
slideMasters.forEach(master -> {
xslfSlideLayouts.addAll(Arrays.asList(master.getSlideLayouts()));
});
System.out.println(numSlides);
for (int i = 0; i < numSlides; i++) {
try (XMLSlideShow newPPT = new XMLSlideShow();
FileOutputStream out = new FileOutputStream("test_" + (i + 1) + ".pptx");) {
newPPT.setPageSize(ppt.getPageSize());
// 复制当前页到新的PPT对象中
XSLFSlide slide = ppt.getSlides().get(i);
XSLFSlide newPPTSlide = newPPT.createSlide();
newPPTSlide.importContent(slide);
xslfSlideLayouts.forEach(slideLayout -> {
slideLayout.copyLayout(newPPTSlide);
});
// 输出为单个ppt
newPPT.write(out);
}
}
}
}
}
但是这种会出现格式丢失的情况,如果对ppt里面的内容要求不高,允许丢失数据,可以使用这种方案,这种方案会比上面的方案更节省资源和加快速度。
添加超链接
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFHyperlink;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import java.io.FileOutputStream;
import java.io.IOException;
public class hyperlink {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
// assign a hyperlink to a text run
XSLFTextBox shape = slide.createTextBox();
XSLFTextRun r = shape.addNewTextParagraph().addNewTextRun();
r.setText("Apache POI");
XSLFHyperlink link = r.createHyperlink();
link.setAddress("https://poi.apache.org");
//save changes
FileOutputStream out = new FileOutputStream("slideshow3.ppt");
ppt.write(out);
out.close();
}
}
创建一个PowerPoint文件,并在其中的幻灯片上添加一个指向Apache POI官网的超链接文本"Apache POI",然后保存为"slideshow3.ppt"文件。
合并ppt
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Merge {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
String[] inputs = {"C:\\Users\\PC\\Documents\\test2.pptx", "C:\\Users\\PC\\Documents\\test.pptx"};
for(String arg : inputs){
FileInputStream is = new FileInputStream(arg);
XMLSlideShow src = new XMLSlideShow(is);
is.close();
for(XSLFSlide srcSlide : src.getSlides()){
ppt.createSlide().importContent(srcSlide);
}
}
FileOutputStream out = new FileOutputStream("merged.pptx");
ppt.write(out);
out.close();
}
}
合并多个PowerPoint文件。它打开每个输入文件,遍历其中的每张幻灯片,并将它们导入到一个新的PowerPoint演示文稿中。最后,它将合并后的演示文稿保存为一个新文件。这种就是我们上面说到的复制方案,但是会丢一些动画和格式。
读取ppt内容
package com.example.aivideo.test3;
import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFConnectorShape;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextShape;
import java.io.FileInputStream;
import java.io.IOException;
public class read {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
// get slides
for (
XSLFSlide slide : ppt.getSlides()) {
for (XSLFShape sh : slide.getShapes()) {
// name of the shape
String name = sh.getShapeName();
// shapes's anchor which defines the position of this shape in the slide
if (sh instanceof PlaceableShape) {
java.awt.geom.Rectangle2D anchor = ((PlaceableShape) sh).getAnchor();
}
if (sh instanceof XSLFConnectorShape) {
XSLFConnectorShape line = (XSLFConnectorShape) sh;
// work with Line
} else if (sh instanceof XSLFTextShape) {
XSLFTextShape shape = (XSLFTextShape) sh;
String text = shape.getText();
System.out.println(text);
// work with a shape that can hold text
} else if (sh instanceof XSLFPictureShape) {
XSLFPictureShape shape = (XSLFPictureShape) sh;
// work with Picture
}
}
}
}
}
遍历每张幻灯片中的所有形状。它识别形状类型(如文本框、图片、线条等),然后对他们进行操作。
读取ppt里面的图片
package com.example.aivideo.test3;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureData;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class readpic {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
for(XSLFPictureData data : ppt.getPictureData()){
byte[] bytes = data.getData();
String fileName = data.getFileName();
System.out.println(fileName);
}
}
}
对了,就是标题的意思,poi提供了读取ppt里面所有图片的sdk。
改变幻灯片的位置
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class Reorder {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
List<XSLFSlide> slides = ppt.getSlides();
XSLFSlide thirdSlide = slides.get(2);
ppt.setSlideOrder(thirdSlide, 0); // move the third slide to the beginning
FileOutputStream out = new FileOutputStream("slideshow2.ppt");
ppt.write(out);
out.close();
}
}
重新排列幻灯片的顺序,然后将修改后的演示文稿保存到新的文件中。
改变ppt的长宽
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class Rewir {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("C:\\Users\\PC\\Documents\\test2.pptx"));
//retrieve page size. Coordinates are expressed in points (72 dpi)
java.awt.Dimension pgsize = ppt.getPageSize();
int pgx = pgsize.width; //slide width in points
int pgy = pgsize.height; //slide height in points
System.out.println("page size: " + pgx + "x" + pgy);
//set new page size
ppt.setPageSize(new java.awt.Dimension(1024, 768));
FileOutputStream out = new FileOutputStream("slideshow2.ppt");
ppt.write(out);
out.close();
}
}
读取一个PowerPoint文件(test2.pptx),获取其页面大小,然后设置新的页面大小为1024x768像素,并将修改后的PowerPoint文件保存为slideshow2.ppt。
往幻灯片里面添加文本框
package com.example.aivideo.test3;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import java.awt.*;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class text {
public static void main(String[] args) throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
XSLFTextBox shape = slide.createTextBox();
XSLFTextParagraph p = shape.addNewTextParagraph();
XSLFTextRun r1 = p.addNewTextRun();
r1.setText("The");
r1.setFontColor(Color.blue);
r1.setFontSize(24.);
XSLFTextRun r2 = p.addNewTextRun();
r2.setText(" quick");
r2.setFontColor(Color.red);
r2.setBold(true);
XSLFTextRun r3 = p.addNewTextRun();
r3.setText(" brown");
r3.setFontSize(12.);
r3.setItalic(true);
r3.setStrikethrough(true);
XSLFTextRun r4 = p.addNewTextRun();
r4.setText(" fox");
FileOutputStream out = new FileOutputStream("slideshow2.ppt");
ppt.write(out);
out.close();
}
}
生成一个PPT文件,包含一个幻灯片和一个文本框。文本框内有不同格式的文字(如蓝色、红色、加粗、斜体、删除线)。
随后,关于PPT格式的部分我就不再赘述了,各位可以直接去官网查看更具体的信息。当然,这个文件有两种阅读方式,如果用旧的hslf去读取pptx格式的文件会出现错误,但如果我们将其输出,无论是用hslf还是xslf,都能输出为PPTx或PPT格式,这样就不会出现错误了。