likes
comments
collection
share

Apache 的POI居然还能操作PPT,快来试试看上次我们讲的用POI操作excel。Java操作Excel(Apac

作者站长头像
站长
· 阅读数 26

上次我们讲的用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格式

Apache 的POI居然还能操作PPT,快来试试看上次我们讲的用POI操作excel。Java操作Excel(Apac

那么我们现在就介绍一下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();
    }
}

Apache 的POI居然还能操作PPT,快来试试看上次我们讲的用POI操作excel。Java操作Excel(Apac

读取一个PowerPoint文件(test2.pptx),获取其页面大小,然后设置新的页面大小为1024x768像素,并将修改后的PowerPoint文件保存为slideshow2.ppt。 Apache 的POI居然还能操作PPT,快来试试看上次我们讲的用POI操作excel。Java操作Excel(Apac

往幻灯片里面添加文本框

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格式,这样就不会出现错误了。

转载自:https://juejin.cn/post/7378512100186718260
评论
请登录