最近有一個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 查看