通过freemarker生成一个word,解决生成的word用wps打开有问题的问题,解决出word时中文文件名乱码问题,解决打开出word时打开的word出现问题的问题,出图片,解决动态列表
来源:互联网 发布:mac删除文件的命令 编辑:程序博客网 时间:2024/05/29 02:29
通过freemarker制作word比较简单
步骤:制作word模板。制作方式是:将模板word保存成为xml----在xml的word模板中添加相应的标记----将xml的word文件的后缀名改成ftl文件(要注意的是生成xml格式要是2003格式的xml,也就是说拿到的word模板得是2003格式的,否则用wps打开word将会出现问题)
详细步骤如下:
模板制作(将要动态显示的数据打上标记,这个标记是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" />
</#list>
另外,往文档中插入图片的时候,在做模板的时候要往模板中插入一个图片,然后打开文档,然后替换掉base64转码的图片部分。
将图片资源变成base64加密后的图片的代码
将图片转成base64串的方式:
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用的相关的类:
读取路径用的TemplateUtil工具类
package com.ucap.netcheck.utils;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.Properties;
/**
* @Title: TemplateUtil.java
* @Package com.ucap.netcheck.utils
* @Description:
* @author
* @date 2015-4-13下午9:07:58
* @version V1.0
*/
public class TemplateUtil {
//模板所在的位置
public static String reportTemplatePath;
//模板的名称
public static String templateFileName;
static {
URL resource = TemplateUtil.class.getClassLoader().getResource("template.properties");
System.out.println(resource.getPath());
File file = new File(resource.getPath());
//生成文件输入流
FileInputStream in = null;
try {
in = new FileInputStream(file);
} catch (Exception e) {
e.printStackTrace();
}
//生成properties对象
Properties prop = new Properties();
try {
prop.load(in);
} catch (Exception e) {
e.printStackTrace();
}
reportTemplatePath = prop.getProperty("reportTemplatePath");
templateFileName = prop.getProperty("templateFileName");
}
/*public static void main(String[] args) {
System.out.println(TemplateUtil.reportTemplatePath);
}*/
}
配置文件路径截图:
FreeMarkerUtil工具类
package com.ucap.netcheck.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import com.thoughtworks.xstream.core.util.Base64Encoder;
import freemarker.template.Configuration;
import freemarker.template.Template;
/**
*@Title: FreeMarkerUtil.java
*@Package com.ucap.netcheck.utils
*@Description: FreeMarker工具类
*@authorZuoquan Tu
*@date 2015-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会报错,解决办法是将这个特殊字符用“&”替换掉,示例加链接的代码如下:
<#if (channelUpdate.url)??>
<w:hlink w:dest="${(channelUpdate.url)?replace('&','&')}">
<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('&','&')}</w:t>
</w:r>
</w:hlink>
</#if>
八、多次替换以及replace多次:
${(problemInfo.problemUrl)?replace("&","&")?replace("<","<")?replace(">",">")}
- 通过freemarker生成一个word,解决生成的word用wps打开有问题的问题,解决出word时中文文件名乱码问题,解决打开出word时打开的word出现问题的问题,出图片,解决动态列表
- 解决word安全模式打开的问题
- 解决word不能打开问题
- 解决jsp打开word文档乱码问题
- 如何解决 打开Word时产生 word无法启动转换器wps32 的问题
- 解决每次打开Word都要重新配置的问题
- 解决struts2下载word文件没法打开的问题
- freemarker导出word部分电脑出现中文乱码问题的解决
- 在weblogic下如何解决Word、Excel直接打开造成乱码的问题。
- 在weblogic下如何解决Word、Excel打开乱码问题
- 如何解决IE打开Word、Excel乱码问题
- 在weblogic下解决Word、Excel打开乱码问题
- 解决“每次打开office2010的word都会出现配置进度框”问题
- 解决office2007每次打开WORD文件出现宏问题
- 解决使用超链接下载word/EXCEL文件时被IE打开的问题
- 挑战性的问题,word打印不出文档(两家网络公司均未解决)
- 解决java poi生成word文件格式错误的问题。
- 解决此word打开时提示:文档有宏 该应用程序的宏语言支持功能被取消 问题
- 找不到Microsoft Access Driver(*.mdb)ODBC驱动程序的安装例程。请重新安装驱动
- Android学习笔记之资源(下)
- UI UIAlertView
- 第八周 项目1-实现复数类中的运算符重载(3)
- c++ 多态实现机制
- 通过freemarker生成一个word,解决生成的word用wps打开有问题的问题,解决出word时中文文件名乱码问题,解决打开出word时打开的word出现问题的问题,出图片,解决动态列表
- ActionBarActivity环境搭建步骤及遇到的问题总结
- webclient下载文件
- 黑马程序员——Java基础——数组操作应用
- string path = @"c:\temp\MyTest.txt";这里的@是什么意思
- 毫无弹性和粒度可言的编程模型
- How to permanently remove TFS Source Control association bindings?
- Java泛型详解
- 求最大连续bit数