当前位置: 首页 > article >正文

easypoi模板导出word多页导出加强版

说明

上一篇文章提到多页导出,但是后边发现一个问题,如果用同一个模板导出多页内容,我们去获取多页内容的时候,会发现全部都一样,举个例子:

XWPFDocument document = WordExportUtil.exportWord07(outputUrl, maps);
List<XWPFTable> tables = document.getTables();
List<XWPFParagraph> paragraphs = document.getParagraphs();

通过上边的代码,不管获取tables 还是paragraphs,集合里边的内容都是一样的,而且表格只有一张,即使你导出的时候多页都有表格,但是代码获取的时候就只有一张表。

另一个问题,就是,到处之后会莫名多出一个空白页。

在这里插入图片描述

解决问题

因为获取不到除第一页的其他页内容,那么照这个方法就没办法了,那么只能转变思路,导出多页,那么就让多页数据在导出的时候独立起来,也就是说我们创建出多个XWPFDocument,最后把这些XWPFDocument合并起来,不再使用前一篇文章提到的官方方法exportWord07(String url, List<Map<String, Object>> list)了,这样不仅可以解决多页内容获取不到的问题,还能解决另一个问题(导出的word总是多出一页空白页)。

具体操作

创建工具类:

import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.springframework.util.CollectionUtils;
 
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * WordUtils
 *
 * @author ZENG.XIAO.YAN
 * @version 1.0
 * @Date 2019-09-20
 */
public final class WordUtils {
 
    /**
     * word文件合并
     * @param wordList
     * @return
     * @throws Exception
     */
    public static  XWPFDocument mergeWord(List<XWPFDocument> wordList) throws Exception{
        if (CollectionUtils.isEmpty(wordList)) {
            throw  new RuntimeException("待合并的word文档list为空");
        }
        XWPFDocument doc = wordList.get(0);
        int size = wordList.size();
        if (size > 1) {
            //不要设置分页符,否则第二页第一行总会多出一个换行符,具体需不需要根据自己的需求来定
            doc.createParagraph().setPageBreak(false);
            for (int i = 1; i < size; i++) {
                // 从第二个word开始合并
                XWPFDocument nextPageDoc = wordList.get(i);
                // 最后一页不需要设置分页符
                if (i != (size-1)) {
                    nextPageDoc.createParagraph().setPageBreak(false);
                }
                appendBody(doc, nextPageDoc);
            }
        }
        return doc;
    }
 
    private static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID
        Map<String,String> map = new HashMap<>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after);
        }
        appendBody(src1Body, src2Body,map);
 
    }
 
    private static void appendBody(CTBody src, CTBody append,Map<String,String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);
        String srcString = src.xmlText();
        String prefix = srcString.substring(0,srcString.indexOf(">")+1);
        String mainPart = srcString.substring(srcString.indexOf(">")+1,srcString.lastIndexOf("<"));
        String sufix = srcString.substring( srcString.lastIndexOf("<") );
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
        }
        //将两个文档的xml内容进行拼接
        CTBody makeBody = CTBody.Factory.parse(prefix+mainPart+addPart+sufix);
        src.set(makeBody);
    }
 
}

关键代码:

//用来装每个需要合并的XWPFDocument
List<XWPFDocument> wordList = new ArrayList<>();
XWPFDocument document = WordExportUtil.exportWord07(outputUrl, map);
XWPFTable table = document.getTables().get(0);
   for (int row = 4; row <= table.getNumberOfRows() - 4; row++) {
       // 从第二行开始,合并上一行和当前行
       XWPFTableRow row1 = table.getRow(row);
       if (row == 4) {
           XWPFTableCell cell = row1.getCell(6);
           cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
           cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
           cell.setText("根据物资的形状、性能、特点、数量、重量进行五五式合理摆放,必须做到稳固、定量、整理、方便和安全");
       } else if (row == table.getNumberOfRows() - 4) {
           XWPFTableCell cell = row1.getCell(7);
           CTTc ctTc = cell.getCTTc();
           if (ctTc != null) {
               CTTcPr tcPr = ctTc.getTcPr();
               if (tcPr == null) {
                   tcPr = ctTc.addNewTcPr();
               }
               if (tcPr.getVMerge() == null) {
                   tcPr.addNewVMerge();
               }
               tcPr.getVMerge().setVal(STMerge.CONTINUE);
           }
           cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
       } else {
           XWPFTableCell cell = row1.getCell(10);
           CTTc ctTc = cell.getCTTc();
           if (ctTc != null) {
               CTTcPr tcPr = ctTc.getTcPr();
               if (tcPr == null) {
                   tcPr = ctTc.addNewTcPr();
               }
               if (tcPr.getVMerge() == null) {
                   tcPr.addNewVMerge();
               }
               tcPr.getVMerge().setVal(STMerge.CONTINUE);
           }
           cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
       }
   }
   wordList.add(document);
}

http://www.kler.cn/a/280492.html

相关文章:

  • pikachu靶场通关攻略(XSS)(1~10关)
  • 【AI绘画】Midjourney前置指令/settings设置详解
  • MyBatis使用递归查询来实现多级菜单的功能
  • 从黑神话悟空看中医养生,各位“天命人”中医养生不了解一下吗?
  • 考研资讯平台
  • Linux3-Linux用户和权限
  • [每日一练]重新格式化部门表(分组聚合的思考)
  • 实习手记(8):增删改查
  • redis 主从及哨兵搭建
  • C++11中的decltype关键字
  • 特殊类设计和类型转换
  • Golang反射:运行时类型检查与操作
  • 亲测分享:这个获客工具,精准又好用!
  • 《计算机网络期末复习知识点大全》
  • C++操作excel,即使函数设置了不备份,但保存后,excel依然会自动生成备份文件的原因分析,及如何来禁止自动备份
  • 10. Java 中的 HashSet 和 HashMap 有什么区别?
  • 模拟实现STL中的unordered_map和unordered_set
  • Android PopupWindow弹窗动态显示在View的上下方,
  • 【STM32】MDK安装
  • 【C++】使用C++手动封装一个顺序表,包含成员数组一个,成员变量N个