`

使用freemarker生成word

    博客分类:
  • Java
阅读更多

最近弄一个项目,需要读取xml文件里面的内容生成word文档,网上找了很多方案,最后选择用freemarker来处理,一是读写起来比较简单,而是不需要设置复杂的Word格式且一旦格式有变化重新生成模板就成,不需要改java代码。这篇文档有介绍怎么生成xml模板以及静态的例子,我也是参考这篇来处理的。链接:

http://blog.csdn.net/lun379292733/article/details/18673081

 

我这里写个简单的过程吧,加深下印象。

 

一、创建模板文件:

1、找到需要做成模板的word文档,将其中的关键数据用EL表达式来替换,譬如:

姓名:wjl

改成:

姓名:${name}

 

2、将替换成EL之后的word另存为xml(注意保存时选择“只保存数据”);

 

3、修改xml文件的后缀名,改成ftl格式。

 

4、我的word模板里面有个需要循环的列表,列表里面的内容我定义成了${content},但是这个内容有很多,类似于循环一样,因此需要添加<#list>来体现循环,如图:

其中,真正的标签是<#list>,fileList是要循环的list,file是别面,用<c:foreach>来说就是:fileList是放在item里面的东西,file类似于var里面的东西。

5、我的这个ftl文件名称为:word.ftl,放在config文件夹下(不是包,参考的那篇文章是放在包下的,我这个放在文件夹下)。
 
二、读取xml文件生成word:

1、createWordFile用来组装业务,包括读取xml数据生成word,并返回给调用出的结果。

/**
 * 该方法用来生成word文件
 * @param:父级文件夹名称
 * @param:需要处理的文件所在目录
 * */
public boolean createWordFile(String parentFileName,String newFilePath) throws Exception{
	boolean result=false;
	File xmlFile = new File(newFilePath+File.separator+"200105.xml");
	if(xmlFile.isFile() && xmlFile.exists()){//是文件且存在
		List list = readWord(xmlFile);//组装数据、以及文件名称
		if(list!=null && list.size()>0){
			String wordName = list.get(0).toString();//文件名称
			Map dataMap = (Map)list.get(1);//集合数据
			String templateFilePath = new File("").getAbsolutePath()+File.separator+"config";//设定为当前文件夹
//				System.out.println("模板文件所在目录:"+templateFilePath);
			boolean flag = createWord(dataMap,templateFilePath,"word.ftl",classFile.getAbsolutePath(),wordName+".doc");//生成word
			if(flag){
				result=true;
			}else{
				errorInfo = "word文件生成失败!";
			}
		}else{
			errorInfo="无法读取"+(newFilePath+File.separator+"200105.xml")+"文件中的数据信息!";
		}
	}
	return result;
}

 

2、readWord用来读取xml文件组装数据,并返回数据以及word文件名称(因为word文件名称来源于xml文件)。

/***
 * 该方法用来组装数据
 * @param xmlFile:需要进行解析的xml文件
 * */
public List readWord(File xmlFile) {
	/** 用于组装word页面需要的数据 */
    Map<String, Object> dataMap = new HashMap<String, Object>();
    List list = null;
    StringBuffer wordName=new StringBuffer();//word文档名称:案件编号+名称+内部编号
	try {
		//读取XML
        SAXReader sax = getSAXReader();
        Document doc = sax.read(xmlFile);//读取文档
        String fileContent="",appAJ="";
        //1、案件编号
        Node  node = doc.selectSingleNode("//ANJIANBH");
        if(node!=null ){
     	  fileContent=node.getText().trim();
         }else{
        	 fileContent="";
         }
        wordName.append(fileContent);
        dataMap.put("caseNum",fileContent);//案件编号
        
        //2、名称
        node = doc.selectSingleNode("//FAMINGCZMC");
        if(node!=null ){
     	  fileContent=node.getText().trim();
         }else{
        	 fileContent="";
         }
        wordName.append(escapeExprSpecialWord(fileContent));//去除特殊字符
        dataMap.put("name",fileContent);//名称
        
         //3、内部编号/申请号
        fileContent="内部编号:";
        node = doc.selectSingleNode("//NEIBUBH");
        if(node!=null ){//说明没有内部编号
        	fileContent="内部编号:"+node.getText().trim();
        	appAJ = node.getText().trim();
        	if(appAJ.toUpperCase().startsWith("AJ")){//避免出现小写aj的情况,所以全部转成大写进行比较
				//内部编号用最后一个下划线截取
				appAJ = appAJ.substring(appAJ.lastIndexOf("_")+1);
			}
	     	wordName.append(appAJ);
         }else{//那么查找是否有申请号
        	 node = doc.selectSingleNode("//SHENQINGH");
        	 if(node!=null ){
        		 fileContent=node.getText().trim();
        		 wordName.append(fileContent.split(":")[1]);
        	 }
         }
        dataMap.put("num",fileContent);
        
      //4、提交人姓名或名称
        node = doc.selectSingleNode("//XINGMINGHMC");
        if(node!=null ){
        	fileContent=node.getText().trim();
         }else{
        	 fileContent="";
         }
        dataMap.put("proxy",fileContent);
       //5、 收到时间
        node = doc.selectSingleNode("//QIANMINGSJC");
        if(node!=null ){
        	fileContent=node.getText().trim();
         }else{
        	 fileContent="";
         }
        dataMap.put("time",fileContent);//收到时间
        
        //6、收到文件情况
         StringBuffer content= new StringBuffer();
         Element element=null;
         List<Map<String, Object>> fileList=new ArrayList<Map<String,Object>>();
         List<Element> els = doc.selectNodes("//SHOUDAOWJ");
         if(els!=null && els.size()>0){
         	for(int i=0;i<els.size();i++){
         		Map<String, Object> map=new HashMap<String, Object>();
         		element = els.get(i);
         		content.delete(0,content.length());//清空
         		content.append((i+1)+"、");//序号
         		node = element.selectSingleNode(".//WENJIANMC");//文件名称 
         		content.append(node.getText().trim()+"          ");
         		node = element.selectSingleNode(".//WENJIANGS");//文件格式
         		content.append(node.getText().trim()+"格式    ");
         		node = element.selectSingleNode(".//WENJIANDX");//文件大小
         		content.append("文件大小"+node.getText().trim());
//	         		System.out.println(content.toString());
    	        map.put("content", content.toString());
    	        fileList.add(map);
         	}
         }else{
        	 Map<String, Object> map=new HashMap<String, Object>();
        	 map.put("content","");
    	     fileList.add(map);
         }
         dataMap.put("fileList",fileList);
         // 落款时间
         node = doc.selectSingleNode("//SHOUDAOSJ");
         if(node!=null ){
        	 fileContent = node.getText().trim();
          }else{
        	  fileContent="";
          }
         dataMap.put("date",fileContent);//落款时间
         list = new ArrayList();
         list.add(wordName);
         list.add(dataMap);
	} catch (Exception e) {
		e.printStackTrace();
		return null;
	}
	return list;
}

/**
 * 该方法用来获取SXAReader对象
 * */
public SAXReader getSAXReader(){
	SAXReader saxReader = new SAXReader();
	/* 在读取文件时,去掉dtd的验证,可以缩短运行时间  */
	try {
//		saxReader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);//可能需要网络,所以不用它
		saxReader.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE, false);  //设置不需要校验头文件
	} catch (SAXException e) {
		e.printStackTrace();
	}
	return saxReader;
}

/**
 * 转义正则特殊字符 ($()*+.[]?\^{},|/\:?"<>)
 * @param keyword
 * @return
 */
public String escapeExprSpecialWord(String keyword) {
	if(keyword!=null && keyword.trim().length()>0){
		String[] fbsArr = {"/","\\",":","*","?","\"","<",">","|", "(", ")","+", "[", "]", "^", "{", "}","、"};
		for (String key : fbsArr) {
			if (keyword.contains(key)) {
				keyword = keyword.replace(key,"");
			}
		}
	}
	return keyword;
}

 

3、createWord用来生成word文档。

/**
* 该方法用来生成word文件
* @param dataMap:数据集合
* @param templateFilePath:模板文件所在目录
* @param templateFileName:模板文件名称
* @param docFilePath:生成的doc文件保存路径
*@param docFileName:生成的doc文件名称:名称+.doc
*/
public static boolean createWord(Map dataMap,
		String templateFilePath,String templateFileName,
		String docFilePath,String docFileName){
        try {
        	Configuration configuration = new Configuration();//创建配置实例 
            configuration.setDefaultEncoding("UTF-8");//设置编码
            configuration.setDirectoryForTemplateLoading(new File(templateFilePath));//加载模板文件
            Template template = configuration.getTemplate(templateFileName);//获取模板
            if(docFileName==null || !docFileName.toUpperCase().endsWith(".DOC")){//为空或者不是以doc结尾的,添加后缀名
            	docFileName = docFileName+".doc";
            }
            File outFile = new File(docFilePath+File.separator+docFileName);
            //如果输出目标文件夹不存在,则创建
            if (!outFile.getParentFile().exists()){
                outFile.getParentFile().mkdirs();
            }
            //将模板和数据模型合并生成文件 
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
            //生成文件
            template.process(dataMap, out);
            //关闭流
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
}

 

 

三、需要用到的jar包:

freemarker-2.3.16.jar:使用freemarker生成word的主要包
dom4j-1.6.1.jar:解析xml文件的主要包
jaxen-1.1-beta-7.jar:解析xml文件的辅助包
已经上传到附件,有需要的可以下载。
 

三、需要注意的问题:

a、将word另存为xml得到的xml文件格式很乱,可能只有几行,可以通过格式化工具格式化一下。这样子易读性是增强了,但是可能会影响word格式。我这里有个落款时间就是因为格式化后出现了问题。格式化之前落款时间是居右显示,格式化之后竟然居中了,代码没有变化,可能就是中间出现了空格导致了问题。所以格式化之后最好测试话一下,或者不要格式化。
 
b、得到的xml文件里的$与参数分开了。譬如原本的word里面写的参数为${content},xml之后${content}被拆成了${,content,和}三部分。具体原因和解决办法可以看看参考文件,我这就是老出现这个问题,弄了好几次还这样子,不得已只能直接改xml文件。
 
c、put到map里的参数一定要与xml中写的的参数一致,否则会报错。特别是有list的情况下,别名一定不能忘。我的例子就是${file.content}这个file一定不能忘,否则也会报错。值得庆幸的是,报错很明显,一查就能查不出来。
  • 大小: 201.9 KB
分享到:
评论

相关推荐

    利用FreeMarker生成word文件例子

    ### 使用FreeMarker生成Word文档 1. **配置FreeMarker**:首先,需要在项目中引入FreeMarker的依赖,例如通过Maven或Gradle添加对应的依赖库。然后,配置FreeMarker的环境,包括设置模板目录、缓存策略等。 2. **...

    使用freemarker生成word文档,源代码+jar包+说明文档及注意事项

    使用freemarker生成word ,并集成struts2 同时生成及下载文档 资料附有Java源代码和自己总结的使用说明及注意事项 大至预览如下: 1、用word编辑好模板 普通字符串替换为 ${string} 表格循环用标签 姓名:${...

    FreeMarker生成word文件

    以下是关于如何使用FreeMarker生成Word文件的一些关键知识点: 1. **FreeMarker模板语言**:FreeMarker使用一种简单的模板语言,允许开发者通过定义变量和控制结构(如循环和条件语句)来动态地插入数据。在模板中...

    java+Freemarker生成word

    在Java中使用Freemarker生成Word文档的过程主要包括以下几个步骤: 1. **环境配置**:首先,你需要在项目中引入必要的库,包括Apache POI用于处理Word文档,以及Freemarker库。在Maven项目中,可以在pom.xml文件中...

    用freemarker生成word.zip

    在使用FreeMarker生成Word之前,需要准备一个数据模型,包含要插入到文档中的文本和图片。图片可以作为`byte[]`数组存储,例如: ```java Map, Object&gt; dataModel = new HashMap(); dataModel.put("title", ...

    java利用freemarker生成word.pdf

    Java利用Freemarker生成Word/PDF是指使用Java语言结合Freemarker模板引擎来生成Word文档或PDF文件的技术。 Freemarker是一个基于Java的模板引擎,它允许开发者使用模板语言来生成文本输出。在本资源中,我们将介绍...

    freemarker生成word

    本篇文章将深入探讨如何使用FreeMarker生成Word文档。 1. FreeMarker 概述: FreeMarker 是一个基于模板的Java库,它允许开发者通过模板语言将数据模型与HTML、XML或其他文本格式分离。模板是纯文本文件,包含控制...

    用Freemarker生成word文档

    ### 使用Freemarker生成Word文档的关键技术点解析 #### 一、引言 在实际工作中,经常需要批量生成带有特定格式或数据填充的Word文档,如报表、合同、通知等。传统的手工创建方法效率低下且易出错。利用Java语言...

    springboot中使用freemarker动态生成word文档,以及使用POI导出自定义格式Excel

    Springboot项目中: 1. 使用Apache POI 3.9 自定义样式导出Excel文件...2. 使用freemarker动态生成word .doc文档(带图片Word以及复杂格式word) 详细说明见个人博客及 github: https://github.com/DuebassLei/excel-poi

    freemarker 生成word,支持一个单元格生成多张图片

    在Java中,生成Word文档通常借助于Apache POI库,而FreeMarker则作为模板引擎,负责数据和模板的结合。Apache POI提供API来操作Word文档,包括创建表格、插入图片等。FreeMarker则可以将动态数据与预先设计好的Word...

    Freemarker生成word文档

    3. 使用Freemarker生成Word文档 - 创建Freemarker模板:首先,我们需要创建一个`.ftl`文件,定义好Word文档的结构和样式,使用Freemarker语法(例如`${expression}`)来表示需要动态填充的部分。 - 解析XML数据:...

    freemarker生成word,pdf转word,pdf插入图片

    freemarker根据模板ftl生成word,pdf格式转word,pdf指定位置插入图片

    freemarker_word.zip

    "freemarker_word.zip" 文件集合就是专门针对使用FreeMarker生成Word文档的一个资源包。 该压缩包包含以下关键组件: 1. **Product.ftl**:这是一个FreeMarker模板文件,扩展名为FTL(FreeMarker Template ...

    freemarkerdemo 生成word 插入图片

    在这个"freemarkerdemo生成word插入图片"的示例中,我们主要探讨如何利用Freemarker来创建Word文档,并且将图片集成到这些文档中。这个过程涉及到几个关键的技术点: 1. **Freemarker基础知识**:Freemarker是一个...

    freemarker根据word模板生成word的完整示例

    在这个示例中,我们将深入探讨如何使用Freemarker根据XML模板生成Word文档。 首先,你需要了解Freemarker的基本概念。Freemarker是一个基于模板的语言,它的核心是模板文件,模板文件中包含了一系列控制结构(如...

    Java中使用 FreeMarker 生成pdf盖章合同文件

    本篇文章将深入探讨如何在Java中使用FreeMarker生成带有盖章的PDF合同文件。 首先,让我们了解FreeMarker的基本概念。FreeMarker是一个基于模板的语言,它与Java代码分离,允许开发者用简单的模板语法来表示数据。...

    freemarker生成word的一个简单例子

    总结起来,这个入门级的例子展示了如何使用Freemarker生成Word文档的基本步骤。通过模板和数据模型的结合,Freemarker提供了一种灵活的方式来自动生成结构化的文档,大大简化了编程工作。在实际项目中,你可以根据...

Global site tag (gtag.js) - Google Analytics