zoukankan      html  css  js  c++  java
  • poi根据模板导出word文档

    POI结构与常用类

    Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。 .NET的开发人员则可以利用NPOI (POI for .NET) 来存取 Microsoft Office文档的功能。

    包名称说明

    • HSSF提供读写Microsoft Excel XLS格式档案的功能。
    • XSSF提供读写Microsoft Excel OOXML XLSX格式档案的功能。
    • HWPF提供读写Microsoft Word DOC格式档案的功能。
    • HSLF提供读写Microsoft PowerPoint格式档案的功能。
    • HDGF提供读Microsoft Visio格式档案的功能。
    • HPBF提供读Microsoft Publisher格式档案的功能。
    • HSMF提供读Microsoft Outlook格式档案的功能。

    测试例子

    测试模板:

     

    测试代码:

    @Test
        public void docxExportTest() throws IOException {
            InputStream is = null;
            FileOutputStream fos = null;
            try {
                //获取docx解析对象
                is = new FileInputStream("F:\document\咨询服务合同.docx");
                XWPFDocument document = new XWPFDocument(is);
    
                //组装参数
                File seal = new File("F:\imgtest\1.jpg");
                Map<String, Object> sealMap = new HashMap<String, Object>();
                sealMap.put("width", 50);
                sealMap.put("height", 50);
                sealMap.put("type", "jpg");
                sealMap.put("content", new FileInputStream(seal));
    
                Map<String, Object> contentMap = new HashMap<>();
                contentMap.put("part_a", "张三");
                contentMap.put("address_a", "青岛市市南区动漫产业园E座");
                contentMap.put("legal_person_a", "李四");
                contentMap.put("seal", sealMap);
    
                //解析替换段落文本对象
                XWPFUtil.changeParagraph(document, contentMap);
    
                //生成新的word文档
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String fileName = "咨询服务合同" + sdf.format(new Date()) + ".docx";
                File file = new File("F://" + fileName);
                fos = new FileOutputStream(file);
                document.write(fos);
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (is != null) {
                    is.close();
                }
                if (fos != null) {
                    fos.close();
                }
            }
        }

    工具类:

    package com.m2plat.puhui.utils;
    
    import com.alibaba.fastjson.JSON;
    import org.apache.commons.io.IOUtils;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.xmlbeans.XmlException;
    import org.apache.xmlbeans.XmlToken;
    import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
    import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
    import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.io.ClassPathResource;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Created by xiangzh on 2018/11/1.
     */
    public class XWPFUtils {
    
        private static Logger logger = LoggerFactory.getLogger(XWPFUtils.class);
    
        /**
         * 根据模板生成word文档
         * @param os
         * @param tempPath
         * @param contentMap
         */
        public static void writeTemp(OutputStream os, String tempPath, Map<String, Object> contentMap){
            logger.info("---根据模板生成word文档");
            logger.info("---模板地址:{}",tempPath);
            logger.info("---替换内容:{}", JSON.toJSONString(contentMap));
            ClassPathResource resource = new ClassPathResource(tempPath);
            if(resource == null || !resource.exists()){
                logger.error("---模板文件不存在,tempPath:{}",tempPath);
                return;
            }
    
            InputStream is = null;
            try{
                is = resource.getInputStream();
                XWPFDocument document = new XWPFDocument(is);
                XWPFUtils.changeParagraph(document, contentMap);
                //生成新的word文档
                document.write(os);
            }catch (IOException e){
                logger.error("---输出word文档失败,原因:{}",e.getMessage());
            }finally {
                IOUtils.closeQuietly(is);
            }
        }
    
    
        /**
         * 替换段落文本
         *
         * @param document docx解析对象
         * @param textMap  需要替换的信息集合
         */
        public static void changeParagraph(XWPFDocument document, Map<String, Object> textMap) {
            //获取段落集合
            List<XWPFParagraph> paragraphs = document.getParagraphs();
    
            for (XWPFParagraph paragraph : paragraphs) {
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
                    String text = run.getText(0);
                    //判断文本是否需要进行替换
                    if (checkText(text)) {
                        for (Map.Entry<String, Object> entry : textMap.entrySet()) {
                            //匹配模板与替换值 格式${key}
                            String key = "${" + entry.getKey() + "}";
                            Object value = entry.getValue();
    
                            if (text.contains(key)) {
                                if (value instanceof String) { //文字替换
                                    text = text.replace(key, (String) value);
                                } else if (value instanceof Map) { //图片替换
                                    text = text.replace(key, "");
                                    Map picMap = (Map) value;
                                    int width = Integer.parseInt(picMap.get("width").toString());
                                    int height = Integer.parseInt(picMap.get("height").toString());
                                    int picType = getPictureType(picMap.get("type").toString());
                                    FileInputStream fis = (FileInputStream) picMap.get("content");
                                    try {
                                        String blipId = document.addPictureData(fis, picType);
                                        int id = document.getNextPicNameNumber(picType);
                                        XWPFUtils.createPicture(id, blipId, width, height, run);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                        //替换模板原来位置
                        run.setText(text, 0);
                    }
                }
            }
        }
    
        /**
         * @param id
         * @param blipId
         * @param width 宽
         * @param height 高
         //* @param paragraph  段落
         */
        private static void createPicture(int id, String blipId, int width, int height,XWPFRun xwpfRun) {
            final int EMU = 9525;
            width *= EMU;
            height *= EMU;
            CTInline inline = xwpfRun.getCTR().addNewDrawing().addNewInline();
            //CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline(); //在遍历run列表的时候,创建新的run有可能会导致报错
            String picXml = ""
                    + "<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">"
                    + "   <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">"
                    + "      <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">"
                    + "         <pic:nvPicPr>" + "            <pic:cNvPr id=""
                    + id
                    + "" name="Generated"/>"
                    + "            <pic:cNvPicPr/>"
                    + "         </pic:nvPicPr>"
                    + "         <pic:blipFill>"
                    + "            <a:blip r:embed=""
                    + blipId
                    + "" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"/>"
                    + "            <a:stretch>"
                    + "               <a:fillRect/>"
                    + "            </a:stretch>"
                    + "         </pic:blipFill>"
                    + "         <pic:spPr>"
                    + "            <a:xfrm>"
                    + "               <a:off x="0" y="0"/>"
                    + "               <a:ext cx=""
                    + width
                    + "" cy=""
                    + height
                    + ""/>"
                    + "            </a:xfrm>"
                    + "            <a:prstGeom prst="rect">"
                    + "               <a:avLst/>"
                    + "            </a:prstGeom>"
                    + "         </pic:spPr>"
                    + "      </pic:pic>"
                    + "   </a:graphicData>" + "</a:graphic>";
    
            inline.addNewGraphic().addNewGraphicData();
            XmlToken xmlToken = null;
            try {
                xmlToken = XmlToken.Factory.parse(picXml);
            } catch (XmlException xe) {
                xe.printStackTrace();
            }
            inline.set(xmlToken);
    
            inline.setDistT(0);
            inline.setDistB(0);
            inline.setDistL(0);
            inline.setDistR(0);
    
            CTPositiveSize2D extent = inline.addNewExtent();
            extent.setCx(width);
            extent.setCy(height);
    
            CTNonVisualDrawingProps docPr = inline.addNewDocPr();
            docPr.setId(id);
            docPr.setName("docx_img_ " + id);
            docPr.setDescr("docx Picture");
        }
    
        /**
         * 判断文本中是否包含$
         *
         * @param text 文本
         * @return 包含返回true, 不包含返回false
         */
        private static boolean checkText(String text) {
            if (text == null || "".equals(text)) {
                return false;
            }
            return text.contains("$");
        }
    
        /**
         * 根据图片类型,取得对应的图片类型代码
         *
         * @param picType
         * @return int
         */
        private static int getPictureType(String picType) {
            int res = XWPFDocument.PICTURE_TYPE_PICT;
            if (picType != null) {
                if (picType.equalsIgnoreCase("png")) {
                    res = XWPFDocument.PICTURE_TYPE_PNG;
                } else if (picType.equalsIgnoreCase("dib")) {
                    res = XWPFDocument.PICTURE_TYPE_DIB;
                } else if (picType.equalsIgnoreCase("emf")) {
                    res = XWPFDocument.PICTURE_TYPE_EMF;
                } else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {
                    res = XWPFDocument.PICTURE_TYPE_JPEG;
                } else if (picType.equalsIgnoreCase("wmf")) {
                    res = XWPFDocument.PICTURE_TYPE_WMF;
                }
            }
            return res;
        }
    }
    View Code

    测试结果:

    注意事项

    1.实际开发过程中,模板通常存放在项目工程中,获取模板的代码如下:

    String tempPath = "static/exportTemplates/咨询服务合同.docx";
    ClassPathResource resource = new ClassPathResource(tempPath);
    InputStream is = resource.getInputStream();
    XWPFDocument document = new XWPFDocument(is);

    2.导出文件时如果报错:Failed to read zip entry source,是因为打包编译将文件解压缩导致出问题,解决办法为在pom文件中配置nonFilteredFileExtension:

    <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>2.6</version>
                    <configuration>
                        <delimiters>
                            <delimiter>@</delimiter>
                            <delimiter>${*}</delimiter>
                        </delimiters>
                        <useDefaultDelimiters>false</useDefaultDelimiters>
                        <encoding>UTF-8</encoding><!-- 指定编码格式,否则在DOS下运行mvn命令时当发生文件资源copy时将使用系统默认使用GBK编码 -->
                        <nonFilteredFileExtensions>
                            <nonFilteredFileExtension>bar</nonFilteredFileExtension>
                            <nonFilteredFileExtension>zip</nonFilteredFileExtension>
                            <nonFilteredFileExtension>txt</nonFilteredFileExtension>
                            <nonFilteredFileExtension>pdf</nonFilteredFileExtension>
                            <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
                            <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
                            <nonFilteredFileExtension>xls</nonFilteredFileExtension>
                            <nonFilteredFileExtension>docx</nonFilteredFileExtension>
                            <nonFilteredFileExtension>doc</nonFilteredFileExtension>
                        </nonFilteredFileExtensions>
                    </configuration>
                </plugin>

     3.所有导出参数必须转换成string类型后才能导出,否则替换不了。

    参考:

    POI使用详解

    POI通过XWPFDocument方式操作word2007

    POI操作word模板并生成新的word.docx

    war在服务器上读取文件报:java.io.IOException: Failed to read zip entry source

    SpringBoot打成jar包后,读取resources目录下的文件

     
  • 相关阅读:
    CreateProcess的使用方法
    数据库课程设计
    OC可变參数的函数实现va_start、va_end、va_list的使用
    Tiny语言执行环境TM机源码
    LeetCode:Triangle
    [LeetCode] Word Search [37]
    关闭对话框,OnClose和OnCancel
    【Hibernate步步为营】--继承映射具体解释
    hdu 4499 Cannon(暴力)
    String.Format使用方法
  • 原文地址:https://www.cnblogs.com/Jason-Xiang/p/10001176.html
Copyright © 2011-2022 走看看