Apache POI操作pptx基本使用


最近有一個ppt操作的需求,因此查了下相關的資料

ppt分類

  (1)2007版之前的

    是基於二進制的文件格式

    細節沒有完全公開,第三方廠商多是用單向工程方法猜測和分析出來的。WPS做得好一些,但開源的只有做得很差的LibreOffice(原OpenOffice)

  (2)2007版以后的

    是基於OOXML開放文檔規范的,本質是一個ZIP包,壓縮了XML文檔和相關資源。

    OOXML是是一種簡潔、可靠的文件格式,這類格式可以更好地實現文檔與后端系統之間的數據集成。

java工具

  (1)Apache POI 

    Apache軟件基金會的開放源碼函式庫,POI提供API給Java程序

    (2)Aspose.Slides

    是一款處理pptx的商業軟件

  (3)Jacob

    Java-COM Bridge

    在Java與微軟的COM組件之間構建一座橋梁。使用Jacob自帶的DLL動態鏈接庫,並通過JNI的方式實現了在Java平台上對COM程序的調用。

    MSWordManager 類,是jacob官方發布的工具類,里面有大多數Java操作MS Office的工具。

    在使用Jacob時,很重要的一點是,用戶本地系統中必須安裝有Word的應用程序。否則也就無法建立Java-COM橋,進而無法解析了。

  因此決定試水 Apache POI 

Apache POI 使用

1.下載http://poi.apache.org/download 

2.修改CLASSPATH

  解壓下載的包,將下面5個jar的完整路徑添加到CLASSPATH

4.介紹

在POI API中

  PowerPoint PPT——格式為 HSLF     對應poi-scratchpad

  PowerPoint PPTX 格式為 XSLF   對應 poi-ooxml

類型 格式 對應的包
Powerpoint '97(-2007)PPT HSLF poi-scratchpad-XXX.jar
PowerPoint 2007 PPTX XSLF  poi-ooxml-XXX.jar

 

 

 

 

3使用

下面是基於pptx的

(1)生成空白文檔

DealDocument.java
import org.apache.poi.xslf.usermodel.XMLSlideShow;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class DealDocument {

    protected String path = "data";
    /**
     * 創建文檔
     *
     * @param name
     */
    public void createDocument(String name) {

        XMLSlideShow ppt = new XMLSlideShow();
        String fileName = this.path + File.separator + name;
        File file = new File(fileName);
        try {
            FileOutputStream out = new FileOutputStream(file);
            ppt.write(out);
            System.out.println("Presentation created successfully");
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Main.java

import java.io.*;
import java.net.URL;
import java.util.List;
import org.apache.poi.*;
public class Main {

    public static void main(String[] args) throws IOException{
        System.out.println("Hello World!");
        DealDocument dd = new DealDocument();
        dd.createDocument("example1.pptx");
    }
}

輸出

Hello World!
Presentation created successfully

並且在項目根目錄的data下生成example1.pptx

說明:

  如果出現錯誤

 Exception in thread "main" java.lang.IncompatibleClassChangeError: Found class org.apache.poi.util.POILogger, but interface was expected

  這個錯誤最可能的原因是poi的jar包使用了多個版本

  使用下面的方法可以查看具體使用的哪里的jar包

  (在網上找的,但是版本不同,第三段 org.apache.poi.hslf.HSLFSlideShow.class.getClassLoader()沒有找到相關的類,將poi-scratchpad-4.1.0.jar反編譯,找了個存在的類,版本是4.1.0)

ClassLoader classloader = org.apache.poi.poifs.filesystem.POIFSFileSystem.class.getClassLoader();
URL res = classloader.getResource("org/apache/poi/poifs/filesystem/POIFSFileSystem.class");
String path = res.getPath();
System.out.println("POI Core came from " + path);

classloader = org.apache.poi.POIDocument.class.getClassLoader();
res = classloader.getResource("org/apache/poi/POIDocument.class");
path = res.getPath();
System.out.println("POI OOXML came from " + path);

classloader=org.apache.poi.hdgf.HDGFDiagram.class.getClassLoader();
res = classloader.getResource("org/apache/poi/hdgf/HDGFDiagram.class");
path = res.getPath();
System.out.println("POI Scratchpad came from " + path);

  輸出

POI Core came from file:/C:/Program%20Files/Java/jdk1.8.0_151/jre/lib/ext/poi-3.17.jar!/org/apache/poi/poifs/filesystem/POIFSFileSystem.class
POI OOXML came from file:/C:/Program%20Files/Java/jdk1.8.0_151/jre/lib/ext/poi-3.17.jar!/org/apache/poi/POIDocument.class
POI Scratchpad came from file:/E:/java/project/ppt/ppttest/lib/poi-scratchpad-4.1.0.jar!/org/apache/poi/hdgf/HDGFDiagram.class

  發現確實有一個class走了老包,想起了在對mpp文件進行讀寫時添加了poi-3.17.jar,因此把相關文件刪掉,問題解決

(2)在已有文檔添加空白頁

在 DealDocument.java 里

在文件 data/tpl1.pptx,追加兩個空白頁

public void addNewSlide(String name){

        String fileName = this.path + File.separator + name;
        File file = new File(fileName);
        try {
            //opening an existing slide show
            FileInputStream in = new FileInputStream(file);
            XMLSlideShow ppt = new XMLSlideShow(in);
            //adding slides to the slodeshow
            XSLFSlide slide1= ppt.createSlide();
            XSLFSlide slide2 = ppt.createSlide();
            //saving the changes
            FileOutputStream out = new FileOutputStream(file);
            ppt.write(out);
            System.out.println("Presentation edited successfully");
            out.close();
        }catch (IOException e) {
            e.printStackTrace();
        }
}

在mian里的使用

DealDocument dd = new DealDocument();
dd.addNewSlide("tpl1.pptx");

 執行完后,輸出

Hello World!
Presentation edited successfully

文件里多了兩個空白頁

(3)將PPT中幻燈片轉成圖片

import org.apache.poi.xslf.usermodel.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class ImageConvert {

    public void converter(String fileName) {
        BackRS rs = new BackRS();
        File file = new File(fileName);
        String name = file.getName();
        String filePath = file.getParent();
        try {
            FileInputStream in = new FileInputStream(file);
            XMLSlideShow ppt = new XMLSlideShow(in);
            Dimension pgsize = ppt.getPageSize();
            String saveImagePathName = filePath + File.separator + getFileNameNoEx(name)+"_JPG";
            File path = new File(saveImagePathName);
            if (!path.exists()) {
                path.mkdir();
            }
            Integer i = 0;
            BufferedImage img =null;
            for (XSLFSlide slide : ppt.getSlides()) {
                //解決亂碼問題
                for(XSLFShape shape : slide.getShapes()){
                    if(shape instanceof XSLFTextShape) {
                        XSLFTextShape tsh = (XSLFTextShape)shape;
                        for(XSLFTextParagraph p : tsh){
                            for(XSLFTextRun r : p){
                                r.setFontFamily("宋體");
                            }
                        }
                    }
                }
                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));
                slide.draw(graphics);
                FileOutputStream out = new FileOutputStream(path + File.separator + (i+1) + ".JPG");
                i++;
                javax.imageio.ImageIO.write(img, "PNG", out);
                out.close();
            }
            System.out.println("Image successfully converted.");
        } catch (Exception e) {
            System.out.println("error:"+e.getMessage());
        }
    }

    /**
     * 獲取文件名,去除擴展名的
     */
    public String getFileNameNoEx(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length()))) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }
}
fileName為完整的路徑
圖片生成的目錄為,和ppt文件同一個目錄下,目錄名為:ppt文件名+_JPG
圖片名為,N.JPG (幻燈片從0開始編號,因此圖片名為1.JPG……)

說明:

  雖然對亂碼問題做了處理,但是還會出現亂碼,而且Apache POI是開源的,創始人離開后版本更新沒有推進

  可以改用Aspose.Slide for java  查看

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM