如何使用Docx4J合并docx及pptx文档

Docx4j

docx4j是一个用于处理OOXML(office open xml)文档(如docx、pptx等文档)的库,功能非常强大,其基础部分是开源的,但一些高级功能是需要商业授权,比如文档的合并等功能。

网络上也有其它合并的方式,但并不好用,那么使用docx4j的商业授权部分来做是什么情况呢?

下面的代码是基于docx4j企业版的试用版(Plutext-Enterprise-3.3.0.6-trial)。

合并多个docx文档

public class MergeWholeDocumentsUsingBlockRange {

    public final static String DIR_IN = System.getProperty("user.dir")+ "/src/samples/MergeDocx/resources/";
    public final static String DIR_OUT = System.getProperty("user.dir")+ "/";

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

        String[] files = {"IntegersOnly.docx", "UN-Declaration.docx" , "SolarSystem.docx"};


        List<BlockRange> blockRanges = new ArrayList<BlockRange>();
        for (int i=0 ; i< files.length; i++) {
            BlockRange block = new BlockRange(WordprocessingMLPackage.load(
                    new File(DIR_IN + files[i])));
            blockRanges.add( block );

            // No pages breaks
            block.setSectionBreakBefore(SectionBreakBefore.CONTINUOUS);

            // if you want no headers on the pages from docx2:
            block.setHeaderBehaviour(HfBehaviour.NONE);

            if (i==1) {
                block.setStyleHandler(StyleHandler.RENAME_RETAIN);
            }
        }

        // Perform the actual merge
        DocumentBuilder documentBuilder = new DocumentBuilder();
        WordprocessingMLPackage output = documentBuilder.buildOpenDocument(blockRanges);

        // Save the result
        Docx4J.save(output, 
                new File(DIR_OUT+"OUT_MergeWholeDocumentsUsingBlockRange.docx"), 
                Docx4J.FLAG_NONE);      


    }   
}

上面的代码是摘自Plutext-Enterprise-3.3.0.6试用版示例代码,代码非常简单,不需要什么解释;当然除了这段标准代码外在合并时还可以设置一些特殊的参数。

合并pptx文档

public class MergeWholePresentations {

    public final static String DIR_IN = "D:/docx/";
    public final static String DIR_OUT = "D:/";

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

        long startMS = System.currentTimeMillis();

        String[] deck = {
                "1.pptx" ,"2.pptx", "3.pptx",
        };

        PresentationBuilder builder = new PresentationBuilder();

        for (int i=0 ; i< deck.length; i++) {

            System.out.println("\n\n loading " + i + "  " + deck[i] + "\n\n");

            // Create a SlideRange representing the slides in this pptx
            SlideRange sr = new SlideRange(
                    (PresentationMLPackage)OpcPackage.load(new File(DIR_IN + deck[i])));
            sr.setName(i+ " " + deck[i]);  // PkgIdentifier for ListeningBean

            // Add the slide range to the output
            builder.addSlideRange(sr);
        }

        builder.getResult().save(new File("D:\\e.pptx"));

        // The times above don't include various things, such as Context init, and saving the final docx
        long elapsedMS = System.currentTimeMillis() - startMS;
        int secs = Math.round(elapsedMS/1000);
        System.out.println("time taken: " + secs + "secs");
    }
}

上面的pptx合并代码基本也是示例代码,只是作了一些简化。

水印

由于需要商业授权,因此上面代码合并结果都给加了水印,如下图所示:

docx合并水印

pttx合并水印

其实仔细分析一下,上面合并文档中的水印都是文档中的一个元素,完全可以将其去掉,但如果文档太大,可能去除过程比较慢。

这里涉及到ooxml的原理,本人也不是很熟悉;如果有兴趣可以去了解一下,本质上一个docx(或pptx)文档就是一堆xml文件压缩到一个文件中,这些xml中定义了该文档所有细节;其中这里的水印也是一段XML代码,我们只需要分析一下合并的结果,找到并删除即可。

去水印

在合并后的docx文档中,水印是一个段落结构,所以我们只需要分析所有段落找到目标段落即可。

下面的代码可以获取文档中所有段落:

// 递归方法,获取给定对象下所有符合条件的对象
private static <T> List<T> getAllElementFromObject(Object obj, Class<T> toSearch) {
    List<T> result = new ArrayList<>();
    if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();

    if (obj.getClass().equals(toSearch)) {
        result.add(toSearch.cast(obj));
    } else if (obj instanceof ContentAccessor) {
        List<?> children = ((ContentAccessor) obj).getContent();
        for (Object child : children) {
            result.addAll(getAllElementFromObject(child, toSearch));
        }
    }
    return result;
}

调用代码:

List<P> pList = getAllElementFromObject(documentPart, P.class);

而在合并的pptx文档中,是每页都有水印的,因此可以分析所有幻灯片,找到目标Shape结构(pptx文档中水印是一个Shape)删除即可。

由于涉及到商业授权,这里就不放完整代码了;不过根据这个思路,去除其实是很容易的。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值