• 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  查看

  • 相关阅读:
    android studio中timber的配置
    bufferknife框架的正确使用方式 -终于他么知道了
    开源的图像滤镜库----for Android
    HSV做通道分离是出现的Vector内存越界错误
    HSV与RGB的相互转换的公式
    Windows下python的第三方库的安装
    Python出现"Non-ASCII character 'xe6' in file"错误解决方法
    Verilog的IDE Quartus II
    Java-ZipUtil工具类
    Java-JDBCUtil工具类
  • 原文地址:https://www.cnblogs.com/baby123/p/10770168.html
Copyright © 2020-2023  润新知