Java poi 生成PPT并插入Excel附件并以图片形式显示代

  • 前言
  • 月报需求
  • POI写法
  • Maven依赖
  • JAVA代码


前言

网上找的都不好使,没办法逼得我自己写了一个。还搜到个的贴子说不知道好不好使的一个帖子收费19.9,一生气我申请了一个9.9的,我这个保证好使的。效果如下:

1.大图,里边有一张小图。

java 实现ppt 模板替换 java生成ppt_ppt


2.点击小图,弹出EXCEL

java 实现ppt 模板替换 java生成ppt_poi_02

月报需求

我的原始需求是生成一个月报,里边是当月的统计图,图片是前台传过来的一张做好的统计图我直接插入PPT就行,但是统计图里的数据需要以EXCEL作为附件放到PPT了,研究了好久,网上例子基本用不了,最后自己研究的。网上有一个Free Office的例子,但是这个例子的依赖,我下载依赖如下。
这个依赖有好多问题:

  1. 依赖太大了,一个jar50M左右,我整个项目的其他依赖加一起没这个依赖大。
  2. 这个依赖刚下载下来的时候360杀毒弹出了一个提示,说是有病毒,所以我没敢用。因为这个程序是要在客户机房里跑的,客户定期扫描出问题可就废了。
<dependency>
    <groupId>e-iceblue</groupId>
    <artifactId>spire.office.free</artifactId>
    <version>3.9.0</version>
</dependency>

POI写法

没找到网上的例子,只能回来继续研究POI的写法,最后终于是实现了功能,代码如下:注意看注释

Maven依赖

<!-- poi office -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>5.0.0</version>
        </dependency>

JAVA代码

import org.apache.poi.sl.usermodel.ObjectMetaData;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.awt.geom.Rectangle2D;
import java.io.*;

/**
 * 我的需求是在PPT里生成一个统计图,然后统计图里的数据以Excel的形式作为附件放在图片下边.
 *
 * @author Lwb
 */
public class PoiOleXlsInPpt {

    public static void main(String[] args) throws IOException {

        final ByteArrayInputStream pptBytes;
        try (XMLSlideShow ppt = new XMLSlideShow()) {
            //这个是插入一个统计图的图片
            File image = new File("C:\\123\\123.jpg");
            ppt.setPageSize(new java.awt.Dimension(1024, 600));
            XSLFSlide slide = ppt.createSlide();
            byte[] picture = IOUtils.toByteArray(new FileInputStream(image));
            XSLFPictureData idx = ppt.addPicture(picture, PictureData.PictureType.EMF);
            XSLFPictureShape pic = slide.createPicture(idx);
            //设置为止
            pic.setAnchor(new java.awt.Rectangle(0, 0, 1024, 600));
            //插入的第2个图片,这个是作为EXCEL的图片,注意是EMF格式,要不会有点小问题
            /**
            * 注意看第31行的注释,必须得是EMF格式,而且这个格式不能强转改后缀名是不行的
            * 我用的方式是先自己创建一个PPT插入我要用的图片,然后用解压缩软件去打开PPT
            * 里边就能看到插入的那张图片,把那张图片拷贝出来然后再在程序里使用那张图片,就好了。
            * */
            final PictureData picData = ppt.addPicture(new FileInputStream("C:\\123\\123.efm"), PictureData.PictureType.EMF);
            //在PPT里插入一个对象,跟你在PPT里点 插入(菜单)-对象是一样的,然后选择以图标显示是一样的
            final XSLFObjectShape oleShape = slide.createOleShape(picData);
            //设置这个图片的位置
            oleShape.setAnchor(new Rectangle2D.Double(300, 280, 60, 60));
            //设置附件格式是EXCEL
            try (OutputStream os = oleShape.updateObjectData(ObjectMetaData.Application.EXCEL_V12, null)) {
                //创建EXCEL并写入object对象的输出流
                fillOleData(os);
            }
            //以图标展示的属性必须设置
            oleShape.getCTOleObject().setShowAsIcon(true);
            final ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
            ppt.write(bos);
            pptBytes = new ByteArrayInputStream(bos.toByteArray());
            org.apache.poi.xslf.usermodel.XSLFObjectShape a;
            //创建PPT文件
            File pptx = new File("C:\\123\\123.pptx");
            FileOutputStream p = new FileOutputStream(pptx);
            ppt.write(p);
        }
        //这个是测试的
//        try (SlideShow<?, ?> ppt = SlideShowFactory.create(pptBytes)) {
//            final ObjectShape<?, ?> oleShape = (ObjectShape<?, ?>) ppt.getSlides().get(0).getShapes().get(1);
//            try (InputStream bis = oleShape.readObjectData()) {
//                validateOleData(bis);
//            }
//        }

    }

    //创建EXCEL的函数
    private static void fillOleData(final OutputStream out) throws IOException {
        //创建EXCEL
        Workbook wb = new XSSFWorkbook();
        //创建sheet页并写了一行数据
        wb.createSheet().createRow(0).createCell(0).setCellValue("test me");
        //输出数据
        wb.write(out);
    }

}