一、 背景说明

在Eclipse环境下,开发JAVA代码操作PPT,支持对PPT模板的修改。包括修改文本标签、图表、表格。满足大多数软件生成PPT报告的要求,即先收工创建好模板,在程序中修改模板数据。

二、 开发环境搭建

下载jacob开源组件,解压后把jacob.jar添加到项目中。拷贝对应的dll文件到Path路径下。32位系统采用X86的dll, 64位系统采用X64的dll。

三、 实现合并PPT公共函数

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

/**
 * 通过jacob组件调用COM接口完成PPT文件的合并。合并后图表数据不丢失,用户可正常手工修改。
 * 调用函数前将jacob.jar添加到项目中,同时将jcaob.dll拷贝到path路径下。
 * @author Elon
 *
 */
public class MergePPT
{
    /**
     * 合并多个PPT文件。要求输出文件和合并文件均已存在,不创建新文件。
     * @param outPutPPTPath 合并后输出的文件路径。
     * @param mergePPTPathList 依次追加合并的文件。
     */
    public synchronized static void merge(String outPutPPTPath, List<String> mergePPTPathList)
    {
        // 启动 office PowerPoint程序
        ActiveXComponent pptApp = new ActiveXComponent("PowerPoint.Application");
        Dispatch.put(pptApp, "Visible", new Variant(true));   

        Dispatch presentations = pptApp.getProperty("Presentations").toDispatch();  

        // 打开输出文件
        Dispatch outputPresentation = Dispatch.call(presentations, "Open", outPutPPTPath, false,
                false, true).toDispatch();

        // 循环添加合并文件
        for (String mergeFile : mergePPTPathList)
        {
            Dispatch mergePresentation = Dispatch.call(presentations, "Open", mergeFile, false,
                false, true).toDispatch();

            Dispatch mergeSildes = Dispatch.get(mergePresentation, "Slides").toDispatch();
            @SuppressWarnings("deprecation")
            int mergePageNum = Dispatch.get(mergeSildes, "Count").toInt();

            // 关闭合并文件
            Dispatch.call(mergePresentation, "Close");

            Dispatch outputSlides = Dispatch.call(outputPresentation, "Slides").toDispatch();
            @SuppressWarnings("deprecation")
            int outputPageNum = Dispatch.get(outputSlides, "Count").toInt();

            // 追加待合并文件内容到输出文件末尾
            Dispatch.call(outputSlides, "InsertFromFile", mergeFile, outputPageNum, 1, mergePageNum);
        }

        // 保存输出文件,关闭退出PowerPonit.
        Dispatch.call(outputPresentation, "Save");
        Dispatch.call(outputPresentation, "Close");
        Dispatch.call(pptApp, "Quit");
    }
}

四、 修改PPT中的文本、图表公共函数

/**
 * 柱状图、饼图值类型
 * @author Elon
 *
 */
public class GraphValue implements Serializable
{
    /**
     *
     */
    private static final long serialVersionUID = 4055958383254660746L;

    /**
     * 系列名称
     */
    private String serialName = "";

    /**
     * 系列的值
     */
    private ArrayList<String> valueList = new ArrayList<String>();

    public String getSerialName()
    {
        return serialName;
    }

    public void setSerialName(String serialName)
    {
        this.serialName = serialName;
    }

    public ArrayList<String> getValueList()
    {
        return valueList;
    }

    public void setValueList(ArrayList<String> valueList)
    {
        this.valueList = valueList;
    }

    @Override
    public String toString()
    {
        String str = "serialName:" + serialName + " valueList:";

        for (String value : valueList)
        {
            str += value + ";";
        }

        return str;
    }
}

/**
 *
 * 修改PPT图表、文本信息公共类定义。
 *
 * @author Elon
 * @version 1.0, 2015年12月16日
 */
public class WritePPTUtil
{
    /**
     * PPT文件路径
     */
    public String pptPath = "";

    /**
     * ppt对象
     */
    private XMLSlideShow ppt = null;

    /**
     * 当前页签
     */
    private XSLFSlide curSlide = null;

    /**
     * 打开ppt文件
     * @param pptPath ppt文件路径
     * @throws XmlException
     * @throws OpenXML4JException
     * @throws IOException 异常
     */
    public void open(String pptPath) throws OpenXML4JException, IOException, XmlException
    {
        this.pptPath = pptPath;
        XSLFSlideShow slideShow = new XSLFSlideShow(pptPath);
        ppt = new XMLSlideShow(slideShow.getPackage());
    }

    /**
     * 保存关闭文件
     * @throws IOException
     */
    public void close() throws IOException
    {
        FileOutputStream out = new FileOutputStream(pptPath + "_new.pptx");
        ppt.write(out);
        out.close();

    }

    /**
     * 选中指定的PPT页签
     * @param slideIndex 页签索引
     * @return true:操作成功;false:操作失败
     */
    public boolean selectSlide(int slideIndex)
    {
        if(ppt == null)
        {
            return false;
        }

        XSLFSlide[] slideArray = ppt.getSlides();
        if(slideArray.length < slideIndex)
        {
            return false;
        }

        curSlide = slideArray[slideIndex];
        return true;
    }

    /**
     * 修改文本框内容
     * @param shapeValue
     * @param value
     * @return
     */
    public boolean modifyTextBox(String shapeValue, String value)
    {
        XSLFShape shape = getShape(shapeValue, ShapeType.TEXT_BOX_TYPE);
        if (shape == null)
        {
            return false;
        }

        XSLFTextBox textBox = (XSLFTextBox)shape;
        textBox.setText(value);
        return true;
    }

    /**
     *
     * 修改图表内容。
     *
     * @param ShapeName 图表名称
     * @param valueList
     * @return
     */
    public boolean modifyBargraph(String ShapeName, ArrayList<GraphValue> valueList)
    {
        XSLFShape shape = getShape("", ShapeType.GRAPHIC_TYPE);
        XSLFGraphicFrame graphicShape = (XSLFGraphicFrame)shape;

        XSLFSheet sheet = graphicShape.getSheet();

        // 修改PPT图表内嵌的sheet的内容(待续)。

        return true;
    }

    /**
     * 获取PPT页签中指定的控件。
     * @param shapeValue
     * @param shapeType
     * @return
     */
    private XSLFShape getShape(String shapeValue, ShapeType shapeType)
    {
        if(curSlide == null)
        {
            return null;
        }

        String shapeName = "";

        XSLFShape[] shapeArray = curSlide.getShapes();
        for (int i = 0; i < shapeArray.length; ++i)
        {
            shapeName = shapeArray[i].getShapeName();
            XSLFShape shape = shapeArray[i];

            if ((shapeType == ShapeType.TEXT_BOX_TYPE)
                    && (shape instanceof XSLFTextBox))
            {
                XSLFTextBox textBox = (XSLFTextBox)shape;
                String value = textBox.getText();
                if(value.equals(shapeValue))
                {
                    return shapeArray[i];
                }
            }
            else if ((shapeType == ShapeType.GRAPHIC_TYPE)
                    && (shape instanceof XSLFGraphicFrame))
            {
                return shape;
            }
        }

        return null;
    }
}

五、 调用PPT合并函数测试代码

public class TestPPTMain
{
    public static void main(String[] args) throws OpenXML4JException, IOException, XmlException
    {
        String outPutPPTPath = "D:\\TEMP\\template\\1.pptx";

        List<String> mergePPTPathList = new ArrayList<String>();
        mergePPTPathList.add("D:\\TEMP\\template\\2.pptx");
        mergePPTPathList.add("D:\\TEMP\\template\\3.pptx");

        MergePPT.merge(outPutPPTPath, mergePPTPathList);;
    }
}

JAVA通过COM接口操作PPT的更多相关文章

  1. C++通过COM接口操作PPT

    一. 背景 在VS环境下,开发C++代码操作PPT,支持对PPT模板的修改.包括修改文本标签.图表.表格.满足大多数软件生成PPT报告的要求,先手工创建好PPT模板,在程序中修改模板数据. 二. 开发 ...

  2. Java使用Unsafe接口操作数组Demo

    public class unSafeArrayDemo { private static final sun.misc.Unsafe UNSAFE; private static final lon ...

  3. Java NIO Path接口和Files类配合操作文件

    Java NIO Path接口和Files类配合操作文件 @author ixenos Path接口 1.Path表示的是一个目录名序列,其后还可以跟着一个文件名,路径中第一个部件是根部件时就是绝对路 ...

  4. java poi 操作ppt

    java poi 操作ppt 可以参考: https://www.w3cschool.cn/apache_poi_ppt/apache_poi_ppt_installation.html http:/ ...

  5. java抽象类和接口区别

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  6. 如何让Java和C++接口互相调用:JNI使用指南

    如何让Java和C++接口互相调用:JNI使用指南 转自:http://cn.cocos2d-x.org/article/index?type=cocos2d-x&url=/doc/cocos ...

  7. Java中的队列:java.util.Queue接口

    队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作. Queue接口与List.Set同一级别,都是继承了Collection接口.Linked ...

  8. Java集合Map接口与Map.Entry学习

    Java集合Map接口与Map.Entry学习 Map接口不是Collection接口的继承.Map接口用于维护键/值对(key/value pairs).该接口描述了从不重复的键到值的映射. (1) ...

  9. java的List接口的实现类 ArrayList,LinkedList,Vector 的区别

    Java的List接口有3个实现类,分别是ArrayList.LinkedList.Vector,他们用于存放多个元素,维护元素的次序,而且允许元素重复. 3个具体实现类的区别如下: 1. Array ...

随机推荐

  1. 使用mybatis插入自增主键ID的数据后返回自增的ID

    在开发中碰到用户注册的功能需要用到用户ID,但是用户ID是数据库自增生成的,这种情况上网查询后使用下面的方式配置mybatis的insert语句可以解决: <insert id="in ...

  2. curl模拟post和get请求

    function _post($url,$post_data){     $ch = curl_init();     curl_setopt($ch, CURLOPT_URL, $url);     ...

  3. 初步探究Android App API接口测试--实战

    一.Android App API接口测试 1.如何学好Android App API接口测试 postman可以用来实现API接口自动化测试,但是也有弊端,无法实现接口测试数据的参数化,为了达到接口 ...

  4. Maven中模块的聚合以及对jar包的继承

    我需要将之前的A B C三个模块聚合到一个一个工程中ABC项目中 pom.xml文件中应该这样配置 1.修改packaging里面的配置 <!-- 用于聚合这个项目的时候应该将packaging ...

  5. 重绘(redraw或repaint),重排(reflow)

    浏览器运行机制图: 浏览器的运行机制:layout:布局: 1.构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树(Co ...

  6. 总结JS中string、math、array的常用的方法

    JS为每种数据类型都内置很多方法,真的不好记忆,而且有些还容易记混,现整理如下,以便以后查看: 一.String ①charAt()方法用于返回指定索引处的字符.返回的字符是长度为 1 的字符串. 语 ...

  7. react+react-router+react-redux+nodejs+mongodb项目

    一个实际项目(OA系统)中的部分功能.这个demo中引入了数据库,数据库使用了mongodb.安装mongodb才能运行完整的功能.要看完整的项目可以移步我的github 技术栈 React v15. ...

  8. Servlet Cookie取不到值原因

    现象: 在测试带Cookie的HTTP请求时发现,服务端用request.getHeader("cookie")可以去到值; 但是用request.getCookies()却不行  ...

  9. 我的Java设计模式-责任链模式

    今天来说说程序员小猿和产品就关于需求发生的故事.前不久,小猿收到了产品的需求. 产品经理:小猿,为了迎合大众屌丝用户的口味,我们要放一张图,要露点的. 小猿:......露点?你大爷的,让身为正义与纯 ...

  10. DirectShow使用说明

    1) 安装directX sdk 2)打开安装目录下的dshow.dsw,进行编译 3)在VC++的Tools/Option/Directory的Include和Library中分别加入 C:/DXS ...