springboot之Docx4j操作pptx

springboot之Docx4j操作pptx

所有代码已经上传

一、引入依赖(清仔细阅读注释的部分 避免走弯路)

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.docx4j/docx4j -->
        <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j</artifactId>
            <version>6.1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.plutext</groupId>
                    <artifactId>jaxb-svg11</artifactId>
                </exclusion>
            </exclusions>
            <!--<exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>jcl-over-slf4j</artifactId>
                </exclusion>
            </exclusions>-->
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.sun.istack/istack-commons-runtime -->
        <dependency>
            <groupId>com.sun.istack</groupId>
            <artifactId>istack-commons-runtime</artifactId>
            <version>3.0.10</version>
        </dependency>
        <!--如果项目是运行在大于jdk8的情况下 需要添加一下两个依赖-->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.4.0-b180830.0359</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.4.0-b180830.0438</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.18</version>
        </dependency>
    </dependencies>

二、两种方式获取pptx文件

1、直接创建pptx文件

import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import java.io.File;

public class CreatePptx {
    public static void main(String[] args) throws Docx4JException {
// Create skeletal package
        PresentationMLPackage presentationMlPackage = PresentationMLPackage.createPackage();
        String outputfilepath = System.getProperty("user.dir") + "/CreatePptx.pptx";
        presentationMlPackage.save(new File(outputfilepath));
    }
}

2、从模版读取

import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import java.io.File;

public class ReadFromTemplate {

    public static void main(String[] args) throws Docx4JException {
        String inputfilepath =  System.getProperty("user.dir") + "/template/read-from-template.pptx";
        PresentationMLPackage presentationMlPackage = PresentationMLPackage.load(new File(inputfilepath));
        String outputfilepath = System.getProperty("user.dir") + "/out-pptx/read-from-template.pptx";
        presentationMlPackage.save(new File(outputfilepath));
    }
}

三、添加一段文字

文字的样式 位置等等取决于 SAMPLE_SHAPE字符串 至于这个字符串怎么获取 怎么去设置看上去是不是就很头大 没关系后面会教大家怎么制作这样的字符串

import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.PresentationML.MainPresentationPart;
import org.docx4j.openpackaging.parts.PresentationML.SlideLayoutPart;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.pptx4j.jaxb.Context;
import org.pptx4j.pml.Shape;

import java.io.File;

public class CreateHelloWorld {
	
	public static void main(String[] args) throws Exception {
		// Where will we save our new .ppxt?
		String outputfilepath = System.getProperty("user.dir") + "/out-pptx/pptx-test.pptx";
		// Create skeletal package, including a MainPresentationPart and a SlideLayoutPart
		PresentationMLPackage presentationMLPackage = PresentationMLPackage.createPackage(); 
		// Need references to these parts to create a slide
		// Please note that these parts *already exist* - they are
		// created by createPackage() above.  See that method
		// for instruction on how to create and add a part.
		MainPresentationPart pp = (MainPresentationPart)presentationMLPackage.getParts().getParts().get(
				new PartName("/ppt/presentation.xml"));		
		SlideLayoutPart layoutPart = (SlideLayoutPart)presentationMLPackage.getParts().getParts().get(
				new PartName("/ppt/slideLayouts/slideLayout1.xml"));
		// OK, now we can create a slide
		SlidePart slidePart = new SlidePart(new PartName("/ppt/slides/slide1.xml"));
		slidePart.setContents( SlidePart.createSld() );		
		pp.addSlide(0, slidePart);
		// Slide layout part
		slidePart.addTargetPart(layoutPart);
		// Create and add shape
		Shape sample = ((Shape)XmlUtils.unmarshalString(SAMPLE_SHAPE, Context.jcPML) );
		slidePart.getContents().getCSld().getSpTree().getSpOrGrpSpOrGraphicFrame().add(sample);
		// All done: save it
		presentationMLPackage.save(new File(outputfilepath));
		System.out.println("\n\n done .. saved " + outputfilepath);
	}

	private static String SAMPLE_SHAPE = 			
		"<p:sp   xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:p=\"http://schemas.openxmlformats.org/presentationml/2006/main\">"
		+ "<p:nvSpPr>"
		+ "<p:cNvPr id=\"4\" name=\"Title 3\" />"
		+ "<p:cNvSpPr>"
			+ "<a:spLocks noGrp=\"1\" />"
		+ "</p:cNvSpPr>"
		+ "<p:nvPr>"
			+ "<p:ph type=\"title\" />"
		+ "</p:nvPr>"
	+ "</p:nvSpPr>"
	+ "<p:spPr />"
	+ "<p:txBody>"
		+ "<a:bodyPr />"
		+ "<a:lstStyle />"
		+ "<a:p>"
			+ "<a:r>"
				+ "<a:rPr lang=\"en-US\" smtClean=\"0\" />"
				+ "<a:t>Hello World</a:t>"
			+ "</a:r>"
			+ "<a:endParaRPr lang=\"en-US\" />"
		+ "</a:p>"
	+ "</p:txBody>"
+ "</p:sp>";	
}

四、插入图片

import cn.hutool.core.util.RandomUtil;
import org.apache.commons.io.FileUtils;
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.PresentationML.MainPresentationPart;
import org.docx4j.openpackaging.parts.PresentationML.SlideLayoutPart;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.pptx4j.Pptx4jException;
import org.pptx4j.jaxb.Context;
import org.pptx4j.pml.Pic;
import javax.xml.bind.JAXBException;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

public class InsertPicture {


    public static void main(String[] args) throws Exception {
        String inputfilepath =  System.getProperty("user.dir") + "/template/img-template.pptx";
        PresentationMLPackage presentationMlPackage = PresentationMLPackage.load(new File(inputfilepath));
        //博主就长图片里面这样
        String imgPath = System.getProperty("user.dir") + "/img/WechatIMG66.jpeg";
        createImageChartSlide(presentationMlPackage,imgPath);
        System.out.println("\n\n saving .. \n\n");
        String outputfilepath = System.getProperty("user.dir") + "/out-pptx/img-test.pptx";
        presentationMlPackage.save(new File(outputfilepath));
        System.out.println("\n\n done .. \n\n");
    }

    /**
     * 创建对比分析图
     */
    private static void createImageChartSlide(PresentationMLPackage presentationMlPackage,String imgPath) throws Pptx4jException, JAXBException, InvalidFormatException {
        //两种方式
        //直接获取已经知道的某个页面
        SlidePart slidePart =
                presentationMlPackage.getMainPresentationPart().getSlide(0);
        //创建一个新的页面
        /*SlidePart slidePart = createCommonSlide(presentationMlPackage,"/ppt/slides/slide1.xml");*/
        try {
            createImage(presentationMlPackage, slidePart, FileUtils.readFileToByteArray(new File(imgPath)), RandomUtil.randomNumbers(5), 0, 0, 7560000, 10692000);
        } catch (IOException | JAXBException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param presentationMlPackage
     * @param slidePart 添加图片所在的页面
     * @param data 图片byte
     * @param x 坐标轴
     * @param y 坐标轴
     * @param cx 宽
     * @param cy 高
     */
    private static void createImage(PresentationMLPackage presentationMlPackage,
                                    SlidePart slidePart, byte[] data, String id, long x,
                                    long y, long cx, long cy) throws JAXBException {
        BinaryPartAbstractImage p_w_picpathPart = null;
        try {
            p_w_picpathPart = BinaryPartAbstractImage.createImagePart( presentationMlPackage, slidePart, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (p_w_picpathPart == null){
            return;
        }
        HashMap<String,Object> mappings = new HashMap<>();
        mappings.put("id1", id);
        mappings.put("name", "");
        mappings.put("descr", "");
        mappings.put("rEmbedId", p_w_picpathPart.getSourceRelationship().getId());
        // 注意,下面是图片位置的坐标
        mappings.put("offx", Long.toString(x)); //坐标轴
        mappings.put("offy", Long.toString(y));//坐标轴
        mappings.put("extcx", Long.toString(cx));//图片宽
        mappings.put("extcy", Long.toString(cy));//图片高
        Object o = XmlUtils.unmarshallFromTemplate(p_w_picpathXml, mappings, Context.jcPML, Pic.class);
        slidePart.getJaxbElement().getCSld().getSpTree() .getSpOrGrpSpOrGraphicFrame().add(o);
    }

    /**
     * 图片XML
     */
    private static final String p_w_picpathXml = "<p:pic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" "
            + "xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" "
            + "xmlns:p=\"http://schemas.openxmlformats.org/presentationml/2006/main\">"
            + "<p:nvPicPr><p:cNvPr id=\"${id1}\" name=\"${name}\" descr=\"${descr}\"/>"
            + "<p:cNvPicPr><a:picLocks noChangeAspect=\"1\"/></p:cNvPicPr><p:nvPr/></p:nvPicPr>"
            + "<p:blipFill><a:blip r:embed=\"${rEmbedId}\" cstate=\"print\"/><a:stretch><a:fillRect/>"
            + "</a:stretch></p:blipFill><p:spPr><a:xfrm><a:off x=\"${offx}\" y=\"${offy}\"/>"
            + "<a:ext cx=\"${extcx}\" cy=\"${extcy}\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/>"
            + "</a:prstGeom></p:spPr></p:pic>";

    static SlidePart createCommonSlide(PresentationMLPackage presentationMLPackage, String partName) throws InvalidFormatException, JAXBException {
        MainPresentationPart pp = (MainPresentationPart) presentationMLPackage.getParts().getParts().get(
                new PartName("/ppt/presentation.xml"));
        SlideLayoutPart layoutPart = (SlideLayoutPart) presentationMLPackage.getParts().getParts().get(
                new PartName("/ppt/slideLayouts/slideLayout1.xml"));
        return PresentationMLPackage.createSlidePart(pp, layoutPart,
                new PartName(partName));
    }
}

五、插入表格

样式类似于这样
在这里插入图片描述

import org.docx4j.dml.CTPoint2D;
import org.docx4j.dml.CTRegularTextRun;
import org.docx4j.dml.CTSRgbColor;
import org.docx4j.dml.CTSolidColorFillProperties;
import org.docx4j.dml.CTTable;
import org.docx4j.dml.CTTableCell;
import org.docx4j.dml.CTTableCellProperties;
import org.docx4j.dml.CTTableCol;
import org.docx4j.dml.CTTableGrid;
import org.docx4j.dml.CTTableProperties;
import org.docx4j.dml.CTTableRow;
import org.docx4j.dml.CTTextBody;
import org.docx4j.dml.CTTextCharacterProperties;
import org.docx4j.dml.CTTextParagraph;
import org.docx4j.dml.Graphic;
import org.docx4j.dml.GraphicData;
import org.docx4j.dml.TextFont;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.pptx4j.pml.CTGraphicalObjectFrame;

import javax.xml.bind.JAXBElement;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CreateTable {

    public static void main(String[] args) throws Exception {
        String inputfilepath = System.getProperty("user.dir") + "/template/table-template.pptx";
        PresentationMLPackage presentationMlPackage = PresentationMLPackage.load(new File(inputfilepath));
        //获取数据
        List<List<List<String>>> rowData = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            rowData.add(getData());
        }
        SlidePart slidePart = presentationMlPackage.getMainPresentationPart().getSlide(0);
        //往当前页面中添加表格
        createTablePackage(presentationMlPackage, slidePart, getData(), 457200, 1054400);
        String outfilepath = System.getProperty("user.dir") + "/out-pptx/table.pptx";
        presentationMlPackage.save(new File(outfilepath));
    }

    public static List<List<String>> getData() {
        List<List<String>> rowDatas = new ArrayList<>();
        List<String> totalAyTitle = Arrays.asList("Column1", "Column2", "Column3", "Column4", "Column1", "Column2", "Column3", "Column4", "Column1", "Column2", "Column3", "Column4");
        rowDatas.add(totalAyTitle);
        for (int i = 0; i < 15; i++) {
            rowDatas.add(Arrays.asList("A", "B", "C", "D", "A", "B", "C", "D", "A", "B", "C", "D"));
        }
        return rowDatas;
    }

    /**
     * 参考文章 https://blog.csdn.net/weixin_33858249/article/details/89902487
     *
     * @param presentationMLPackage
     * @param rowDatas              数据
     * @param AyX                   坐标轴x
     * @param AyY                   坐标轴y
     * @throws Exception
     */
    public static void createTablePackage(PresentationMLPackage presentationMLPackage, SlidePart slidePart, List<List<String>> rowDatas, int AyX, int AyY) throws Exception {
        createStTableSlide(presentationMLPackage, slidePart, rowDatas, AyX, AyY);
    }

    /**
     * 创建表格
     */
    private static void createStTableSlide(
            PresentationMLPackage presentationMLPackage, SlidePart slidePart, List<List<String>> rowDatas, int AyX, int AyY) throws Exception {
        createTable(slidePart, rowDatas, AyX, AyY);
    }

    /**
     * @param slidePart
     * @param rowDatas
     * @param x
     * @param y
     */
    private static void createTable(SlidePart slidePart, List<List<String>> rowDatas, int x, int y) {
        org.docx4j.dml.ObjectFactory objectFactory = new org.docx4j.dml.ObjectFactory();
        org.pptx4j.pml.ObjectFactory graphicObjectFactory = new org.pptx4j.pml.ObjectFactory();
        CTGraphicalObjectFrame graphicFrame = graphicObjectFactory.createCTGraphicalObjectFrame();
        org.pptx4j.pml.CTGraphicalObjectFrameNonVisual nvGraphicFramePr = graphicObjectFactory.createCTGraphicalObjectFrameNonVisual();
        org.docx4j.dml.CTNonVisualDrawingProps cNvPr = objectFactory.createCTNonVisualDrawingProps();
        org.docx4j.dml.CTNonVisualGraphicFrameProperties cNvGraphicFramePr = objectFactory.createCTNonVisualGraphicFrameProperties();
        org.docx4j.dml.CTGraphicalObjectFrameLocking graphicFrameLocks = objectFactory.createCTGraphicalObjectFrameLocking();
        org.docx4j.dml.CTTransform2D xfrm = objectFactory.createCTTransform2D();
        // 设置表格的位置
        CTPoint2D ctPoint = objectFactory.createCTPoint2D();
        ctPoint.setX(x);
        ctPoint.setY(y);
        xfrm.setOff(ctPoint);
        Graphic graphic = objectFactory.createGraphic();
        GraphicData graphicData = objectFactory.createGraphicData();

        // 设置表格样式1
        CTTable ctTable = objectFactory.createCTTable();
        CTTableProperties ctTablePr = objectFactory.createCTTableProperties();
        ctTablePr.setFirstRow(true);
        ctTablePr.setBandRow(true);
        ctTable.setTblPr(ctTablePr);


        JAXBElement<CTTable> tbl = objectFactory.createTbl(ctTable);
        CTTableGrid ctTableGrid = objectFactory.createCTTableGrid();
        graphicFrame.setNvGraphicFramePr(nvGraphicFramePr);
        nvGraphicFramePr.setCNvPr(cNvPr);
        cNvPr.setName("1");
        nvGraphicFramePr.setCNvGraphicFramePr(cNvGraphicFramePr);
        cNvGraphicFramePr.setGraphicFrameLocks(graphicFrameLocks);
        graphicFrameLocks.setNoGrp(true);
        nvGraphicFramePr.setNvPr(graphicObjectFactory.createNvPr());
        graphicFrame.setXfrm(xfrm);
        xfrm.setExt(objectFactory.createCTPositiveSize2D());
        graphicFrame.setGraphic(graphic);
        graphic.setGraphicData(graphicData);
        graphicData
                .setUri("http://schemas.openxmlformats.org/drawingml/2006/table");
        graphicData.getAny().add(tbl);
        ctTable.setTblGrid(ctTableGrid);

        int rowCells = rowDatas.get(0).size();
        int cellWidth = 6645600 / rowCells;
        for (int i = 0; i < rowCells; i++) {
            ctTableGrid.getGridCol().add(createCol(cellWidth, objectFactory));
        }
        for (int j = 0; j < rowDatas.size(); j++) {
            if ((j + 1) % 5 == 0 || j == 0) {
                ctTable.getTr().add(createRow(rowDatas.get(j), objectFactory, "EFF4FF"));
            } else {
                ctTable.getTr().add(createRow(rowDatas.get(j), objectFactory, "FFFFFF"));
            }
        }
        slidePart.getJaxbElement().getCSld().getSpTree()
                .getSpOrGrpSpOrGraphicFrame().add(graphicFrame);
    }

    /**
     * @param width
     * @return
     */
    private static CTTableCol createCol(int width, org.docx4j.dml.ObjectFactory objectFactory) {
        CTTableCol gridCol = objectFactory.createCTTableCol();
        gridCol.setW(width);
        return gridCol;
    }

    /**
     * @param datas
     * @return
     */
    private static CTTableRow createRow(List<String> datas, org.docx4j.dml.ObjectFactory objectFactory, String sRgb) {
        CTTableRow ctTableRow = objectFactory.createCTTableRow();
        for (String data : datas) {
            ctTableRow.getTc().add(createCell(data, objectFactory, sRgb));
        }
        return ctTableRow;
    }

    /**
     * @param value
     * @return
     */
    private static CTTableCell createCell(String value, org.docx4j.dml.ObjectFactory objectFactory, String sRgb) {
        CTTableCell ctTableCell = objectFactory.createCTTableCell();
        // 单元格文字
        CTTextBody ctTextBody = objectFactory.createCTTextBody();
        ctTextBody.setBodyPr(objectFactory.createCTTextBodyProperties());
        ctTextBody.setLstStyle(objectFactory.createCTTextListStyle());
        CTTextParagraph ctTextPr = objectFactory.createCTTextParagraph();
        CTRegularTextRun run = objectFactory.createCTRegularTextRun();
        CTTextCharacterProperties ctTpr = objectFactory
                .createCTTextCharacterProperties();
        // 14号字体
        ctTpr.setSz(1200);
        TextFont font = objectFactory.createTextFont();
        font.setTypeface("微软雅黑");
        ctTpr.setLatin(font);
        ctTpr.setEa(font);
        run.setRPr(ctTpr);
        // 设置内容,不能为null
        run.setT(value == null ? "" : value);
        ctTextPr.getEGTextRun().add(run);
        ctTextPr.setEndParaRPr(objectFactory.createCTTextCharacterProperties());
        ctTextBody.getP().add(ctTextPr);
        ctTableCell.setTxBody(ctTextBody);
        CTTableCellProperties ctTableCellProperties = objectFactory.createCTTableCellProperties();
        CTSolidColorFillProperties ctSolidColorFillProperties = objectFactory.createCTSolidColorFillProperties();
        CTSRgbColor ctsRgbColor = new CTSRgbColor();
//        ctsRgbColor.setVal("EFF4FF");
        //单元格的颜色
        ctsRgbColor.setVal(sRgb);
        ctSolidColorFillProperties.setSrgbClr(ctsRgbColor);
        ctTableCellProperties.setSolidFill(ctSolidColorFillProperties);
        ctTableCell.setTcPr(ctTableCellProperties);
        return ctTableCell;
    }
}

六、占位符替换

import org.apache.commons.io.FileUtils;
import org.docx4j.TraversalUtil;
import org.docx4j.TraversalUtil.CallbackImpl;
import org.docx4j.dml.CTBlip;
import org.docx4j.dml.CTBlipFillProperties;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.OpcPackage;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.pptx4j.Pptx4jException;

import javax.xml.bind.JAXBException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class TemplateReplaceSimple {
	
	public static void main(String[] args) throws Docx4JException, Pptx4jException, JAXBException, IOException {
		
		// Input file
		String inputfilepath = System.getProperty("user.dir") + "/template/template-replace.pptx";
		String imgPath = System.getProperty("user.dir") + "/img/Snipaste_2023-10-16_13-40-23.png";

		// String replacements
		HashMap<String, String> mappings = new HashMap<String, String>();
		mappings.put("colour", "red");

		// Image replacements
		List<ImageReplacementDetails>  imageReplacements = new ArrayList<ImageReplacementDetails>();
		
		ImageReplacementDetails example1 = new ImageReplacementDetails();
		example1.slideIndex = 0; //图片所在页面
		example1.imageRelId = "rId1"; //至于这个 我也不是特别理解 但是大致猜测如下 pptx中有几张图片
		example1.replacementImageBytes = FileUtils.readFileToByteArray(new File(imgPath));
		imageReplacements.add(example1);
		
		
		
		PresentationMLPackage presentationMLPackage = 
				(PresentationMLPackage)OpcPackage.load(new File(inputfilepath));
			
		
		// First, the text replacements
		List<SlidePart> slideParts= 
				presentationMLPackage.getMainPresentationPart().getSlideParts();
		for (SlidePart slidePart : slideParts) {
			
			slidePart.variableReplace(mappings);
		}
		
		
		// Second, the image replacements.
		// We have a design choice here.  
		// Either we can replace text placeholders with images,
		// or we can replace existing images with new images, but keep the XML specifying size etc
		// Here I opt for the latter, so what we need is the relId and image bytes.
		for( ImageReplacementDetails ird : imageReplacements) {
			
			// its a bit inefficient to potentially traverse a single slide
			// multiple times, but I've done it this way to keep this example simple
			SlidePart slidePart= 
					presentationMLPackage.getMainPresentationPart().getSlide(ird.slideIndex);
						
			SlidePicFinder traverser = new SlidePicFinder();
			new TraversalUtil(slidePart.getJaxbElement().getCSld().getSpTree().getSpOrGrpSpOrGraphicFrame(), traverser);
			
			for(org.pptx4j.pml.Pic pic : traverser.pics) {
				
				CTBlipFillProperties  blipFill = pic.getBlipFill();
				if (blipFill!=null) {
					CTBlip blip = blipFill.getBlip();
					if (blip.getEmbed()!=null) {
						String relId = blip.getEmbed();
						
						// is this the one we want?
						if (relId.equals(ird.imageRelId)) {
							Part part = slidePart.getRelationshipsPart().getPart(relId);
							try {
								BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage)part;
								// you'll need to ensure that you replace like with like,
								// ie png for png, not eg jpeg for png!
								imagePart.setBinaryData(ird.replacementImageBytes);
							} catch (ClassCastException cce) {
								System.out.println(part.getClass().getName());
							}
						} else {
							System.out.println(relId + " isn't a match for this replacement. ");							
						}
					} else {
						System.out.println("No a:blip/@r:embed");
					}
				}
			}
		}
		
		System.out.println("\n\n saving .. \n\n");
		String outputfilepath = System.getProperty("user.dir") + "/out-pptx/OUT_VariableReplace.pptx";
		presentationMLPackage.save(new File(outputfilepath));

		System.out.println("\n\n done .. \n\n");
		
		
	}
	
	static class ImageReplacementDetails {
		
		int slideIndex;
		
		String imageRelId;
		
		byte[] replacementImageBytes;
		
	}
	

	static class SlidePicFinder extends CallbackImpl {
		List<org.pptx4j.pml.Pic> pics = new ArrayList<org.pptx4j.pml.Pic>();
		public List<Object> apply(Object o) {

			if (o instanceof org.pptx4j.pml.Pic) {
				pics.add((org.pptx4j.pml.Pic) o);
				System.out.println("added pic");
			}
			return null;
		}
	}
}

七、pptx to xml

此处将设计好的pptx模版转换成XML格式,可以通过截取某一段XML代码作为三、添加一段文字插入的内容 经测试,只要你在模版中的样式设计好,添加一段文字的样式也会是一摸一样的
注意:截取的一点XML 可能需要你加上类似于如下的头部标签:
xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:p=\"http://schemas.openxmlformats.org/presentationml/2006/main\">

可以参考CreateHelloWorld SAMPLE_SHAPE字符串

import org.apache.commons.io.FileUtils;
import org.docx4j.convert.out.flatOpcXml.FlatOpcXmlCreator;
import org.docx4j.openpackaging.packages.OpcPackage;

import java.io.File;


public class ConvertOutFlatOpenPackage {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {

        String inputfilepath = System.getProperty("user.dir") + "/template/out-xml-template.pptx";
        OpcPackage pptxPackage = OpcPackage.load(new File(inputfilepath));

        FlatOpcXmlCreator worker = new FlatOpcXmlCreator(pptxPackage);

        org.docx4j.xmlPackage.Package result = worker.get();

        boolean suppressDeclaration = true;
        boolean prettyprint = true;


        String data =
                org.docx4j.XmlUtils.
                        marshaltoString(result, suppressDeclaration, prettyprint,
                                org.docx4j.jaxb.Context.jcXmlPackage);

        FileUtils.writeStringToFile(
                new File(System.getProperty("user.dir") + "/out-pptx/pptx.xml"),
                data);


    }

}

八、页面删除

我有这样一个需求,模版pptx中有某些固定的页面,但是这些页面是需要根据用户的选择去显示的,所以我需要根据用户的选择删除那些不需要的页面。

import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.PresentationML.MainPresentationPart;
import org.pptx4j.Pptx4jException;

import java.io.File;

public class RemoveSlide {

    public static void main(String[] args) throws Docx4JException, Pptx4jException {
        String inputfilepath = System.getProperty("user.dir") + "/template/remove.pptx";
        PresentationMLPackage presentationMlPackage = PresentationMLPackage.load(new File(inputfilepath));
        MainPresentationPart mainPresentationPart = presentationMlPackage.getMainPresentationPart();

        //至于这里为什么是1 或者 是 rId3 是需要自己通过 ConvertOutFlatOpenPackage 方式转换成xml 然后自己去判断的
        //方式1
        mainPresentationPart.removeSlide(1);
        //方式2
//        Relationship rel = mainPresentationPart.getRelationshipsPart().getRelationshipByID("rId3");
//        mainPresentationPart.removeSlide(rel);

        System.out.println("\n\n saving .. \n\n");
        String outputfilepath = System.getProperty("user.dir") + "/out-pptx/remove-later.pptx";
        presentationMlPackage.save(new java.io.File(outputfilepath));

        System.out.println("\n\n done .. \n\n");
    }
}

九、在某个页面后面插入一个页面

import org.docx4j.XmlUtils;
import org.docx4j.dml.CTShapeProperties;
import org.docx4j.dml.CTTextParagraph;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.PresentationMLPackage;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.PresentationML.MainPresentationPart;
import org.docx4j.openpackaging.parts.PresentationML.SlideLayoutPart;
import org.docx4j.openpackaging.parts.PresentationML.SlidePart;
import org.pptx4j.Pptx4jException;
import org.pptx4j.jaxb.Context;
import org.pptx4j.pml.Shape;
import org.pptx4j.pml.Sld;
import org.pptx4j.pml.SldLayout;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class AddSlideIndex {

    public static void main(String[] args) throws Docx4JException, Pptx4jException {
        String inputfilepath = System.getProperty("user.dir") + "/template/add-slide.pptx";
        PresentationMLPackage presentationMlPackage = PresentationMLPackage.load(new File(inputfilepath));
        MainPresentationPart pp = presentationMlPackage.getMainPresentationPart();

        SlideLayoutPart layoutPart = (SlideLayoutPart)presentationMlPackage.getParts().getParts().get(
                new PartName("/ppt/slideLayouts/slideLayout1.xml"));

        // OK, now we can create a slide
        SlidePart slidePart = new SlidePart(new PartName("/ppt/slides/slide1.xml"));
        int index = 1;
        pp.addSlide(index, slidePart);

        // Slide layout part
        slidePart.addTargetPart(layoutPart);

        // Copy certain placeholders from layout part
        slidePart.setContents( extractFromLayout(layoutPart.getContents())  );
        String outputfilepath = System.getProperty("user.dir") + "/out-pptx/add-slide.pptx";
        presentationMlPackage.save(new java.io.File(outputfilepath));
    }

    private static Sld extractFromLayout(SldLayout sldLayout) {
//        SlidePlaceholder.sldLayout = sldLayout;

        Sld sld = Context.getpmlObjectFactory().createSld();

        // Clone first
        sld.setCSld(XmlUtils.deepCopy(sldLayout.getCSld(), Context.jcPML));
        sld.setClrMapOvr(XmlUtils.deepCopy(sldLayout.getClrMapOvr(), Context.jcPML));

        // Then delete stuff
        sld.getCSld().setName(null);

        // Remove p:sp, if cNvPr name contains "Date Placeholder", "Footer Placeholder", "Slide Number Placeholder"
        //       (and these are on the master?)
        List<Shape> deletions = new ArrayList<Shape>();
        for (Object o : sld.getCSld().getSpTree().getSpOrGrpSpOrGraphicFrame()) {

            //System.out.println(o.getClass().getName());
            if (o instanceof Shape) {

                Shape shape = (Shape)o;
                if (shape.getNvSpPr()!=null
                        && shape.getNvSpPr().getCNvPr()!=null
                        && shape.getNvSpPr().getCNvPr().getName()!=null) {
                    String name = shape.getNvSpPr().getCNvPr().getName();
                    if (name.startsWith("Date Placeholder" )
                            || name.startsWith( "Footer Placeholder" )
                            || name.startsWith( "Slide Number Placeholder")) {

                        deletions.add(shape);
                    }

                }
            }
        }
        sld.getCSld().getSpTree().getSpOrGrpSpOrGraphicFrame().removeAll(deletions);

        // From remaining shapes ..
        for (Object o : sld.getCSld().getSpTree().getSpOrGrpSpOrGraphicFrame()) {
            if (o instanceof Shape) {
                Shape shape = (Shape)o;
                shape.setSpPr(new CTShapeProperties());
                if (shape.getTxBody()!=null) {

                    shape.getTxBody().setLstStyle(null);

                    for (CTTextParagraph p : shape.getTxBody().getP()) {
                        p.getEGTextRun().clear();
                    }
                }
            }
        }
        return sld;
    }
}

注意事项

  • 模版的样式(纸张大小、页边距等等 提前在WPS或者Office中设置好)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值