版权声明:本文为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

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

  1. FreemarkerJavaDemo【Android将表单数据生成Word文档的方案之一(基于freemarker2.3.28,只能java生成)】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这个方案只能在java中运行,无法在Android项目中运行.所以此方案是:APP将表单数据发送给后台,后台通过freemarker ...

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

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用Poi实现android中根据模板文件生成Word文档的功能.这里的模板文件是doc文件.如果模板文件是docx文件的话,请阅读 ...

  3. Android根据word模板文档将表单数据生成word文档的方案整理

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 尝试的方案包括以下几种: freemarker 只能在java项目上运行,无法在Android项目上运行: 参考资料:<Fre ...

  4. Java Web项目中使用Freemarker生成Word文档

    Web项目中生成Word文档的操作屡见不鲜.基于Java的解决方式也是非常多的,包含使用Jacob.Apache POI.Java2Word.iText等各种方式,事实上在从Office 2003開始 ...

  5. Java 导出数据库表信息生成Word文档

    一.前言 最近看见朋友写了一个导出数据库生成word文档的业务,感觉很有意思,研究了一下,这里也拿出来与大家分享一波~ 先来看看生成的word文档效果吧 下面我们也来一起简单的实现吧 二.Java 导 ...

  6. PowerDesigner将PDM导出生成WORD文档

    PowerDesigner将PDM导出生成WORD文档 环境 PowerDesigner15 1.点击Report Temlates 制作模板 2.如果没有模板,单击New图标创建.有直接双击进入. ...

  7. 将HTML导出生成word文档

    前言: 项目开发中遇到了需要将HTML页面的内容导出为一个word文档,所以有了这边随笔. 当然,项目开发又时间有点紧迫,第一时间想到的是用插件,所以百度了下.下面就介绍两个导出word文档的方法. ...

  8. POI生成word文档完整案例及讲解

    一,网上的API讲解 其实POI的生成Word文档的规则就是先把获取到的数据转成xml格式的数据,然后通过xpath解析表单式的应用取值,判断等等,然后在把取到的值放到word文档中,最后在输出来. ...

  9. 使用freemarker模板引擎生成word文档的开发步骤

    1.准备模板文档,如果word文档中有表格,只保留表头和第一行数据:2.定义变量,将word文档中的变量用${var_name}替换:3.生成xml文件,将替换变量符后的word文档另存为xml文件: ...

随机推荐

  1. SAE提供服务分析

    这个分析列表主要关注两个问题,服务能做什么,移植实现难度. AppConfig: 这个东西主要面向SAE本身的一些配置选项,移植时放弃这个东西,所以就不谈难度了Counter :这个东西提供某个操作的 ...

  2. 使用Glide以及OkHttp集成

    1.glide的使用: 添加依赖: compile 'com.github.bumptech.glide:glide:3.7.0' 调用代码: ImageView imageView = (Image ...

  3. C游新官网总结

    从2017年9月18号,我开始独立做C游新官网项目.第一次独立完成项目,压力还是挺大的,毕竟还要自己去写前端,前端我已经忘了差不多了. 做这个网站主要是公司开始转型,开始自己建立渠道倒量,这样网站的S ...

  4. 有终将被编程潮流淹没的程序员,那是因为没学python人工智能吧?

    2017年被称为中国人工智能元年--在两会时期,人工智能曾经成为国度计策,同时被写进当局报告.在从前的一年里,人工智能获得注重,已逐步浸透到别的行业,无人超市.主动驾驶.人脸识别.智能家居等" ...

  5. HTML学习笔记6:列表标签

    列表标签     什么是列表标签呢? 以平台区分有什么游戏? 手游 pc游戏 家用机游戏 掌机游戏 以游戏类型区分有什么游戏? RPG ARPG MMORPG ACT FPS 以上两种就是一种列表标签 ...

  6. 基于DP的LCS(最长公共子序列)问题

    最长公共子序列,即给出两个序列,给出最长的公共序列,例如: 序列1 understand 序列2 underground 最长公共序列undernd,长度为7 一般这类问题很适合使用动态规划,其动态规 ...

  7. Fibonacci数列使用迭代器实现

    Fibonacci数列,数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... class FibItera ...

  8. Java中的String类型

    1.基本类型和引用类型 在C语言里面,是有指针这么一个变量类型的,指针变量保存的就是所要指向内容的地址.在Java里面,没有了指针的这么个说法,而是换了一个词:引用类型变量. 先说Java里面的基本类 ...

  9. CSS学习笔记四:下拉选择框以及其动画特效

    以前学的只是了解了css的一些基本属性,在做项目的时候都是直接使用bootstrap响应式来写项目,这样子很方便,很快捷,但是在自己看来还是有一点缺陷的,毕竟,我很多时候不怎么清楚它里面的具体运作.所 ...

  10. PAT1082:Read Number in Chinese

    1082. Read Number in Chinese (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...