通过freemarker制作word比较简单

步骤:制作word模板。制作方式是:将模板word保存成为xml----在xml的word模板中添加相应的标记----将xml的word文件的后缀名改成ftl文件(要注意的是生成xml格式要是2003格式的xml,也就是说拿到的word模板得是2003格式的,否则用wps打开word将会出现问题)

详细步骤如下:

  1. 模板制作(将要动态显示的数据打上标记,这个标记是freemarker中的EL标记,要注意的是,要控制值为空的情况,下面${(site.wzmc)?default(“”)}标识当网站名称为空的时候显示空值,如果这里如果不做控制,在实际项目中会显示错误!)

另外要注意的是:

一、不要直接在word中替换掉文字的方式添加标记,这种会有问题。

二、不要使用Eclipse对xml文件进行格式化,这种生成word的时候会提示文档有问题。解决这个的问题是通过firstobject对word的xml进行格式化,对xml进行编辑。(使用firstobject打开带有中文文件名的xml文件的时候,会出现问题,建议使用英文word文档名称)

三、firstobject下载地址:http://www.firstobject.com/dn_editor.htm

其中,要想软件能够格式化xml代码,需要进行设置,设置方式是:打开firstobject----Tools-----Preferences------Format-----Tabs

点击Indent,结果xml变成了有格式化的,效果图如下:

常见标签:

行标记:

<w:p w:rsidR="00790C22"w:rsidRPr="00C07F75" w:rsidRDefault="00790C22"w:rsidP="004018B7">

标识是一个表格的标签

<w:tbl></w:tb1>

表格行:

<w:trw:rsidR="00790C22" w:rsidRPr="00C07F75"w:rsidTr="004018B7"></w:tr>

表格中的单元格:

<w:tc></w:tc>

循环输出数据的方式

<#list problemInfoInterview as problemInfo>

<w:tbl>

<w:tblPr>

<w:tblW w:w="0" w:type="auto"/>

<w:tblBorders>

<w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/>

<w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/>

<w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/>

<w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/>

<w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/>

<w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/>

</w:tblBorders>

<w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1"/>

</w:tblPr>

<w:tblGrid>

<w:gridCol w:w="2235"/>

<w:gridCol w:w="6287"/>

</w:tblGrid>

<w:tr w:rsidR="00790C22" w:rsidRPr="00C07F75" w:rsidTr="004018B7">

<w:tc>

<w:tcPr>

<w:tcW w:w="2235" w:type="dxa"/>

<w:shd w:val="clear" w:color="auto" w:fill="auto"/>

<w:vAlign w:val="center"/>

</w:tcPr>

<w:p w:rsidR="00790C22" w:rsidRPr="00C07F75" w:rsidRDefault="00790C22" w:rsidP="004018B7">

<w:pPr>

<w:jc w:val="center"/>

<w:rPr>

<w:rFonts w:ascii="Times New Roman" w:eastAsia="黑体" w:hAnsi="Times New Roman"/>

<w:sz w:val="24"/>

<w:szCs w:val="24"/>

</w:rPr>

</w:pPr>

<w:r>

<w:rPr>

<w:rFonts w:ascii="Times New Roman" w:eastAsia="黑体" w:hAnsi="Times New Roman" w:hint="eastAsia"/>

<w:sz w:val="24"/>

<w:szCs w:val="24"/>

</w:rPr>

<w:t>问题名称</w:t>

</w:r>

</w:p>

</w:tc>

<w:tc>

<w:tcPr>

<w:tcW w:w="6287" w:type="dxa"/>

<w:shd w:val="clear" w:color="auto" w:fill="auto"/>

<w:vAlign w:val="center"/>

</w:tcPr>

<w:p w:rsidR="00790C22" w:rsidRPr="00C07F75" w:rsidRDefault="00790C22" w:rsidP="004018B7">

<w:pPr>

<w:jc w:val="left"/>

<w:rPr>

<w:rFonts w:ascii="Times New Roman" w:eastAsia="宋体" w:hAnsi="Times New Roman"/>

<w:sz w:val="24"/>

<w:szCs w:val="24"/>

</w:rPr>

</w:pPr>

<w:r>

<w:rPr>

<w:rFonts w:ascii="Times New Roman" w:eastAsia="宋体"

w:hAnsi="Times New Roman" w:hint="eastAsia" />

<w:sz w:val="24" />

<w:szCs w:val="24" />

</w:rPr>

<w:t>${(problemInfo.problemName)?default("")}</w:t>

</w:r>

</w:p>

</w:tc>

</w:tr>

这里面的行删除

</w:tbl>

<w:p w:rsidR="007F35A8" w:rsidRPr="007F35A8" w:rsidRDefault="007F35A8" w:rsidP="007F35A8" />

-4-5下午6:02:11

*@version V1.0

*/

publicclass FreeMarkerUtil {

privatestatic Configurationconfiguration =null;

privatestatic Map<String, Template>allTemplates =null;

static {

configuration =new Configuration();

configuration.setDefaultEncoding("utf-8");

//configuration.setClassForTemplateLoading(FreeMarkerUtil.class,

//   "../template");

try {

configuration.setDirectoryForTemplateLoading(

new File(TemplateUtil.reportTemplatePath));

}catch (IOException e1) {

e1.printStackTrace();

}

allTemplates =new HashMap<String, Template>();

try {

allTemplates.put("word",configuration.getTemplate(TemplateUtil.templateFileName));

}catch (Exception e) {

e.printStackTrace();

thrownew RuntimeException(e);

}

}

public FreeMarkerUtil() {

}

publicstatic File createDoc(Map<?, ?> dataMap,String type){

String name ="temp" + (int) (Math.random() * 100000) +".doc";

File f =new File(name);

Template t =allTemplates.get(type);

try {

//这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word

//文档会因为有无法识别的编码而无法打开

Writer w =new OutputStreamWriter(new FileOutputStream(f),"utf-8");

t.process(dataMap, w);

w.close();

}catch (Exception ex) {

ex.printStackTrace();

thrownew RuntimeException();

}

return f;

}

publicstatic String getImageString(String fileName)throws IOException {

InputStream in =null;

byte[] data =null;

try {

in =new FileInputStream(fileName);

data =newbyte[in.available()];

in.read(data);

in.close();

}catch (Exception e) {

e.printStackTrace();

}finally {

if (in !=null){

in.close();

}

}

Base64Encoder encoder =new Base64Encoder();

return data !=null ? encoder.encode(data) :"";

}

}

出Word的Controller层的代码,并解决出word时中文文件名乱码的问题

package com.ucap.netcheck.controller;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

import java.net.URLEncoder;

import java.util.Map;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import com.ucap.netcheck.entity.Site;

import com.ucap.netcheck.entity.User;

import com.ucap.netcheck.service.IReport2WordService;

import com.ucap.netcheck.service.ISiteService;

import com.ucap.netcheck.utils.DateUtil;

import com.ucap.netcheck.utils.FreeMarkerUtil;

/**

* @Title: Report2WordController.java

* @Package com.ucap.netcheck.controller

* @Description:生成word部分的Controller

* @author Zuoquan Tu

* @date 2015-4-12上午9:36:43

* @version V1.0

*/

@Controller

@RequestMapping(value = "/reportToWord", method = { RequestMethod.GET,

RequestMethod.POST })

public class Report2WordController {

@Autowired

private IReport2WordService report2WordService;

@Autowired

private ISiteService siteService;

@RequestMapping(value = "/word")

public String outWord(Model model, HttpServletRequest request,

HttpServletResponse response) throws Exception {

request.setCharacterEncoding("utf-8");

//获取innerUUID,taskId

String siteCode = request.getParameter("innerUUID");

//获取taskId

Integer taskId = Integer.parseInt(request.getParameter("taskId"));

//获取用户的userId

User user = (User) request.getSession().getAttribute("user");

//通过下面的方式获得模板的参数

Site site = siteService.findSite(siteCode);

String webSiteName = site.getWzmc();

Map<String, Object> map = report2WordService.generateWordData(siteCode,

taskId, user.getId());

//获取innerUUID,taskId

// Map<String, Object> map = new HashMap<String, Object>();

//获取innerUUID,taskId

// Map<String, Object> map = new HashMap<String, Object>();

// map.put("taskNum", "测试");

// map.put("tackRunNum", "测试2……rqwrqw");

// String imageStr = new FreeMarkerUtil().getImageString("D:/1.png");

// map.put("imgStr", imageStr);

//

// List<CheckService> newsList = new ArrayList<CheckService>();

// for (int i = 0; i < 10; i++) {

// CheckService checkService = new CheckService();

// checkService.setTaskRunNum(10);

// checkService.setTaskNum(1000);

// newsList.add(checkService);

// }

// map.put("newList", newsList);

this.generateWord(request,response, map, webSiteName);

return null;

}

@SuppressWarnings("static-access")

private void generateWord(HttpServletRequest request,HttpServletResponse response,

Map<String, Object> map, String webSiteName)

throws FileNotFoundException, IOException {

File file = null;

InputStream fin = null;

ServletOutputStream out = null;

try {

//调用工具类WordGenerator的createDoc方法生成Word文档

file = new FreeMarkerUtil().createDoc(map, "word");

fin = new FileInputStream(file);

response.setCharacterEncoding("utf-8");

response.setContentType("application/msword");

//设置浏览器以下载的方式处理该文件默认名为下面的文件,按照时间来生成的一个文件名称

String longMsDateStr = DateUtil.getStringLongMsDate();

String fileName = webSiteName + "_" + longMsDateStr + ".doc";

//设置下载用的文件名

setFileDownloadHeader(request, response, fileName);

//response.addHeader("Content-Disposition", "attachment;filename=" + fileName);

out = response.getOutputStream();

byte[] buffer = new byte[512];

int bytesToRead = -1;

//通过循环将读入的Word文件的内容输出到浏览器中

while ((bytesToRead = fin.read(buffer)) != -1) {

out.write(buffer, 0, bytesToRead);

}

} finally {

if (fin != null)

fin.close();

if (out != null)

out.close();

if (file != null)

file.delete(); //删除临时文件

}

}

/**

*根据当前用户的浏览器不同,对文件的名字进行不同的编码设置,从而解决不同浏览器下文件名中文乱码问题

*/

public static void setFileDownloadHeader(HttpServletRequest request,

HttpServletResponse response, String fileName) {

final String userAgent = request.getHeader("USER-AGENT");

try {

String finalFileName = null;

if (StringUtils.contains(userAgent, "MSIE")) {

// IE浏览器

finalFileName = URLEncoder.encode(fileName, "UTF8");

} else if (StringUtils.contains(userAgent, "Mozilla")) {

// google,火狐浏览器

finalFileName = new String(fileName.getBytes(), "ISO8859-1");

} else {

//其他浏览器

finalFileName = URLEncoder.encode(fileName, "UTF8");

}

//这里设置一下让浏览器弹出下载提示框,而不是直接在浏览器中打开

response.setHeader("Content-Disposition", "attachment; filename=\""

+ finalFileName + "\"");

} catch (Exception e) {

e.printStackTrace();

}

}

}

ServiceImpl层的实现类

package com.ucap.netcheck.service.impl;

import java.text.NumberFormat;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.ucap.netcheck.combination.beans.TargetTypeParentToChildBean;

import com.ucap.netcheck.dao.IReport2WordDao;

import com.ucap.netcheck.entity.CheckService;

import com.ucap.netcheck.entity.MainPageScanFail;

import com.ucap.netcheck.entity.MainPageScanResult;

import com.ucap.netcheck.entity.ProblemInfo;

import com.ucap.netcheck.entity.Site;

import com.ucap.netcheck.entity.SiteService;

import com.ucap.netcheck.service.CheckServiceService;

import com.ucap.netcheck.service.IReport2WordService;

import com.ucap.netcheck.service.ISingleRejectResultService;

import com.ucap.netcheck.service.ISiteService;

import com.ucap.netcheck.service.SiteServService;

import com.ucap.netcheck.service.TargetTypeService;

import com.ucap.netcheck.utils.DateUtil;

/**

* @Title: Report2WordServiceImpl.java

* @Package com.ucap.netcheck.service.impl

* @Description:

* @author

* @date 2015-4-12上午11:58:09

* @version V1.0

*/

@Service

public class Report2WordServiceImpl implements IReport2WordService {

@Autowired

private ISiteService siteService;

@Autowired

private CheckServiceService checkServiceService;

@Autowired

private IReport2WordDao report2WordDao;

@Autowired

private TargetTypeService targetTypeService;

@Autowired

private ISingleRejectResultService singleRejectResultService;

@Autowired

private SiteServService siteServService;

/**

* generateWordData(通过这个方法获得生成报告所需的数据)

*

* @Title: generateWordData

* @Description:通过这个方法获得生成报告所需的数据

* @param @return   返回所需的数据

* @return Map<String,Object>   返回的数据

* @throws

*/

@Override

public Map<String, Object> generateWordData(

String siteCode,Integer taskId,String userId) {

Map<String, Object> map = new HashMap<String, Object>();

//网站名称,首页网址,报告编号,报告日期

Site site = siteService.findSite(siteCode);

map.put("site", site);

//生成报告编号和报告日期

map.put("reportCode", DateUtil.getNowDateStr() + "_" + taskId);

map.put("reportDate", DateUtil.getYearMonthAndDay());

//检查方法的数据,获得CheckService的值

//通过siteCode查找site_service

SiteService siteService = siteServService.findSiteService(siteCode);

CheckService checkService = report2WordDao.findCheckService(siteService.getServId());

map.put("checkService", checkService);

//设置开通时间的日期

map.put("checkServiceOpenTime", DateUtil.dateToStr(checkService.getOpenTime()));

//设置结束时间的日期

map.put("checkServiceCloseTime", DateUtil.dateToStr(checkService.getCloseTime()));

return map;

}

}

Ftl语法:

一、判断list的channelUpdateResults是否为空,判断list的大小是否大于某个值,注意加括号

<#if channelUpdateResults??>

<#if (channelUpdateResults?size>=10) >

未更新数量为“单项否决”。

</#if>

</#if>

二、list迭代

<#list queryMainPageScanFailList as mainPageScanFail>

</#list>

四、迭代的时候输出序号

${( mainPageScanFail _index+1)?default("")}  其中

五、if语句中取数组的值

<#if deadUrl[0] == 1>

是                                                                                             <#else>                                                                                            否                                                                             </#if>

六、<#assign>赋值,并且通过x_has_next来辨别当前项是否是序列的最后一项的布尔值。

<#assign seq = ["winter", "spring", "summer", "autumn"]>

<#list seq as x>

${x_index+ 1}. ${x}<#ifx_has_next>,</#if>

</#list>

七、解决出word中因为特殊字符“&”出现的问题,同时判断字符串为NULL和“”空字符串。如果在链接地址中出现了&字符,在生成的word会报错,解决办法是将这个特殊字符用“&amp;”替换掉,示例加链接的代码如下:

<#if (channelUpdate.url)??>
           <w:hlink w:dest="${(channelUpdate.url)?replace('&','&amp;')}">
            <w:r wsp:rsidR="002F59FF" wsp:rsidRPr="002F59FF">
             <w:rPr>
              <w:rStyle w:val="ab"/>
              <w:rFonts w:ascii="仿宋" w:fareast="仿宋" w:h-ansi="仿宋"/>
              <wx:font wx:val="仿宋"/>
              <w:sz w:val="24"/>
              <w:sz-cs w:val="30"/>
             </w:rPr>
             <w:t>${(channelUpdate.url)?replace('&','&amp;')}</w:t>
            </w:r>
           </w:hlink>
                                                                                                   </#if>

八、多次替换以及replace多次:

${(problemInfo.problemUrl)?replace("&","&amp;")?replace("<","&lt;")?replace(">","&gt;")}





通过freemarker生成一个word,解决生成的word用wps打开有问题的问题,解决出word时中文文件名乱码问题,解决打开出word时打开的word出现问题的问题,出图片,解决动态列表的更多相关文章

  1. 解决COS、FileUpload上传文件时中文文件名乱码问题

    方法: MultipartParser mp = new MultipartParser(request, 10*1024*1024); mp.setEncoding("GBK") ...

  2. Ubuntu下解决解压zip文件中文文件名乱码问题

    在Ubuntu下解压Windows下压缩的zip文件时,会出现解压出的带中文文件名的文件名乱码,这是因为Ubuntu和Windows默认的编码不同,Ubuntu下默认的编码是UTF-8,而Window ...

  3. 完美解决ExtJs6上传中文文件名乱码,后端SpringMVC

    ExtJs上传中文文件名乱码,观察请求. ExtJs6上传乱码从后台无法解决,因为文件名请求里面就已经乱码了,后台无法解码. 除非请求参数正确没有乱码,后台因为编码设置不一样,可以通过后台处理乱码 这 ...

  4. linux 学习解决归档管理器打开rar和zip中文文件名乱码问题

    在ubunut下打开windows下压缩的rar文件和zip压缩文件出现中文文件名乱码的问题真的很头疼.文件名乱码其实也没有什么关系是不?至少重命名再改回来或者是使用英文命名都可以克服.不巧的是,如此 ...

  5. 如何解决 Matlab 画图时中文显示乱码的问题?

    使用的是win10系统,从前几个月某一天,我的matlab的figure里的中文都变成了口口.很是郁闷,还以为是动到了什么配置引起的. 前几天更新了matlab 2018b,发现还有这个问题.就觉得不 ...

  6. Java ZIP压缩和解压缩文件(解决中文文件名乱码问题)

    Java ZIP压缩和解压缩文件(解决中文文件名乱码问题) 学习了:http://www.tuicool.com/articles/V7BBvy 引用原文: JDK中自带的ZipOutputStrea ...

  7. dotnetcore下解压zip文件,解决中文文件名乱码问题

    (迄今为止网上那些说的用Encoding.Default解决中文文件名乱码的都不能真正解决问题!) 1.在程序开始处 Encoding.RegisterProvider(CodePagesEncodi ...

  8. 解决Linux与Windows压缩解压中文文件名乱码(转载)

    转自:http://crazyfeng.com/linux-windows-compress-chinese-filename.html 由于Linux与Windows编码问题,使用Zip Tar 压 ...

  9. 上传文件,经过Zuul,中文文件名乱码解决办法

    转载请标明出处: http://blog.csdn.net/forezp/article/details/77170470 本文出自方志朋的博客 问题描述 在项目中又一个上传文件的oss服务,直接调用 ...

随机推荐

  1. 重写轮子之 ID3

    这是半成品, 已完成了 fit() 部分, 形成了包含一棵完整树的 node 对象. 后续工作是需解析该 node对象, 完成 predict() 工作. # !/usr/bin/python # - ...

  2. 利用生产者消费者模型和MQ模型写一个自己的日志系统-并发设计里一定会用到的手段

    一:前言 写这个程序主要是用来理解生产者消费者模型,以及通过这个Demo来理解Redis的单线程取原子任务是怎么实现的和巩固一下并发相关的知识:这个虽然是个Demo,但是只要稍加改下Appender部 ...

  3. SQL部分常用指令整理

    dual 伪表 用来测试函数和表达式 1.查询EMP表中所有人的信息,结果格式样例为"某人的月薪是1000$" SELECT ENAME||'的月薪是'||SAL||'$' FRO ...

  4. 如何改变hr颜色

    html中用css改变颜色,<hr style="border:0;background-color:#ff0000;height:1px;">如果不加border:0 ...

  5. 牛客网编程练习之PAT乙级(Basic Level):1033 害死人不偿命的(3n+1)猜想

    3n+1水题.... AC代码: import java.util.Scanner; /** * @author CC11001100 */ public class Main { public st ...

  6. Lua语言模型 与 Redis应用

    Lua语言模型 与 Redis应用 标签: Java与NoSQL 从 2.6版本 起, Redis 开始支持 Lua 脚本 让开发者自己扩展 Redis. 本篇博客主要介绍了 Lua 语言不一样的设计 ...

  7. ViewPager实现首次进入软件时左右滑屏的软件展示效果

    效果如图: 图片资源不再提供,大家可以自己下载,能实现效果即可,看代码: 首先是展示界面的layout: view.xml 注意,采用的是帧布局,页面切换时的小圆点是在各张图片之上的 <?xml ...

  8. Swift中如何转换不同类型的Mutable指针

    在Swift中我们拥有强大高级逻辑抽象能力的同时,低级底层操作被刻意的限制了.但是有些情况下我们仍然想做一些在C语言中的hack工作,下面本猫就带大家看一看如何做这样的事. hacking is ha ...

  9. Cocoa中层(layer)坐标系的极简理解

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) Cocoa层的坐标系一直理解的不清晰,现在把它整理总结一下: ...

  10. Java进阶(四十六)简述ArrayList、Vector与LinkedList的异同点

    简述ArrayList.Vector与LinkedList的异同点   Collection类的继承图如下:   从图中可以看出,LinkedList与ArrayList.ArrayDeque这三者都 ...