工作中,我们时常会遇到一些操作文件的操作,比如在线生成合同模板,上传/下载/解析Excel,doc文档转为pdf等操作。本文就已工作中遇到的在线生成合同为例,简要地介绍一种文档替换写法。

本文目的:给出源文件模板,通过程序操作后,替换模板中的指定内容,从而生成固定模板的文件。

使用场景:生成固定格式的合同信息。

原理:给一个文档模板,需要替换的内容以 $$包含,然后,在代码中给需要替换的字段赋值,生成新的文档。

工具包:poi-ooxml-3.10.jar   自己网上下载

代码:

 package word2pdf;

 import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; 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.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow; public class DocWriterTest { public static void searchAndReplace(String srcPath, String destPath, Map<String, String> map) {
try {
XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(srcPath));
/**
* 替换段落中的指定文字
*/
Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
while (itPara.hasNext()) {
XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
Set<String> set = map.keySet();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String key = iterator.next().trim();
List<XWPFRun> run = paragraph.getRuns();
int runSize = run.size();
for (int i = 0; i < runSize; i++) {
String text = run.get(i).getText(0);
System.out.println("++++++text++++++:" + text);
for (Entry<String, String> e : map.entrySet()) {
if (text != null && text.contains(e.getKey())) {
text = text.replace(e.getKey(), e.getValue());
System.out.println("++++++text222222222++++++:" + text);
run.get(i).setText(text, 0);
}
}
}
}
} /**
* 替换表格中的指定文字
*/
Iterator<XWPFTable> itTable = document.getTablesIterator();
while (itTable.hasNext()) {
XWPFTable table = (XWPFTable) itTable.next();
int count = table.getNumberOfRows();
for (int i = 0; i < count; i++) {
XWPFTableRow row = table.getRow(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
for (XWPFParagraph p : cell.getParagraphs()) {
for (XWPFRun r : p.getRuns()) {
String text = r.getText(0);
for (Entry<String, String> e : map.entrySet()) {
if (text != null && text.contains(e.getKey())) {
text = text.replace(e.getKey(), e.getValue());
r.setText(text, 0);
}
}
}
} }
}
}
FileOutputStream outStream = null;
outStream = new FileOutputStream(destPath);
document.write(outStream);
outStream.close();
} catch (Exception e) {
e.printStackTrace();
} } public static void main(String[] args) throws Exception {
Map<String, String> map = new HashMap<String, String>();
map.put("$name$", "coco");
map.put("$sex$", "女");
map.put("work", "Java开发");
String srcPath = "E:\\cocoxu\\test_mode\\sourcefile.docx";
String destPath = "E:\\cocoxu\\test_mode\\destfile.docx";
searchAndReplace(srcPath, destPath, map);
}
}

调试时遇到的报错:

1.

java.lang.IllegalStateException: Zip File is closed
at org.apache.poi.openxml4j.util.ZipFileZipEntrySource.getEntries(ZipFileZipEntrySource.java:45)
at org.apache.poi.openxml4j.opc.ZipPackage.getPartsImpl(ZipPackage.java:182)
at org.apache.poi.openxml4j.opc.OPCPackage.getParts(OPCPackage.java:665)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:226)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:186)
at org.apache.poi.POIXMLDocument.openPackage(POIXMLDocument.java:67)
at word2pdf.DocWriterTest.searchAndReplace(DocWriterTest.java:23)
at word2pdf.DocWriterTest.main(DocWriterTest.java:93)

此类错看似是zip文件被关闭,其实不然。其实是由于文档路径写错,找不到文件导致的。

String srcPath = "E:\\cocoxu\\\test_mode\\sourcefile.docx";

2、没有生产想要的文件:

sourcefile.docx内容:

目的是用代码中的内容,替换文档中的内容,但是我们第一次得到的确实这样的:

在代码中打印日志,可以看到,word文档中的$name$被跨行分开了:

本来是一行的东西,为什么代码执行操作的时候会被分成三行呢?这个就是doc文档操作的问题啦 ,

方法一:操作源文档,对文档中所有拼写语法不合规范的都忽略

方法二:创建一个新文档,在纯英文格式下拼写字段,然后复制带源文件中,即可。

最终得到的目的问题内容:

至此,我们用java操作文档的案例就结束了,实际工作中也可以模仿此类代码去生成哦。

Java中常用到的文件操作那些事(一)——替换doc文档模板,生成真实合同案例的更多相关文章

  1. Java中常用到的文件操作那些事(二)——使用POI解析Excel的两种常用方式对比

    最近生产环境有个老项目一直内存报警,不时的还出现内存泄漏,导致需要重启服务器,已经严重影响正常服务了.获取生成dump文件后,使用MAT工具进行分析,发现是其中有个Excel文件上传功能时,经常会导致 ...

  2. JAVA中让Swagger产出更加符合我们诉求的描述文档,按需决定显示或者隐藏指定内容

    大家好,又见面啦. 在前一篇文档<JAVA中自定义扩展Swagger的能力,自动生成参数取值含义说明,提升开发效率>中,我们探讨了如何通过自定义注解的方式扩展swagger的能力让Swag ...

  3. Java中常用IO流之文件流的基本使用姿势

    所谓的 IO 即 Input(输入)/Output(输出) ,当软件与外部资源(例如:网络,数据库,磁盘文件)交互的时候,就会用到 IO 操作.而在IO操作中,最常用的一种方式就是流,也被称为IO流. ...

  4. Java中常用的操作PDF的类库

    iText iText是一个能够快速产生PDF文件的java类库.iText的java类对于那些要产生包含文本,表格,图形的只读文档是很有用的.它的类库尤其与java Servlet有很好的给合.使用 ...

  5. java中常用的工具类(三)

    继续分享java中常用的一些工具类.前两篇的文章中有人评论使用Apache 的lang包和IO包,或者Google的Guava库.后续的我会加上的!谢谢支持IT江湖 一.连接数据库的综合类       ...

  6. java中常用的工具类(二)

    下面继续分享java中常用的一些工具类,希望给大家带来帮助! 1.FtpUtil           Java   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  7. java中常用的工具类(一)

    我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...

  8. Java高级特性 第2节 java中常用的实用类(1)

    一.Java API Java API即Java应用程序编程接口,他是运行库的集合,预先定义了一些接口和类,程序员可以直接调用:此外也特指API的说明文档,也称帮助文档. Java中常用的包: jav ...

  9. Java中常用的设计模式代码与理解

    Java中常用的设计模式代码与理解 一.单例模式 1.饿汉式 (太饿了,类加载的时候就创建实例) /** * 饿汉式单例模式 */ public class HungrySingleInstance ...

随机推荐

  1. ADT离线安装

    1.安装eclipse软件.安装后点击HELP菜单,找到下面的Install New Software并点击. 2.之后会弹出一个对话框,然后我们点击add,接下来弹出ADD对话框,然后我们再点击ar ...

  2. null与not null

    .not null CREATE TABLE `test` ( `col1` VARCHAR( ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NUL ...

  3. ubuntu 卡在登陆界面无法进入桌面,但是可以进入命令行界面

    ubuntu 卡在登陆界面无法进入桌面,但是可以进入命令行界面(初步断定是Xwindows界面软件出问题了,所以重装即可!)Solve: 1.Ctrl+Alt+F1进入命令行界面,root账户登陆2. ...

  4. UVa 11136 Hoax or what (STL)

    题意:有 n 天,每天有m个数,开始的前一天没有数据,然后每天从这个里面拿出一个最大的和最小的,求 n 天的最大的和最小的差值相加. 析:一看就知道用set啊,多简单的STL,不过要注意,开long ...

  5. S5PV210定时器

    在S5PV210内部,一共有4类定时器件.这4类定时器件的功能.特征是不同的. 1.PWM定时器(1)这种是最常用的,平时所说的定时器一般指的是这个.像简单单片机(譬如51单片机)中的定时器也是这类. ...

  6. 对ConditionQueue和锁的理解

    1. 什么时候使用conditionQueue 使用conditionQueue的一个最基本的条件是,操作和状态相关,而且是多线程同时访问的状态. 也就是说在使用conditionQueue的时候, ...

  7. Zynq学习笔记(1)——Hellow World

    Zynq是一款SOC芯片,之前只是用了PL(Programmable Logic)部分,而Zynq最突出的功能,就是内部的双核Cortex-A9,所以从现在开始我将学习ZYNQ的SOC学习(PS部分) ...

  8. leetcode-8-String to Integer (atoi) (已总结)

    8. String to Integer (atoi) Total Accepted: 93917 Total Submissions: 699588 Difficulty: Easy Impleme ...

  9. SpringMvc与Struts2的对比

    目前企业中使用SpringMvc的比例已经远远超过Struts2,那么两者到底有什么区别,是很多初学者比较关注的问题,下面我们就来对SpringMvc和Struts2进行各方面的比较: 1.核心控制器 ...

  10. Android-有序广播是可以中断的

    在之前的博客,Android-广播概念,中介绍了(广播和广播接收者)可以组件与组件之间进行通讯,有两种类型的广播(无序广播 和 有序广播),这篇博客就来讲解有序广播的代码实现: 有序广播:接收者 可以 ...