栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java docx4j 操作word 2.1

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java docx4j 操作word 2.1

 一、简介

      本工具类复制即可使用,内附测试代码,包含以下操作:

      -- word 中 属性值替换

      -- word 中 列表动态插入数据

      -- word 转 pdf

      -- 版本更新:

          1、链式调用

          2、方法解耦

二、环境


    com.itextpdf
    itextpdf
    5.5.13.2


    freemarker
    freemarker
    2.3.8


    org.docx4j
    docx4j
    6.1.2


    org.docx4j
    docx4j-export-fo
    8.1.7 //版本号不能高于8.1.7

  

    net.sf.barcode4j
    barcode4j-light
    2.0


    javax.xml.bind
    jaxb-api
    2.3.1



    javax.activation
    activation
    1.1



    org.glassfish.jaxb
    jaxb-runtime
    2.3.5

三、工具类

package com.dily.scaffold.common.utils;

import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import org.docx4j.Docx4J;
import org.docx4j.TraversalUtil;
import org.docx4j.XmlUtils;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.ClassFinder;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.jaxb.Context;
import org.docx4j.model.datastorage.migration.VariablePrepare;
import org.docx4j.model.table.TblFactory;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.*;
import org.springframework.core.io.ClassPathResource;

import javax.xml.bind.JAXBElement;
import java.io.*;
import java.util.*;


public class Docx4jUtils {

    public static WordOption getWordOption() {
        return new WordOption();
    }

    
    public static List getAllElementFromObject(List context, Class toSearch) {
        List result = new ArrayList<>();
        for (Object obj : context) {
            if (obj instanceof JAXBElement)
                obj = ((JAXBElement) obj).getValue();
            if (obj.getClass().equals(toSearch))
                result.add(obj);
            else if (obj instanceof ContentAccessor) {
                List children = ((ContentAccessor) obj).getContent();
                getAllElementFromObject(children, toSearch);
            }
        }
        return result;
    }

    
    public static String Docx2Pdf(String wordPath) {
        OutputStream os = null;
        InputStream is = null;
        //输出pdf文件路径和名称
        String pdfNoMarkPath = wordPath.substring(0, wordPath.indexOf('.')) + ".pdf";
        try {
            is = new FileInputStream(wordPath);
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
            Mapper fontMapper = new IdentityPlusMapper();
            fontMapper.put("等线", PhysicalFonts.get("SimSun"));
            fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
            fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
            fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
            fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
            fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
            fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
            fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
            fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
            fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
            fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
            fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
            fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
            fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
            fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
            fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
            fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
            fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
            fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
            fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
            fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
            fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
            fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
            fontMapper.put("新細明體", PhysicalFonts.get("SimSun"));
            PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));            //解决宋体(正文)和宋体(标题)的乱码问题
            PhysicalFonts.put("新細明體", PhysicalFonts.get("SimSun"));
            fontMapper.put("SimSun", PhysicalFonts.get("SimSun"));             //宋体&新宋体
            mlPackage.setFontMapper(fontMapper);

            os = new FileOutputStream(pdfNoMarkPath);

            //docx4j  docx转pdf
            FOSettings foSettings = Docx4J.createFOSettings();
            foSettings.setWmlPackage(mlPackage);
            Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);

            is.close();//关闭输入流
            os.close();//关闭输出流

            return pdfNoMarkPath;
        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } finally {
            File file = new File(wordPath);
            if (file.isFile() && file.exists()) {
                file.delete();
            }
        }
        return "";
    }

    
    public static String addTextMark(String inPdfPath, String markPath) {
        PdfStamper stamp = null;
        PdfReader reader = null;
        try {
            //输出pdf带水印文件路径和名称
            String outPdfMarkPath = inPdfPath.substring(0, inPdfPath.indexOf('.')) + "水印.pdf";

            //添加水印
            reader = new PdfReader(inPdfPath, "PDF".getBytes());
            stamp = new PdfStamper(reader, new FileOutputStream(outPdfMarkPath));
            PdfContentByte under;
            int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
            //水印图片
            Image image;
            if (markPath.contains(":"))
                image = Image.getInstance(markPath);
            else {
                ClassPathResource resource = new ClassPathResource(markPath);
                image = Image.getInstance(resource.getFile().getPath());
            }
            for (int i = 1; i <= pageSize; i++) {
                under = stamp.getOverContent(i);// 水印在之前文本下
                for (int j = 0; j < 4; j++) {
                    image.setAbsolutePosition(0, j * 250 + 100);//水印位置
                    under.addImage(image);
                    image.setAbsolutePosition(200, j * 250 + 100);//水印位置
                    under.addImage(image);
                    image.setAbsolutePosition(400, j * 250 + 100);//水印位置
                    under.addImage(image);
                }
            }
            stamp.close();// 关闭
            reader.close();//关闭

            return outPdfMarkPath;
        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (stamp != null) {
                    stamp.close();
                }
                if (reader != null) {
                    reader.close();//关闭
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } finally {
            //删除生成的无水印pdf
            File file = new File(inPdfPath);
            if (file.exists() && file.isFile()) {
                file.delete();
            }
        }
        return "";
    }

    
    public static class WordOption {

        private static WordprocessingMLPackage wordMLPackage;

        public WordprocessingMLPackage getWordMLPackage() {
            return wordMLPackage;
        }

        
        public WordOption createDocx() throws Docx4JException {
            wordMLPackage = WordprocessingMLPackage.createPackage();
            return this;
        }

        
        public WordOption loadDocx(String filePath) throws Docx4JException {
            wordMLPackage = WordprocessingMLPackage.load(new File(filePath));
            return this;
        }

        
        public WordOption addContext(String styled, String conText) {
            wordMLPackage.getMainDocumentPart().addStyledParagraphOfText(styled, conText);
            return this;
        }

        
        public WordOption addContext(String conText) {
            wordMLPackage.getMainDocumentPart().addParagraphOfText(conText);
            return this;
        }

        
        public WordOption addImage(String imagePath) throws Exception {
            BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, new File(imagePath));
            Inline inline = imagePart.createImageInline("Filename hint", "Alternative text", 1, 2, false);
            ObjectFactory factory = new ObjectFactory();
            P paragraph = factory.createP();
            R run = factory.createR();
            paragraph.getContent().add(run);
            Drawing drawing = factory.createDrawing();
            run.getContent().add(drawing);
            drawing.getAnchorOrInline().add(inline);
            wordMLPackage.getMainDocumentPart().addObject(paragraph);
            return this;
        }

        
        public WordOption addTable(int row, int col) {
            Tbl table = TblFactory.createTable(row, col, 20000 / col);
            wordMLPackage.getMainDocumentPart().addObject(table);
            return this;
        }

        
        public WordOption addTableWithDataAndTopHeader(List> list) {
            Set keySet = new HashSet<>(list.get(0).keySet());
            ObjectFactory factory = Context.getWmlObjectFactory();
            Tbl table = TblFactory.createTable(0, 0, 20000 / list.get(0).size());

            // 表头
            Tr tableHeader = factory.createTr();
            keySet.forEach(e -> {
                Tc tableCell = factory.createTc();
                tableCell.getContent().add(wordMLPackage.getMainDocumentPart().createParagraphOfText(e));
                tableHeader.getContent().add(tableCell);
            });
            table.getContent().add(tableHeader);

            // 数据
            list.forEach(e -> {
                Tr tableRow = factory.createTr();
                keySet.forEach(item -> {
                    Tc tableCell = factory.createTc();
                    tableCell.getContent().add(wordMLPackage.getMainDocumentPart().createParagraphOfText(e.get(item)));
                    tableRow.getContent().add(tableCell);
                });
                table.getContent().add(tableRow);
            });
            wordMLPackage.getMainDocumentPart().addObject(table);
            return this;
        }

        
        public WordOption addTableWithDataAndLeftHeader(List> list) {
            Set keySet = new HashSet<>(list.get(0).keySet());
            ObjectFactory factory = Context.getWmlObjectFactory();
            Tbl table = TblFactory.createTable(0, 0, 20000 / list.get(0).size());
            keySet.forEach(e -> {
                Tr tableRow = factory.createTr();
                Tc tableHeader = factory.createTc();
                tableHeader.getContent().add(wordMLPackage.getMainDocumentPart().createParagraphOfText(e));
                tableRow.getContent().add(tableHeader);
                list.forEach(item -> {
                    Tc tableCell = factory.createTc();
                    tableCell.getContent().add(wordMLPackage.getMainDocumentPart().createParagraphOfText(item.get(e)));
                    tableRow.getContent().add(tableCell);
                });
                table.getContent().add(tableRow);
            });
            wordMLPackage.getMainDocumentPart().addObject(table);
            return this;
        }

        
        public WordOption replaceData(Map data, List> tableDataList, int tableTemplateIndex, int tableIndex) throws Exception {
            // 构造循环列表的数据
            ClassFinder find = new ClassFinder(Tbl.class);

            new TraversalUtil(wordMLPackage.getMainDocumentPart().getContent(), find);

            // 获取第二个表格属性
            if (find.results.size() > 0) {
                Tbl table = (Tbl) find.results.get(tableIndex);

                // 第二行约定为模板
                Tr dynamicTr = (Tr) table.getContent().get(tableTemplateIndex);

                // 获取模板行的xml数据
                String dynamicTrXml = XmlUtils.marshaltoString(dynamicTr);

                // 循环填充模板表格行数据
                int addIndex = tableTemplateIndex;
                for (Map dataMap : tableDataList) {

                    addIndex++;

                    Tr newTr = (Tr) XmlUtils.unmarshallFromTemplate(dynamicTrXml, dataMap);

                    table.getContent().add(addIndex, newTr);

                }

                // 删除模板行的占位行
                table.getContent().remove(tableTemplateIndex);
            }

            // 设置全局的变量替换
            wordMLPackage.getMainDocumentPart().variableReplace(data);
            return this;
        }

        
        public WordOption replaceData(Map data) throws Exception {
            MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
            VariablePrepare.prepare(wordMLPackage);

            // 替换属性
            documentPart.variableReplace(data);

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            wordMLPackage.save(outputStream);
            return this;
        }

        public void save(String path) throws Docx4JException {
            wordMLPackage.save(new File(path));
        }

        public void save(OutputStream outputStream) throws Docx4JException {
            wordMLPackage.save(outputStream);
        }
    }

}

 

四、水印工具类

Java 生成水印https://mp.csdn.net/mp_blog/creation/editor/121976565https://mp.csdn.net/mp_blog/creation/editor/121976565https://mp.csdn.net/mp_blog/creation/editor/121976565

五、docx模板及替换结果

Word模板文档
替换后的PDF文档(未加水印)

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号