精华内容
下载资源
问答
  • java替换word占位符.zip

    2021-07-26 13:58:06
    java 替换word 占位符
  • javaword占位符替换

    2021-04-15 19:07:05
    一、java中有什么方法可以读取占位符的字符串,并且把占位符替换成参数可以通过字符串的format方法进行实现。举例:string domain = "www.ykmaiz.com";//定义第一个值int iVisit = 0;//定义第二个值System.out....

    一、java中有什么方法可以读取占位符的字符串,并且把占位符替换成参数

    可以通过字符串的format方法进行实现。

    举例:string domain = "www.ykmaiz.com";//定义第一个值int iVisit = 0;//定义第二个值System.out.println(String.Format("该域名{0}被访问了 {1} 次.", domain, iVisit));//在控制台输出备注:占位符的方式通常能够通过直接进行字符串的多次“+”的形式进行实现,如果不熟练format的形式,建议直接用连接符(“+”)的形式实现即可。

    二、如何使用POI 3.8替换占位符的docx的头在Java中

    公共XWPFDocument的setHeader(XWPFDocument文件,字符串标记,字符串textToReplace){

    XWPFHeaderFooterPolicy政策= document.getHeaderFooterPolicy();

    XWPFHeader头= policy.getHeader(0);

    replaceInParagraphs(header.getParagraphs(),令牌,textToReplace);

    返回文件;

    }私人无效replaceInParagraphs(列表< XWPFParagraph>段落,字符串占位符,字符串replaceText){

    对于(XWPFParagraph xwpfParagraph:段){

    清单< XWPFRun>奔跑= xwpfParagraph.getRuns();

    对于(XWPFRun运行:运行){

    串runText = run.getText(run.getTextPosition()); 如果(占位=“与”&!&安培;!placeHolder.isEmpty()){

    如果(runText = NULL&放大器;!&安培;

    Pattern.compile(占位符,Pattern.CASE_INSENSITIVE).matcher(runText).find()){

    runText = replaceText;

    }

    }

    run.setText(runText,0);

    }

    }

    }

    展开全文
  • 做一个demo,解析docx的word文档,替换占位符,并导出成pdf 分两步,第一步是解析word替换占位符,生成一个新的word文件。第二步再导出成pdf Springboot:2.4.0 一、解析word替换占位符 1.所需要的依赖: <!-...

    做一个demo,解析docx的word文档,替换占位符,并导出成pdf

    分两步,第一步是解析word,替换占位符,生成一个新的word文件。第二步再导出成pdf

    Springboot:2.4.0

    一、解析word,替换占位符

    1.所需要的依赖:

    <!--  apache  poi-->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-scratchpad</artifactId>
                <version>3.8</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.6</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.8</version>
            </dependency>
    

    2.将word模板文件放到resource下的static/aaa.docx
    大致如下:
    在这里插入图片描述

    3.编写代码

    service:

    package com.example.rabmq.ramqdemo.word;
    
    import org.apache.poi.POIXMLDocument;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    import org.springframework.stereotype.Component;
    
    import java.io.*;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author Honey
     * @Date 2021/9/9
     * @Description
     */
    @Component
    public class GeneratePdf {
    
        public XWPFDocument ttt() {
            Resource resource = new ClassPathResource("static/hubei-protocol-template2021.docx");
            InputStream inputStream = null;
            Map<String, String> map = new HashMap<>();
            map.put("${CONTRACT_BH}", "HT11");
            map.put("${PARTY_A_NAME}", "测试公司");
            String absolutePath = null;
            try {
                absolutePath = resource.getFile().getAbsolutePath();
                System.out.println(absolutePath);
                XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(absolutePath));
    
                Iterator<XWPFParagraph> paragraphsIterator = document.getParagraphsIterator();
                while (paragraphsIterator.hasNext()) {
                    XWPFParagraph next = paragraphsIterator.next();
                    List<XWPFRun> runs = next.getRuns();
                    for (int i = 0; i < runs.size(); i++) {
                        XWPFRun xwpfRun = runs.get(i);
                        String text = xwpfRun.getText(xwpfRun.getTextPosition());
                        System.out.println(text);
                        if (text == null || text.trim().equals("")) {
                            continue;
                        }
                        //替换
                        for (Map.Entry<String, String> entry : map.entrySet()) {
                            String key = entry.getKey();
                            String value = entry.getValue();
                            if (text.contains(key)) {
                                text = text.replace(key, value);
                                xwpfRun.setText(text, 0);
                                break;
                            }
                        }
                        
                    }
                }
                return document;
    //            System.out.println("aa");
    //            FileOutputStream fos = new FileOutputStream("C:/资源/aaa.docx");
    //            document.write(fos);
    //            ByteArrayOutputStream ostream = new ByteArrayOutputStream();
    //            FileOutputStream out = new FileOutputStream(absolutePath);
    //            document.write(out);
    //            out.flush();
    //            out.close();
    //            out.write(ostream.toByteArray());
    
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
    

    controller:

    package com.example.rabmq.ramqdemo.word;
    
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.OutputStream;
    
    /**
     * @author Honey
     * @Date 2021/9/9
     * @Description
     */
    @Controller
    public class PdfController {
    
        @Autowired
        private GeneratePdf generatePdf;
    
        @RequestMapping("testExport")
        public void gen(HttpServletResponse response) throws Exception {
            OutputStream outputStream = response.getOutputStream();
            XWPFDocument ttt = generatePdf.ttt();
            StringBuilder contentDispositionValue = new StringBuilder();
            contentDispositionValue.append("attachment; filename=")
                    .append("testFile.docx")
                    .append(";")
                    .append("filename*=")
                    .append("utf-8''")
                    .append("testFile.docx");
    
            response.setHeader("Content-disposition", contentDispositionValue.toString());
            ttt.write(outputStream);
        }
    }
    
    

    3.项目启动后,使用postman测试接口

    在这里插入图片描述
    4.打开保存的文件,可以看到目标值被替换了

    在这里插入图片描述
    PS:在写demo进行测试的时候,遇到一个报错的问题:
    Can’t obtain the input stream from /docProps/app.xml
    在文本替换后,将文件写入到一个word文件里,poi报错了。
    原因发现是,FileOutputStream写出的文件用的之前的同一个文件导致的,这里代码进行如下改造之后就没问题了。

    //原代码
    FileOutputStream fos = new FileOutputStream(absolutePath);
    //改成
    FileOutputStream fos = new FileOutputStream("C:/资源/aaa.docx");
    //可能是不能使用原来文件的绝对路径。
    

    二、解析后的word导出成pdf文件

    经发现,word转换成pdf有好几种方式,但是各有优劣。
    1.apache poi + itext
    这种方式无需安装其他组件,使用java代码就可以运行,但是word里的图片,还有表格等会丢失,只适合比较简单的文档处理。

    2.jacob的jar包
    这种方式貌似效率还可以,但是jacob只支持windows,如果你的程序需要在linux服务器上运行,那么就用不了。

    3.openOffice
    需要使用openOffice搭建一个服务,比较繁琐,运维成本比较高,支持windows和linux。

    这里使用第一个poi + itext做一个转换的demo

    1.加入itext相关依赖

    <!--  apache  poi-->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.14</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-scratchpad</artifactId>
                <version>3.14</version>
            </dependency>
            <dependency>
                <groupId>fr.opensagres.xdocreport</groupId>
                <artifactId>xdocreport</artifactId>
                <version>1.0.6</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml-schemas</artifactId>
                <version>3.14</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>ooxml-schemas</artifactId>
                <version>1.3</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf.tool</groupId>
                <artifactId>xmlworker</artifactId>
                <version>5.5.11</version>
            </dependency>
            <dependency>
                <groupId>org.jsoup</groupId>
                <artifactId>jsoup</artifactId>
                <version>1.11.3</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>5.5.11</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itext-asian</artifactId>
                <version>5.2.0</version>
            </dependency>
    

    2.增加代码

    package com.example.rabmq.ramqdemo.word;
    
    import com.itextpdf.text.BaseColor;
    import com.itextpdf.text.Font;
    import com.itextpdf.text.FontProvider;
    import com.itextpdf.text.PageSize;
    import com.itextpdf.text.pdf.BaseFont;
    import com.itextpdf.text.pdf.PdfWriter;
    import com.itextpdf.tool.xml.XMLWorkerHelper;
    import org.apache.poi.POIXMLDocument;
    import org.apache.poi.xwpf.converter.core.BasicURIResolver;
    import org.apache.poi.xwpf.converter.core.FileImageExtractor;
    import org.apache.poi.xwpf.converter.core.utils.StringUtils;
    import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
    import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Element;
    import org.jsoup.nodes.Entities;
    import org.jsoup.select.Elements;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    import org.springframework.stereotype.Component;
    
    import java.io.*;
    import java.nio.charset.Charset;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author Honey
     * @Date 2021/9/9
     * @Description
     */
    @Component
    public class GeneratePdf {
    
        public XWPFDocument ttt() {
            Resource resource = new ClassPathResource("static/hubei-protocol-template2021.docx");
            InputStream inputStream = null;
            Map<String, String> map = new HashMap<>();
            map.put("${CONTRACT_BH}", "HT11");
            map.put("${PARTY_A_NAME}", "测试公司");
            String absolutePath = null;
            try {
                absolutePath = resource.getFile().getAbsolutePath();
                System.out.println(absolutePath);
                XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(absolutePath));
    
                Iterator<XWPFParagraph> paragraphsIterator = document.getParagraphsIterator();
                while (paragraphsIterator.hasNext()) {
                    XWPFParagraph next = paragraphsIterator.next();
                    List<XWPFRun> runs = next.getRuns();
                    for (int i = 0; i < runs.size(); i++) {
                        XWPFRun xwpfRun = runs.get(i);
                        String text = xwpfRun.getText(xwpfRun.getTextPosition());
                        if (text == null || text.trim().equals("")) {
                            continue;
                        }
                        //替换
                        for (Map.Entry<String, String> entry : map.entrySet()) {
                            String key = entry.getKey();
                            String value = entry.getValue();
                            if (text.contains(key)) {
                                text = text.replace(key, value);
                                xwpfRun.setText(text, 0);
                                break;
                            }
                        }
                    }
                }
                return document;
    //            System.out.println("aa");
    //            FileOutputStream fos = new FileOutputStream("C:/资源/aaa.docx");
    //            document.write(fos);
    //            ByteArrayOutputStream ostream = new ByteArrayOutputStream();
    //            FileOutputStream out = new FileOutputStream(absolutePath);
    //            document.write(out);
    //            out.flush();
    //            out.close();
    //            out.write(ostream.toByteArray());
    
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 将docx格式文件转成html
         *
         * @param docxPath docx文件路径
         * @param imageDir docx文件中图片存储目录
         * @return html
         */
        public static String docx2Html(String docxPath, String imageDir) {
            String content = null;
    
            FileInputStream in = null;
            ByteArrayOutputStream baos = null;
            try {
                // 1> 加载文档到XWPFDocument
                in = new FileInputStream(new File(docxPath));
                XWPFDocument document = new XWPFDocument(in);
                // 2> 解析XHTML配置(这里设置IURIResolver来设置图片存放的目录)
                XHTMLOptions options = XHTMLOptions.create();
                // 存放word中图片的目录
                options.setExtractor(new FileImageExtractor(new File(imageDir)));
                options.URIResolver(new BasicURIResolver(imageDir));
                options.setIgnoreStylesIfUnused(false);
                options.setFragment(true);
                // 3> 将XWPFDocument转换成XHTML
                baos = new ByteArrayOutputStream();
                XHTMLConverter.getInstance().convert(document, baos, options);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                    if (baos != null) {
                        content = new String(baos.toByteArray(), "utf-8");
                        baos.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return content;
        }
    
        /**
         * 使用jsoup规范化html
         *
         * @param html html内容
         * @return 规范化后的html
         */
        public static String formatHtml(String html) {
            org.jsoup.nodes.Document doc = Jsoup.parse(html);
            // 去除过大的宽度
            String style = doc.attr("style");
            if (StringUtils.isNotEmpty(style) && style.contains("width")) {
                doc.attr("style", "");
            }
            Elements divs = doc.select("div");
            for (Element div : divs) {
                String divStyle = div.attr("style");
                if (StringUtils.isNotEmpty(divStyle) && divStyle.contains("width")) {
                    div.attr("style", "");
                }
            }
            // jsoup生成闭合标签
            doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml);
            doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);
            return doc.html();
        }
    
    
        /**
         * html转成pdf
         *
         * @param html          html
         * @param outputPdfPath 输出pdf路径
         */
        public static void htmlToPdf(String html, String outputPdfPath) {
            com.itextpdf.text.Document document = null;
            ByteArrayInputStream bais = null;
            try {
                // 纸
                document = new com.itextpdf.text.Document(PageSize.A4);
                // 笔
                PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdfPath));
                document.open();
    
                // html转pdf
                bais = new ByteArrayInputStream(html.getBytes());
                XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais,
                        Charset.forName("UTF-8"), new FontProvider() {
                            @Override
                            public boolean isRegistered(String s) {
                                return false;
                            }
    
                            @Override
                            public Font getFont(String s, String s1, boolean embedded, float size, int style, BaseColor baseColor) {
                                // 配置字体
                                Font font = null;
                                try {
                                    // 方案一:使用本地字体(本地需要有字体)
    //                              BaseFont bf = BaseFont.createFont("c:/Windows/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    //                                BaseFont bf = BaseFont.createFont("C:/Windows/Fonts/seguisym.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                                    // 方案二:使用jar包:iTextAsian,这样只需一个jar包就可以了
                                    BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
                                    font = new Font(bf, size, style, baseColor);
                                    font.setColor(baseColor);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                return font;
                            }
                        });
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (document != null) {
                    document.close();
                }
                if (bais != null) {
                    try {
                        bais.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            String basePath = "C:/个人资料/";
            String docxPath = basePath + "testFile2.docx";
            String pdfPath = basePath + "index.pdf";
            String imageDir = "C:/个人资料/";
    
            // 测试doc转pdf
    //        String docHtml = doc2Html(docPath, imageDir);
    //        docHtml = formatHtml(docHtml);
    //        htmlToPdf(docHtml, pdfPath);
    
            // 测试docx转pdf
            String docxHtml = docx2Html(docxPath, imageDir);
            docxHtml = formatHtml(docxHtml);
    //        docxHtml = docxHtml.replace("___", "张三");
            htmlToPdf(docxHtml, pdfPath);
        }
    }
    
    

    3.运行main方法,得到一个转换后的pdf文件

    在这里插入图片描述
    PS:转换后的文件,丢失了很多的表格框,另外图片也无法处理,如果不加入上面itext-asign里处理编码格式的方法,转换出来的文件还会出现中文乱码。
    因此这种方式只适合比较简单的word文档转pdf,如果是专门做文档业务的,可能要搭建一个高效的独立的office服务,可转换,在在线预览等。

    下次有时间研究一下openOffice以及pageOffice,然后看看效率和效果。

    展开全文
  • word模板动态替换占位符(eg:${placeholder})然后生成新的word 网上搜索的不管是docx4j还是poi都只是实现了占位符在同一个文本中(读取word行数据后,行数据会分为多个文本)的替换,针对占位符没有在同一个文本...

    word模板动态替换占位符(eg:${placeholder})然后生成新的word

    网上搜索的不管是docx4j还是poi都只是实现了占位符在同一个文本中(读取word行数据后,行数据会分为多个文本)的替换,针对占位符没有在同一个文本或者换行了都没有实现,总结docx4j和poi两种方式终极实现占位符替换生成新word,两种方式源码如下

    1、Docx4J实现代码

    
    import cn.hutool.core.util.ObjectUtil;
    import com.google.common.collect.Lists;
    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
    import org.docx4j.wml.ContentAccessor;
    import org.docx4j.wml.Text;
    import org.junit.Test;
    
    import javax.xml.bind.JAXBElement;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author liuchao
     * @date 2020/6/8
     */
    public class Test01 {
    
        /**
         * 设置最大Text类型节点个数 如果超过此值,在删除占位符时可能会重复计算导致错误
         */
        private static int MAX_TEXT_SIZE = 1000000;
    
        @Test
        public void test() throws Exception {
            String docxFile = "/Users/liuchao/java/temp/1.docx";
            WordprocessingMLPackage template = WordprocessingMLPackage.load(new java.io.File(docxFile));
            List<Object> texts = getAllElementFromObject(
                    template.getMainDocumentPart(), Text.class);
            Map<String, String> map = new HashMap<>();
            map.put("${company}", "Company Name here...");
            map.put("${address}", "xxxfffadfasdf");
            map.put("${secondParty}", "xxxfffadfasdf");
            map.put("${year}", "xxxfffadfasdf");
            map.put("${month}", "xxxfffadfasdf");
            map.put("${day}", "xxxfffadfasdf");
            map.put("${money}", "1000");
            searchAndReplace(texts, map);
            template.save(new java.io.File("/Users/liuchao/java/temp/NEW.docx"));
        }
    
    
        /**
         * 递归获取所有的节点
         *
         * @param obj      当前文档
         * @param toSearch 要查询的节点类型
         * @return java.util.List<java.lang.Object>
         * @author liuchao
         * @date 2020/6/9
         */
        private static List<Object> getAllElementFromObject(Object obj,
                                                            Class<?> toSearch) {
            List<Object> result = Lists.newArrayListWithCapacity(60);
            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();
                for (Object child : children) {
                    result.addAll(getAllElementFromObject(child, toSearch));
                }
            }
            return result;
        }
    
        /**
         * 查找并且替换占位符
         *
         * @param texts  当前文档所有的Text类型节点
         * @param values 要替换的占位符key\value
         * @return void
         * @author liuchao
         * @date 2020/6/9
         */
        public static void searchAndReplace(List<Object> texts, Map<String, String> values) {
            // 存储占位符 位置信息集合
            List<int[]> placeholderList = getPlaceholderList(texts, values);
            if (ObjectUtil.isEmpty(placeholderList)) {
                return;
            }
            int[] currentPlaceholder;
            // 删除元素占位符
            for (int i = 0; i < texts.size(); i++) {
                if (ObjectUtil.isEmpty(placeholderList)) {
                    break;
                }
                currentPlaceholder = placeholderList.get(0);
                Text textElement = (Text) texts.get(i);
                String v = textElement.getValue();
                StringBuilder nval = new StringBuilder();
                char[] textChars = v.toCharArray();
                for (int j = 0; j < textChars.length; j++) {
                    char c = textChars[j];
                    if (null == currentPlaceholder) {
                        nval.append(c);
                        continue;
                    }
                    // 计算是否需要排除当前节点
                    int start = currentPlaceholder[0] * MAX_TEXT_SIZE + currentPlaceholder[1];
                    int end = currentPlaceholder[2] * MAX_TEXT_SIZE + currentPlaceholder[3];
                    int cur = i * MAX_TEXT_SIZE + j;
                    // 排除'$'和'}'两个字符之间的字符
                    if (!(cur >= start && cur <= end)) {
                        nval.append(c);
                    }
    
                    if (j > currentPlaceholder[3] && i >= currentPlaceholder[2]) {
                        placeholderList.remove(0);
                        if (ObjectUtil.isEmpty(placeholderList)) {
                            currentPlaceholder = null;
                            continue;
                        }
                        currentPlaceholder = placeholderList.get(0);
                    }
                }
                textElement.setValue(nval.toString());
            }
        }
    
        /**
         * 获取占位符信息,并且在占位符后面填充值
         *
         * @param texts  Text类型节点集合
         * @param values 要替换的占位符key\value
         * @return java.util.List<int [ ]>
         * @author liuchao
         * @date 2020/6/9
         */
        public static List<int[]> getPlaceholderList(List<Object> texts, Map<String, String> values) {
            // 标识忽略
            int ignoreTg = 0;
            // 标识已读取到'$'字符
            int startTg = 1;
            // 标识已读取到'{'字符
            int readTg = 2;
            // 当前标识
            int modeTg = ignoreTg;
    
            // 存储占位符 位置信息集合
            List<int[]> placeholderList = new ArrayList<>();
            // 当前占位符 0:'$'字符Text在texts中下标
            //          1:'$'字符在Text.getValue().toCharArray()数组下标
            //          2: '}'字符Text在texts中下标
            //          3:'}'字符在Text.getValue().toCharArray()数组下标
            int[] currentPlaceholder = new int[4];
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < texts.size(); i++) {
                Text textElement = (Text) texts.get(i);
                String newVal = "";
                String text = textElement.getValue();
                StringBuilder textSofar = new StringBuilder();
                char[] textChars = text.toCharArray();
                for (int col = 0; col < textChars.length; col++) {
                    char c = textChars[col];
                    textSofar.append(c);
                    switch (c) {
                        case '$': {
                            modeTg = startTg;
                            sb.append(c);
                        }
                        break;
                        case '{': {
                            if (modeTg == startTg) {
                                sb.append(c);
                                modeTg = readTg;
                                currentPlaceholder[0] = i;
                                currentPlaceholder[1] = col - 1;
                            } else {
                                if (modeTg == readTg) {
                                    sb = new StringBuilder();
                                    modeTg = ignoreTg;
                                }
                            }
                        }
                        break;
                        case '}': {
                            if (modeTg == readTg) {
                                modeTg = ignoreTg;
                                sb.append(c);
                                newVal += textSofar.toString()
                                        + (null == values.get(sb.toString()) ? sb.toString() : values.get(sb.toString()));
                                textSofar = new StringBuilder();
                                currentPlaceholder[2] = i;
                                currentPlaceholder[3] = col;
                                placeholderList.add(currentPlaceholder);
                                currentPlaceholder = new int[4];
                                sb = new StringBuilder();
                            } else if (modeTg == startTg) {
                                modeTg = ignoreTg;
                                sb = new StringBuilder();
                            }
                        }
                        default: {
                            if (modeTg == readTg) {
                                sb.append(c);
                            } else if (modeTg == startTg) {
                                modeTg = ignoreTg;
                                sb = new StringBuilder();
                            }
                        }
                    }
                }
                newVal += textSofar.toString();
                textElement.setValue(newVal);
            }
            return placeholderList;
        }
    

    依赖jar

            <dependency>
                <groupId>org.docx4j</groupId>
                <artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
                <version>8.1.7</version>
            </dependency>
            <!--hutool工具类-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>4.6.0</version>
            </dependency>
            <!--json格式化-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.60</version>
            </dependency>  

     

    2、Poi实现代码

    
    import cn.hutool.core.io.FileUtil;
    import cn.hutool.core.util.ObjectUtil;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.junit.Test;
    
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author liuchao
     * @date 2020/6/9
     */
    public class Test03 {
    
        // 标识忽略
        static final int ignoreTg = 0;
        // 标识已读取到'$'字符
        static final int startTg = 1;
        // 标识已读取到'{'字符
        static final int readTg = 2;
    
        @Test
        public void test() throws Exception {
            Map<String, String> map = new HashMap<>();
            map.put("${company}", "Company Name here...");
            map.put("${address}", "xxxfffadfasdf");
            map.put("${secondParty}", "xxxfffadfasdf");
            map.put("${year}", "xxxfffadfasdf");
            map.put("${month}", "xxxfffadfasdf");
            map.put("${day}", "xxxfffadfasdf");
            map.put("${money}", "1000");
    
            XWPFDocument doc = new XWPFDocument(new FileInputStream(new File("/Users/liuchao/java/temp/1.docx")));
            List<XWPFParagraph> paragraphList = Lists.newArrayList(doc.getParagraphs());
            // 获取表格中的占位符信息
            getTableParagraphs(doc, paragraphList, placeholderValues);
            //获取占位符,并且将占位符需要替换的值写入
            List<int[]> placeholderList = getPlaceholderList(paragraphList, map);
            //清除占位符信息
            clearPlaceholder(placeholderList, paragraphList);
            BufferedOutputStream bos = FileUtil.getOutputStream(new File("/Users/liuchao/java/temp/NEW.docx"));
            doc.write(bos);
            bos.flush();
            bos.close();
            doc.close();
        }
    
    
        /**
         * 获取表格中占位符信息
         *
         * @param doc               当前文档
         * @param list              存储占位符信息
         * @param placeholderValues 需要替换的值
         * @return void
         * @author liuchao
         * @date 2020/7/6
         */
        private void getTableParagraphs(XWPFDocument doc, List<XWPFParagraph> list, Map<String, String> placeholderValues) {
            List<XWPFTable> tables = doc.getTables();
            if (ObjectUtil.isEmpty(tables)) {
                return;
            }
            tables.forEach(table -> table.getRows().forEach(row -> row.getTableCells().forEach(cell -> {
                String text = cell.getText();
                if (ObjectUtil.isEmpty(text)) {
                    return;
                }
                Iterator<String> it = placeholderValues.keySet().iterator();
                while (it.hasNext()) {
                    String key = it.next();
                    if (text.indexOf(key) != -1) {
                        list.addAll(cell.getParagraphs());
                    }
                }
            })));
        }
    
    
    
        /**
         * 清除占位符信息
         *
         * @param placeholderList 占位符位置信息
         * @param paragraphList   行数据
         * @return void
         * @author liuchao
         * @date 2020/6/10
         */
        public static void clearPlaceholder(List<int[]> placeholderList, List<XWPFParagraph> paragraphList) {
            if (ObjectUtil.isEmpty(placeholderList)) {
                return;
            }
            int[] currentPlaceholder = placeholderList.get(0);
            StringBuilder tempSb = new StringBuilder();
            for (int i = 0; i < paragraphList.size(); i++) {
                XWPFParagraph p = paragraphList.get(i);
                List<XWPFRun> runs = p.getRuns();
                for (int j = 0; j < runs.size(); j++) {
                    XWPFRun run = runs.get(j);
                    String text = run.getText(run.getTextPosition());
                    StringBuilder nval = new StringBuilder();
                    char[] textChars = text.toCharArray();
                    for (int m = 0; m < textChars.length; m++) {
                        char c = textChars[m];
                        if (null == currentPlaceholder) {
                            nval.append(c);
                            continue;
                        }
                        // 排除'$'和'}'两个字符之间的字符
                        int start = currentPlaceholder[0] * 1000000 + currentPlaceholder[1] * 500 + currentPlaceholder[2];
                        int end = currentPlaceholder[3] * 1000000 + currentPlaceholder[4] * 500 + currentPlaceholder[5];
                        int cur = i * 1000000 + j * 500 + m;
                        if (!(cur >= start && cur <= end)) {
                            nval.append(c);
                        } else {
                            tempSb.append(c);
                        }
                        //判断是否是占位符结尾,如果是那获取新的占位符
                        if (tempSb.toString().endsWith("}")) {
                            placeholderList.remove(0);
                            if (ObjectUtil.isEmpty(placeholderList)) {
                                currentPlaceholder = null;
                                continue;
                            }
                            currentPlaceholder = placeholderList.get(0);
                            tempSb = new StringBuilder();
                        }
                    }
                    run.setText(nval.toString(), run.getTextPosition());
    
                }
            }
        }
    
        /**
         * 获取占位符信息,并且在占位符后面填充值
         *
         * @param paragraphList 行数据
         * @param map           要替换的占位符key\value
         * @return java.util.List<int [ ]>
         * @author liuchao
         * @date 2020/6/10
         */
        public static List<int[]> getPlaceholderList(List<XWPFParagraph> paragraphList, Map<String, String> map) {
            // 存储占位符 位置信息集合
            List<int[]> placeholderList = new ArrayList<>();
            // 当前占位符 0:'$'字符在XWPFParagraph集合中下标
            //          1:'$'字符在XWPFRun集合中下标
            //          2:'$'字符在text.toCharArray()数组下标
            //          3: '}'字符在XWPFParagraph集合中下标
            //          4: '}'字符在XWPFRun集合中下标
            //          5:'}'字符在text.toCharArray()数组下标
            int[] currentPlaceholder = new int[6];
    
            // 当前标识
            int modeTg = ignoreTg;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < paragraphList.size(); i++) {
                XWPFParagraph p = paragraphList.get(i);
                List<XWPFRun> runs = p.getRuns();
                for (int j = 0; j < runs.size(); j++) {
                    XWPFRun run = runs.get(j);
                    String text = run.getText(run.getTextPosition());
                    char[] textChars = text.toCharArray();
                    String newVal = "";
                    StringBuilder textSofar = new StringBuilder();
                    for (int m = 0; m < textChars.length; m++) {
                        char c = textChars[m];
                        textSofar.append(c);
                        switch (c) {
                            case '$': {
                                modeTg = startTg;
                                sb.append(c);
                            }
                            break;
                            case '{': {
                                if (modeTg == startTg) {
                                    sb.append(c);
                                    modeTg = readTg;
                                    currentPlaceholder[0] = i;
                                    currentPlaceholder[1] = j;
                                    currentPlaceholder[2] = m - 1;
                                } else {
                                    if (modeTg == readTg) {
                                        sb = new StringBuilder();
                                        modeTg = ignoreTg;
                                    }
                                }
                            }
                            break;
                            case '}': {
                                if (modeTg == readTg) {
                                    modeTg = ignoreTg;
                                    sb.append(c);
                                    String val = map.get(sb.toString());
                                    if (ObjectUtil.isNotEmpty(val)) {
                                        newVal += textSofar.toString() + val;
                                        placeholderList.add(currentPlaceholder);
                                        textSofar = new StringBuilder();
                                    }
                                    currentPlaceholder[3] = i;
                                    currentPlaceholder[4] = j;
                                    currentPlaceholder[5] = m;
                                    currentPlaceholder = new int[6];
                                    sb = new StringBuilder();
                                } else if (modeTg == startTg) {
                                    modeTg = ignoreTg;
                                    sb = new StringBuilder();
                                }
                            }
                            default: {
                                if (modeTg == readTg) {
                                    sb.append(c);
                                } else if (modeTg == startTg) {
                                    modeTg = ignoreTg;
                                    sb = new StringBuilder();
                                }
                            }
                        }
                    }
                    newVal += textSofar.toString();
                    run.setTextPosition(0);
                    run.setText(newVal, run.getTextPosition());
                }
            }
            return placeholderList;
        }

    依赖jar

                <!--hutool工具类-->
                <dependency>
                    <groupId>cn.hutool</groupId>
                    <artifactId>hutool-all</artifactId>
                    <version>4.6.0</version>
                </dependency>
                <!--json格式化-->
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>fastjson</artifactId>
                    <version>1.2.60</version>
                </dependency>  
                <dependency>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi</artifactId>
                    <version>4.1.1</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi-ooxml</artifactId>
                    <version>4.1.1</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi-ooxml-schemas</artifactId>
                    <version>4.1.1</version>
                </dependency>                      

     

     

    展开全文
  • Element picElement = (Element)tElements.item(i);if(picElement.getTextContent().equals(tag)){picElement.setTextContent(this.getImageStr(imgFile));/*图片编码*/picElement.setAttribute("w:name",wName);...

    Element picElement = (Element)tElements.item(i);

    if(picElement.getTextContent().equals(tag)){

    picElement.setTextContent(this.getImageStr(imgFile));/*图片编码*/

    picElement.setAttribute("w:name",wName);//设置名字

    Element imagedataElement = (Element) xElement.getElementsByTagName("v:imagedata").item(i);

    imagedataElement.setAttribute("src",wName);

    }

    }

    return xElement;

    }

    /**

    * 插入图片

    * @param parentElement 图片添加至何处

    * @param imgFile 图片路径

    * @param isnewLine 是否换行

    * @return 返回添加图片节点后的节点

    */

    public Element addPic(Element parentElement,String imgFile,boolean isnewLine){ Document parent = parentElement.getOwnerDocument();

    Element p = null;

    Element pict = null;

    Element binData = null;

    Element shape = null;

    Element imagedata = null;

    String src = "wordml://" + new Date().getTime();

    if(isnewLine){

    p = parent.createElement("w:p");

    }

    pict = parent.createElement("w:pict");

    binData = parent.createElement("w:binData");

    binData.setAttribute("w:name", src);

    binData.setAttribute("xml:space", "preserve");

    binData.setTextContent(this.getImageStr(imgFile));

    shape = parent.createElement("v:shape");

    imagedata = parent.createElement("v:imagedata");

    展开全文
  • 1.java处理word是个大大的坑,无论是poi还是Java2word 都不是尽善尽美。2.poi只能进行简单读操作,Java2word需要调用系统的com接口,系统机必须安装office和动态链接库。3.word从2003版本就可以保存为xml格式,通过...
  • java替换word中的变量

    2014-11-05 09:24:17
    java替换word字符串 附带jar;支持docx,doc
  • 以前写过用asposeword 替换文字和图片,但是后来遇到问题,有些word替换替换图片后会导致打开时弹出错误:此文件中检测到错误,单word可以通过进行一下修复来打开文件。 考虑可能是版本有bug,于是从官网下了最新的...
  • doc类型的word用HWPFDocument类进行解析 docx类型的word用XWPFDocument类进行解析 /** * * @param srcPath word模板数据源路径 * @param destPath word导出路径 * @param map 关键字键值对映射 * @...
  • 链接: 详情.
  • I have a template in word (.docx) format and want to replace some placeholders in this template with my own data, do you know where I can find the right classes for this project? It would be nice for ...
  • //将需要替换的内容翻到map中,如果word中使用的不是${}形式,map的可以也需要修改 Map map = new HashMap(); map.put("${甲方盖章}","急急急"); map.put("${乙方签名}","烦烦烦"); map.put("${工作岗位}","java...
  • 1.占位符替换模板导出(只适用于word中含有表格形式的):/// /// 使用替换模板进行到处word文件/// public class WordUtility{private object tempFile = null;private object saveFile = null;private static Word._...
  • 如题,通过docx4j这个框架解析项目下的docx模板,然后在数据库查询数据,填充到Map,然后替换模板中的占位符${name},生成一个新的docx文档,并生成pdf文件。 1.jar包依赖 <dependency> <groupId>org....
  • 常用的占位符含义: 转换符 详细说明 示例 %s 字符串类型 “喜欢请收藏” %c 字符类型 ‘m’ %b 布尔类型 true %d 整数类型(十进制) 88 %x 整数类型(十六进制) FF %o 整数类型(八进制) 77 %f 浮点类型 8.888 %...
  • //这里是 判断 数据库的富文本中有没有某个占位符 然后进行替换 content = replacePlaceholder(content, placeholder); List htmlList = HTMLWorker.parseToList(new StringReader(content), ss); for (int i =...
  • libreOffice 官网 ... 参考原文: ...将下载的LibreOffice_6.1.3_Linux_x86-64_rpm.tar.gz的压缩包上传到linux中, .../opt/libreoffice6.0/program/soffice.bin: error while loading...代码启动类 Test.java    
  • 1 importjava.io.IOException;2 importjava.math.BigInteger;3 importjava.util.ArrayList;4 importjava.util.HashMap;5 importjava.util.Iterator;6 importjava.util.List;7 importjava.util.Map;8 importjava.util...
  • 在poi操作word模板进行数据替换时,会存在替换的段落需要换行的情况,由于传入的都是字符串,之前在网上搜索过一些处理方法都没有效果,如给字符串添加:“\r”,“\r\n”,"\n","char(11)。"然后只有考虑从代码...
  • Java 占位符

    2020-12-21 13:24:50
    //输出结果 我是程序猿,来自魔都,测试占位符 Android 使用问题 bug Multiple annotations found at this line: - error: Multiple substitutions specified in non-positional format; did you mean to add the ...
  • * 替换文档的占位符,保留占位符原有样式 * 此处只用于demo,请根据业务需要,定制成你喜欢的样子 */ public class DocxUtils { /** * 用一个docx文档作为模板,然后替换其中的内容,再写入目标文档中。 * * @...
  • 其原理就是先做一个word模板, 该模板中变量数据用xxx这种方式填写,然后再导出时只需读取模板然后用相应的数据替换其中的{xxx}这种方式填写, 然后再导出时只需读取模板然后用相应的数据替换其中的xxx这种方式填写,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,596
精华内容 1,438
关键字:

java替换word占位符

java 订阅