Apache POI操作PPT: 文字替换 图片替换 表格填充 PPT合并

一点前置

POI PPT常用组件

在POI中,我们经常使用的几个对象如下:

  • SlideShow 对应整个PPT文件
  • Slide 对应一页PPT
  • Shape 这个可以实现就比较多了。文本域、图片、表格、都归属于这一类。
  • PictureShape 图片对象 没啥说的
  • XSLFTable 表格 也没啥好说的
  • TextShape 文本域对象
  • TextParagraph 当Shape的实现类是TextShape是,我们就可以获取到段落啦。
  • TextRun 这个是最基础的东西了。具体的文字和样式都是由它控制的。

可能存在的坑

  1. 虽然TextShape存在setText方法,但是调用的话会导致之前设置的样式全部失败。
  2. 你认为属于一个TextRun的文本,它还真不一定在同一个里面,尤其里面有特殊符号。
  3. 目前对于图片的替换还不能控制比例。
  4. 对于PPT合并,不要通过创建新PPT导入来实现。如果需要合并的PPT中大小有宽屏的,很有可能会变形。

具体操作

首先是依赖

		
		<dependency>
			<groupId>org.apache.poigroupId>
			<artifactId>poiartifactId>
			<version>4.1.1version>
		dependency>
		
		<dependency>
			<groupId>org.apache.poigroupId>
			<artifactId>poi-scratchpadartifactId>
			<version>4.1.1version>
		dependency>
		
		<dependency>
			<groupId>org.apache.poigroupId>
			<artifactId>poi-ooxmlartifactId>
			<version>4.1.1version>
		dependency>

替换字符串

个人这边做了一点封装。可以采用${xxx}的占位符方式来进行替换。
示例:

Map<String, String> textMap = new HashMap<>();
textMap.put("${xxx}", "文本域");
PoiUtils.replaceText(tmpFileName, textMap);

具体代码:

    /**
     * 进行文本替换
     *
     * @param path
     * @param textMap
     * @throws IOException
     */
    public static void replaceText(String path, Map<String, String> textMap) throws IOException {
     
        FileInputStream fileInput = new FileInputStream(path);
        XMLSlideShow ppt = new XMLSlideShow(fileInput);
        for (Slide slide : ppt.getSlides()) {
     
            List<Shape> shapes = slide.getShapes();
            for (Shape shape : shapes) {
     
                //文本
                if (shape instanceof TextShape) {
     
                    List<TextParagraph> list = ((TextShape) shape).getTextParagraphs();
                    replaceData(list, textMap);
                }
            }
        }
        FileOutputStream out = new FileOutputStream(path);
        ppt.write(out);
        out.close();
        ppt.close();
    }
    
 	/**
     * 替换文本
     *
     * @param list
     * @param textMap
     */
    private static void replaceData(List<TextParagraph> list, Map<String, String> textMap) {
     
        if (list == null || list.size() <= 0){
     
            return;
        }

        StringBuffer target = new StringBuffer();
        TextRun targetRun = null;

        for (TextParagraph textParagraph : list) {
     
            if (textParagraph == null) {
     
                continue;
            }
            List<TextRun> textRuns = textParagraph.getTextRuns();
            if (textRuns == null || textRuns.size() <= 0 || textRuns.isEmpty()) {
     
                continue;
            }
            for (int i = 0; i < textRuns.size(); i++) {
     
                TextRun textRun = textRuns.get(i);
                if (textRun == null) {
     
                    continue;
                }
                String text = textRun.getRawText();
                if (StringUtils.isBlank(text)) {
     
                    continue;
                }
                //检测开始标记
                if (text.contains("${")) {
     
                    targetRun = textRun;
                }else if ("}".equals(text)) {
     
                    if(null == targetRun){
     
                        continue;
                    }
                    String finalText = target.append("}").toString();
                    for(String key : textMap.keySet()){
     
                        if(finalText.contains(key)){
     
                            finalText = finalText.replace(key,textMap.get(key));
                        }
                    }
                    target.delete(0,target.length());
                    targetRun.setText(finalText);
                    targetRun =null;
                    textRun.setText("");
                }
                if(null != targetRun){
     
                    target.append(textRun.getRawText().trim());
                    textRun.setText("");
                }

            }
        }

    }

替换图片

目前还无法改变图片大小,那位大佬知道的话还请不吝赐教。

    /**
     * 替换图片信息
     * 
     * @param ppt
     * @param pictureData
     * @param index
     */
    public static void feedImageData(XMLSlideShow ppt, byte[] pictureData,int index) throws IOException {
     
        int num = 0;
        for (XSLFSlide slide : ppt.getSlides()) {
     
            // 获取每一张幻灯片中的shape
            for (XSLFShape shape : slide.getShapes()) {
     
                if (shape instanceof PictureShape) {
     
                    if(num == index){
     
                        XSLFPictureShape pictureShape = (XSLFPictureShape) shape;
                        pictureShape.getPictureData().setData(pictureData);
                        break;
                    }
                    num++;
                }
            }
        }
    }

进行表格数据填充

个人建议目标表格最少两行。表头这个就不说了。PPT创建新行的话会默认使用上一行的样式。所以如果你的数据行和表头行不一致的话,请保证起码存在一行空的数据行。

    /**
     * 进行表格填充 仅处理获取到的第一个表格
     *
     * @param path
     * @param data
     */
    public static void dealTable(String path, List<List<String>> data) throws IOException {
     
        FileInputStream fileInput = new FileInputStream(path);
        XMLSlideShow ppt = new XMLSlideShow(fileInput);
        for (XSLFSlide slide : ppt.getSlides()) {
     
            // 获取每一张幻灯片中的shape
            for (XSLFShape shape : slide.getShapes()) {
     
                if (shape instanceof XSLFTable) {
     
                    XSLFTable table = (XSLFTable) shape;
                    for (int i = 0; i < data.size() - 1; i++) {
     
                        XSLFTableRow row = table.getRows().get(i + 1);
                        if(null == row){
     
                            row = table.addRow();
                        }
                        List<String> cellsData = data.get(i);
                        for (int j = 0; j < cellsData.size(); j++) {
     
                            String dataStr = cellsData.get(j);

                            XSLFTableCell cell = row.getCells().get(j);
                            if (null == cell) {
     
                                cell = row.addCell();
                            }
                            cell.setHorizontalCentered(true);
                            cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
                            XSLFTextParagraph paragraph = cell.getTextParagraphs().get(0);
                            if (null == paragraph) {
     
                                paragraph = cell.addNewTextParagraph();
                            }
                            XSLFTextRun run = paragraph.addNewTextRun();
                            run.setText(dataStr);
                            run.setFontFamily("微软雅黑");
                            run.setFontSize(9D);
                        }
                    }
                    break;
                }
            }
        }
        FileOutputStream out = new FileOutputStream(path);
        ppt.write(out);
        out.close();
        ppt.close();
    }

合并PPT

注意:如果你的PPT存在大小不一样的情况,那么拼接完会出现变形,切记!

 /**
     * 合并ppt
     *
     * @param file1
     * @param file2
     * @throws IOException
     */
    public static void merge(String file1, String file2) throws IOException {
     
        Assert.hasLength(file1);
        Assert.hasLength(file2);

        FileInputStream is = new FileInputStream(file1);
        XMLSlideShow src = new XMLSlideShow(is);

        FileInputStream is2 = new FileInputStream(file2);
        XMLSlideShow src2 = new XMLSlideShow(is2);
        is2.close();
        
        for (XSLFSlide slide : src2.getSlides()) {
     
            XSLFSlide slide1 = src.createSlide();
            slide1.importContent(slide);
        }

        FileOutputStream out = new FileOutputStream(file1);
        src.write(out);
        out.close();
        is.close();
    }

你可能感兴趣的:(日常小工具,java,poi)