• PoiDocxDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0),目前只能java生成】


    版权声明:本文为HaiyuKing原创文章,转载请注明出处!

    前言

    这个是《PoiDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)】》的扩展,上一篇是根据doc模板生成doc文件,这个是根据docx模板生成docx文件。

    注意:目前只能java生成,集成到Android项目中,运行报错【暂时未解决】:

    Process: com.why.project.poidocxdemo, PID: 13762
        java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/xml/stream/XMLEventFactory;
            at org.apache.poi.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller.<clinit>(PackagePropertiesMarshaller.java:41)
            at org.apache.poi.openxml4j.opc.OPCPackage.<init>(OPCPackage.java:140)
            at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:103)
            at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:298)
            at org.apache.poi.ooxml.util.PackageHelper.open(PackageHelper.java:37)
            at org.apache.poi.xwpf.usermodel.XWPFDocument.<init>(XWPFDocument.java:142)

    前期准备

    参考《PoiDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)】

    区别在于,模板的占位有所不用【docx模板文件不需要$符号】:

    代码分析

    参考《PoiDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)】

    使用步骤

    一、项目组织结构图

    注意事项:

    1、  导入类文件后需要change包名以及重新import R文件路径

    2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

    二、导入步骤

    1、将poi相关jar文件导入项目中【Demo采用的是module方式】

    引用jar文件参考《【Android Studio安装部署系列】十七、Android studio引用第三方库、jar、so、arr文件

    注意:

    解析docx文件,需要引用下面的jar文件:

    • poi-4.0.0.jar
    • poi-ooxml-4.0.0.jar
    • poi-ooxml-schemas-4.0.0.jar
    • ooxml-lib目录下的curvesapi-1.05.jar、xmlbeans-3.0.1.jar
    • lib目录下的commons-collections4-4.2.jar
    • 下载的commons-compress-1.18.jar

    commons-compress-1.18.jar下载地址:http://commons.apache.org/proper/commons-compress/download_compress.cgi

    2、将制作的模板文件复制到D:/temp目录下

     

    3、将PoiUtils.java文件复制到项目中

    package com.why.main;
    
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.poi.xwpf.usermodel.XWPFTable;
    import org.apache.poi.xwpf.usermodel.XWPFTableCell;
    import org.apache.poi.xwpf.usermodel.XWPFTableRow;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public class PoiUtils {
        
        //测试
        public static void main(String[] args) {
            String templetDocPath = "D:/temp/请假单模板1.docx";
            String targetDocPath = "D:/temp/请假单1.docx";
            
            Map<String, Object> dataMap = new HashMap<String, Object>();
            dataMap.put("writeDate", "2018年10月14日");
            dataMap.put("name", "HaiyuKing");
            dataMap.put("dept", "移动开发组");
            dataMap.put("leaveType", "☑倒休 √年假 ✔事假 ☐病假 ☐婚假 ☐产假 ☐其他");
            dataMap.put("leaveReason", "倒休一天。");
            dataMap.put("leaveStartDate", "2018年10月14日上午");
            dataMap.put("leaveEndDate", "2018年10月14日下午");
            dataMap.put("leaveDay", "1");
            dataMap.put("leaveLeader", "同意");
            dataMap.put("leaveDeptLeaderImg", "同意!");
            
            PoiUtils.writeToDocx(templetDocPath,targetDocPath,dataMap);
            
            try {
                PoiUtils.readDocx(targetDocPath);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        /**
         * 通过XWPFDocument对内容进行访问。对于XWPF文档而言,用这种方式进行读操作更佳。
         * @throws Exception
         */
        public static void readDocx(String templetDocPath) throws Exception {
            InputStream is = new FileInputStream(templetDocPath);
            XWPFDocument doc = new XWPFDocument(is);
            List<XWPFParagraph> paras = doc.getParagraphs();
            for (XWPFParagraph para : paras) {
                //当前段落的属性
                System.out.println("para=="+para.getText());
            }
            //获取文档中所有的表格
            List<XWPFTable> tables = doc.getTables();
            List<XWPFTableRow> rows;
            List<XWPFTableCell> cells;
            for (XWPFTable table : tables) {
                //获取表格对应的行
                rows = table.getRows();
                for (XWPFTableRow row : rows) {
                    //获取行对应的单元格
                    cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        System.out.println("cell=="+cell.getText());;
                    }
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 生成一个docx文件
         * @param templetDocPath  模板文件的完整路径
         * @param targetDocPath 生成的目标文件的完整路径
         * @param dataMap 替换的数据*/
        public static void writeToDocx(String templetDocPath, String targetDocPath, Map<String,Object> dataMap){
            try
            {
                //得到模板doc文件的HWPFDocument对象
                InputStream in = new FileInputStream(templetDocPath);
                writeToDocx(in,targetDocPath,dataMap);
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }
        }
    
        /**
         * 生成一个docx文件,主要用于直接读取asset目录下的模板文件,不用先复制到sd卡中
         * @param templetDocInStream  模板文件的InputStream
         * @param targetDocPath 生成的目标文件的完整路径
         * @param dataMap 替换的数据*/
        public static void writeToDocx(InputStream templetDocInStream, String targetDocPath, Map<String,Object> dataMap){
            try
            {
                //得到模板doc文件的HWPFDocument对象
                XWPFDocument HDocx = new XWPFDocument(templetDocInStream);
                //替换段落里面的变量  
                replaceInPara(HDocx, dataMap);  
                //替换表格里面的变量  
                replaceInTable(HDocx, dataMap);  
                
                //写到另一个文件中
                OutputStream os = new FileOutputStream(targetDocPath);  
                //把doc输出到输出流中
                HDocx.write(os);
                os.close();
                templetDocInStream.close();
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
        
        /** 
        * 替换段落里面的变量 
        * @param doc 要替换的文档 
        * @param params 参数 
        */  
        private static void replaceInPara(XWPFDocument doc, Map<String, Object> params) {  
            Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();  
            XWPFParagraph para;  
            while (iterator.hasNext()) {  
                para = iterator.next();  
                replaceInPara(para, params);  
            }  
        }
        
        
        
        /**
         * 替换段落里面的变量
         * @param para 要替换的段落
         * @param params 参数
         */
        private static void replaceInPara(XWPFParagraph para, Map<String, Object> params) {
            List<XWPFRun> runs;
            System.out.println("para.getParagraphText()=="+para.getParagraphText());
            
            runs = para.getRuns();
            for (int i=0; i<runs.size(); i++) {
                XWPFRun run = runs.get(i);
                String runText = run.toString();
                System.out.println("runText=="+runText);
                
                // 替换文本内容,将自定义的$xxx$替换成实际文本
                for(Map.Entry<String, Object> entry : params.entrySet())
                {
                    runText = runText.replace(entry.getKey(), entry.getValue()+"");
                    //直接调用XWPFRun的setText()方法设置文本时,在底层会重新创建一个XWPFRun,把文本附加在当前文本后面,
                    //所以我们不能直接设值,需要先删除当前run,然后再自己手动插入一个新的run。
                    para.removeRun(i);
                    para.insertNewRun(i).setText(runText);
                }
            }
        }
        
        /** 
        * 替换表格里面的变量 
        * @param doc 要替换的文档 
        * @param params 参数 
        */  
       private static void replaceInTable(XWPFDocument doc, Map<String, Object> params) {  
          Iterator<XWPFTable> iterator = doc.getTablesIterator();  
          XWPFTable table;  
          List<XWPFTableRow> rows;  
          List<XWPFTableCell> cells;  
          List<XWPFParagraph> paras;  
          while (iterator.hasNext()) {  
             table = iterator.next();  
             rows = table.getRows();  
             for (XWPFTableRow row : rows) {  
                cells = row.getTableCells();  
                for (XWPFTableCell cell : cells) {  
                    paras = cell.getParagraphs();  
                    for (XWPFParagraph para : paras) {  
                       replaceInPara(para, params);  
                    }  
                }  
             }  
          }  
       }  
    
    }
    PoiUtils.java

    4、运行

    5、效果【生成的docx文件有问题,之前的样式全失效了

    混淆配置

    暂无

    参考资料

    Android使用ApachePOI组件读写Worddoc和docx文件

    Android 下使用 Poi 读取高版本excel

    Java:封装POI实现word的docx文件的简单模板功能

    使用POI读写word docx文件

    POI操作word2007(docx)文件的文本和图片

    项目demo下载地址

    链接:https://pan.baidu.com/s/165hpn3kZssxVvHIF9RNtkQ 提取码:3mmj

  • 相关阅读:
    UnixTime的时间戳的转换
    dotnet cors 跨域问题
    sqlServer备份和还原语句
    mvc的生命周期
    Java序列化
    js 分页
    jquery js 分页
    Myeclipse 6.0代码
    前序遍历_中序遍历_后序遍历
    数组去重的一些方法以及数组排序
  • 原文地址:https://www.cnblogs.com/whycxb/p/9796659.html
Copyright © 2020-2023  润新知