java如何根据word模板生成word文档

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java如何根据word模板生成word文档相关的知识,希望对你有一定的参考价值。

小弟今年大四了,准备做毕业设计,选的课题是“试卷自动生成系统”,要求能自动生成并导出一个word文档,版式要和平时考试试卷一样。我查了几天的资料,得到的结果是:
1、新建一个word模板,另存为 *.xml 文件
2、用java解析xml文件
3、替换内容
4、生成word文档
这种方式用来做荣誉证书之类的话就没什么问题,只要在指定位置替换姓名、性别等就行了。可是试卷没有固定的题目个数、题目类型,有的可能还有图片……
请大虾们指点一下啊!小弟感激不敬!!
使用jsp开发…………

首先是action的createDoc方法:
[java]
/**
* 通过HttpCient调用报告服务器的方法生成报告 DOC
*/
public String createDoc() throws Exception
//定义放回成功与否的判断码
String prMsg="";
// 获取当前登录的用户
UserVo userVo = CommonUtils.getUserMessage();
//获取模版类型
docType = Struts2Utils.getParameter("docType");
//重新创建文档
String creatOrnot = Struts2Utils.getParameter("creatOrnot");
//获取组组编号参数
workgroupId = Struts2Utils.getParameter("workgroupId");
//获取评估用例实例ID参数
evtcaseInstId = Struts2Utils.getParameter("evtcaseInstId");
if(CommonUtils.isNotNull(docType))
//获取项目Id
projectId = Struts2Utils.getParameter("projectId");
if(!CommonUtils.isNotNull(projectId))
if(CommonUtils.isNotNull(this.getIdFromSession("PM_PROJECTID")))
projectId = this.getIdFromSession("PM_PROJECTID").toString();
else
Struts2Utils.getRequest().setAttribute("msg", "请先选择项目!");


if(CommonUtils.isNotNull(projectId))
prMsg = infoSystemDescService.downloadFileByUrl(projectId, userVo.getUserId(), workgroupId, evtcaseInstId, docType, creatOrnot);


return "docList";

注:在我贴出来的代码中,能看懂就行了,有些不用管他(可能是其他业务方面的判断),关于最后返回的prMsg---代表各种状态 主要表示成功与否或者是出错的信息。

接着我贴出service层的方法downloadFileByUrl

[java]
</pre><p></p><p></p><pre name="code" class="java"><pre name="code" class="java">/**
* 功能:
* 1.(生成报告文档)
* 2.保存指定URL的源文件到指定路径下
* @param projectId
* @param userId
* @param workgroupId
* @param evtcaseInstId
* @param docType
* @param creatOrnot
* @return
* @throws Exception
*/
@SuppressWarnings("deprecation")
public synchronized String downloadFileByUrl(String projectId,String userId,String workgroupId,String evtcaseInstId,String docType,String creatOrnot) throws Exception
String msg = "1";//"1":默认为创建成功的提示信息 "2":标识创建失败
String srcUrl = ""; //报告服务器的执行路径
HttpResponse response = null;
FileOutputStream out = null;
HttpClient httpclient = null;
HttpGet httpget = null;
long time1 = System.currentTimeMillis();
//获取保存后的路径
TProjDoc projDoc = projectDocDao.findFileByType(userId, Integer.parseInt(docType), Long.parseLong(projectId), workgroupId,evtcaseInstId);
if(projDoc == null || (projDoc != null && CommonUtils.isNotNull(creatOrnot) && creatOrnot.equals("1"))) //FT_任务编号_[FID]
try
//获取报告服务器的执行路径
srcUrl = xmlPathDef.getActionUrl(docType, projectId,userId,workgroupId,evtcaseInstId);

HttpParams httpParams = new BasicHttpParams();
// 设置最大连接数
ConnManagerParams.setMaxTotalConnections(httpParams, 1);
// 设置获取连接的最大等待时间
//ConnManagerParams.setTimeout(httpParams, 6000);
// 设置每个路由最大连接数
ConnPerRouteBean connPerRoute = new ConnPerRouteBean(1);
ConnManagerParams.setMaxConnectionsPerRoute(httpParams,connPerRoute);
// 设置连接超时时间
HttpConnectionParams.setConnectionTimeout(httpParams, 6000);
// 设置读取超时时间
if(docType.toString().equals(XmlPathDef.SPOTTEST_DOC) && docType.toString().equals(XmlPathDef.FTEST_DOC))
HttpConnectionParams.setSoTimeout(httpParams, 2400000);
else
HttpConnectionParams.setSoTimeout(httpParams, 600000);


SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(httpParams, registry);

httpclient = new DefaultHttpClient(connectionManager, httpParams);

httpget = new HttpGet(srcUrl);
//执行返回
response = httpclient.execute(httpget);
//如果是本机既当服务器,又当报表服务器,那么就只生成一遍
String ipvalues = xmlPathDef.getRepUrl();
if(CommonUtils.isNotNull(ipvalues))
if(ipvalues.indexOf(":") != -1)
ipvalues = ipvalues.substring(0,ipvalues.lastIndexOf(":"));


HttpEntity entity = response.getEntity();
//获取保存后的路径
projDoc = projectDocDao.findFileByType(userId,Integer.parseInt(docType), Long.parseLong(projectId), workgroupId,evtcaseInstId);
String filePath = "";
if(projDoc != null)
filePath = projDoc.getPath();
if(CommonUtils.isNotNull(filePath))
String basepath = XmlPathDef.getBasePath();
String outFilePath = (basepath + filePath).replaceAll("\\\\\\\\", "\\\\/");
XmlPathDef.isExists(outFilePath);
File wdFile = new File(outFilePath);
out = new FileOutputStream(wdFile);
int l;
byte[] tmp = new byte[2048];
while ((l = instream.read(tmp)) != -1)
out.write(tmp, 0, l);

out.flush();
out.close();
System.out.println("****************************** ");
System.out.println("");
System.out.println("*************** 恭喜! 报告创建成功 结束 ***************");
System.out.println("");
else
msg = "8";//说明word创建成功,但是数据没有保存成功
response = null;

else
msg = "2";

catch (ClientProtocolException e)
msg = "7";
e.printStackTrace();
catch (IOException e)
msg = "7";
logger.error("数据库报告服务器地址配置错误或网络不通!!2.连接是否超时" + e.getMessage());
e.printStackTrace();
finally
if(out!=null)
try
out.close();
catch (IOException e)
msg = "7";
logger.error("数据库报告服务器地址配置错误或网络不通!!2.连接是否超时" + e.getMessage());
e.printStackTrace();





long time2 = System.currentTimeMillis();
long numTime = time2 - time1;
if(docType.toString().equals(XmlPathDef.SPOTTEST_DOC) && docType.toString().equals(XmlPathDef.FTEST_DOC))
if(numTime >= 2401000)
msg = "9";


else
if(numTime >= 601000)
msg = "9";


System.out.println("");
String loggerinfo = "********* 报告类型为 :" + docType + " 执行时间为: " + (time2 - time1) /1000 + " 秒!***************";
System.out.println(loggerinfo);
System.out.println("");
System.out.println("*****************************");
logger.info(loggerinfo);
return msg;
参考技术A 先下载jacob_1.10.1.zip。
解压后将jacob.dll放到windows/system32下面或\j2sdk\bin下面。
将jacob.jar加入项目。

/*
* Java2word.java
*
* Created on 2007年8月13日, 上午10:32
*
* To
change this template, choose Tools | Template Manager
* and open the template
in the editor.
*/

/*
* 传入数据为HashMap对象,对象中的Key代表word模板中要替换的字段,Value代表用来替换的值。
*
word模板中所有要替换的字段(即HashMap中的Key)以特殊字符开头和结尾,如:$code$、$date$……,
以免执行错误的替换。
*
所有要替换为图片的字段,Key中需包含image或者Value为图片的全路径(目前只判断文件后缀名为:.bmp、
.jpg、.gif)。
*
要替换表格中的数据时,HashMap中的Key格式为“table$R@N”,其中:R代表从表格的第R行开始替换,N代表
word模板中的第N张表格;Value为ArrayList对象,ArrayList中包含的对象统一为String[],一条String[]代
表一行数据,ArrayList中第一条记录为特殊记录,记录的是表格中要替换的列号,如:要替换第一列、第三列、
第五列的数据,则第一条记录为String[3]
“1”,”3”,”5”。
*/

package com.word.util;

/**
*
* @author kdl
*/
import java.util.ArrayList;
import
java.util.HashMap;
import java.util.Iterator;

import com.jacob.activeX.ActiveXComponent;
import
com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class Java2word

private boolean saveOnExit;

/**
* word文档
*/
Dispatch doc = null;

/**
* word运行程序对象s
*/
private ActiveXComponent
word;
/**
* 所有word文档
*/
private Dispatch
documents;

/**
* 构造函数
*/

public Java2word()
if(word==null)
word = new
ActiveXComponent("Word.Application");
word.setProperty("Visible",new
Variant(false));

if(documents==null)

documents = word.getProperty("Documents").toDispatch();
saveOnExit =
false;


/**
* 设置参数:退出时是否保存
* @param
saveOnExit boolean true-退出时保存文件,false-退出时不保存文件
*/
public void
setSaveOnExit(boolean saveOnExit)
this.saveOnExit =
saveOnExit;

/**
* 得到参数:退出时是否保存
* @return
boolean true-退出时保存文件,false-退出时不保存文件
*/
public boolean
getSaveOnExit()
return saveOnExit;


/**
* 打开文件
* @param inputDoc String 要打开的文件,全路径
*
@return Dispatch 打开的文件
*/
public Dispatch open(String inputDoc)

return
Dispatch.call(documents,"Open",inputDoc).toDispatch();
//return
Dispatch.invoke(documents,"Open",Dispatch.Method,new Object[]inputDoc,new
int[1]).toDispatch();


/**
* 选定内容
*
@return Dispatch 选定的范围或插入点
*/
public Dispatch select()

return word.getProperty("Selection").toDispatch();



/**
* 把选定内容或插入点向上移动
* @param selection
Dispatch 要移动的内容
* @param count int 移动的距离
*/
public
void moveUp(Dispatch selection,int count)
for(int i = 0;i <
count;i ++)
Dispatch.call(selection,"MoveUp");



/**
* 把选定内容或插入点向下移动
* @param selection
Dispatch 要移动的内容
* @param count int 移动的距离
*/
public
void moveDown(Dispatch selection,int count)
for(int i = 0;i <
count;i ++)
Dispatch.call(selection,"MoveDown");



/**
* 把选定内容或插入点向左移动
* @param selection
Dispatch 要移动的内容
* @param count int 移动的距离
*/
public
void moveLeft(Dispatch selection,int count)
for(int i = 0;i <
count;i ++)
Dispatch.call(selection,"MoveLeft");




/**
* 把选定内容或插入点向右移动
* @param
selection Dispatch 要移动的内容
* @param count int 移动的距离
*/

public void moveRight(Dispatch selection,int count)
for(int i =
0;i < count;i ++)

Dispatch.call(selection,"MoveRight");


/**
*
把插入点移动到文件首位置
* @param selection Dispatch 插入点
*/
public
void moveStart(Dispatch selection)

Dispatch.call(selection,"HomeKey",new Variant(6));


/**
* 从选定内容或插入点开始查找文本
* @param selection Dispatch
选定内容
* @param toFindText String 要查找的文本
* @return boolean
true-查找到并选中该文本,false-未查找到文本
*/
public boolean find(Dispatch
selection,String toFindText)
//从selection所在位置开始查询

Dispatch find = word.call(selection,"Find").toDispatch();

//设置要查找的内容
Dispatch.put(find,"Text",toFindText);

//向前查找
Dispatch.put(find,"Forward","True");

//设置格式
Dispatch.put(find,"Format","True");

//大小写匹配
Dispatch.put(find,"MatchCase","True");

//全字匹配
Dispatch.put(find,"MatchWholeWord","True");

//查找并选中
return Dispatch.call(find,"Execute").getBoolean();



/**
* 把选定内容替换为设定文本
* @param selection
Dispatch 选定内容
* @param newText String 替换为文本
*/
public
void replace(Dispatch selection,String newText)

//设置替换文本
Dispatch.put(selection,"Text",newText);



/**
* 全局替换
* @param selection Dispatch
选定内容或起始插入点
* @param oldText String 要替换的文本
* @param newText
String 替换为文本
*/
public void replaceAll(Dispatch
selection,String oldText,Object replaceObj)
//移动到文件开头

moveStart(selection);

if(oldText.startsWith("table") ||
replaceObj instanceof ArrayList)

replaceTable(selection,oldText,(ArrayList) replaceObj);
else

String newText = (String) replaceObj;

if(newText==null)
newText="";

if(oldText.indexOf("image") != -1&!newText.trim().equals("") ||
newText.lastIndexOf(".bmp") != -1 || newText.lastIndexOf(".jpg") != -1 ||
newText.lastIndexOf(".gif") != -1)

while(find(selection,oldText))

replaceImage(selection,newText);

Dispatch.call(selection,"MoveRight");


else
while(find(selection,oldText))

replace(selection,newText);

Dispatch.call(selection,"MoveRight");






/**
* 替换图片
* @param
selection Dispatch 图片的插入点
* @param imagePath String 图片文件(全路径)

*/
public void replaceImage(Dispatch selection,String imagePath)


Dispatch.call(Dispatch.get(selection,"InLineShapes").toDispatch(),"AddPicture",imagePath);



/**
* 替换表格
* @param selection Dispatch
插入点
* @param tableName String
表格名称,形如table$1@1、table$2@1...table$R@N,R代表从表格中的第N行开始填充,N代表word文件中的第N张表

* @param fields HashMap 表格中要替换的字段与数据的对应表
*/
public void
replaceTable(Dispatch selection,String tableName,ArrayList dataList)

if(dataList.size() <= 1)

System.out.println("Empty table!");
return;



//要填充的列
String[] cols = (String[])
dataList.get(0);

//表格序号
String tbIndex =
tableName.substring(tableName.lastIndexOf("@") + 1);

//从第几行开始填充
int fromRow =
Integer.parseInt(tableName.substring(tableName.lastIndexOf("$") +
1,tableName.lastIndexOf("@")));
//所有表格
Dispatch tables =
Dispatch.get(doc,"Tables").toDispatch();
//要填充的表格

Dispatch table = Dispatch.call(tables,"Item",new
Variant(tbIndex)).toDispatch();
//表格的所有行
Dispatch rows =
Dispatch.get(table,"Rows").toDispatch();
//填充表格
for(int
i = 1;i < dataList.size();i ++)
//某一行数据

String[] datas = (String[]) dataList.get(i);

//在表格中添加一行
if(Dispatch.get(rows,"Count").getInt() < fromRow +
i - 1)
Dispatch.call(rows,"Add");

//填充该行的相关列
for(int j = 0;j < datas.length;j ++)

//得到单元格
Dispatch cell =
Dispatch.call(table,"Cell",Integer.toString(fromRow + i -
1),cols[j]).toDispatch();
//选中单元格

Dispatch.call(cell,"Select");
//设置格式

Dispatch font = Dispatch.get(selection,"Font").toDispatch();

Dispatch.put(font,"Bold","0");

Dispatch.put(font,"Italic","0");
//输入数据

Dispatch.put(selection,"Text",datas[j]);





/**
* 保存文件
* @param outputPath String
输出文件(包含路径)
*/
public void save(String outputPath)

Dispatch.call(Dispatch.call(word,"WordBasic").getDispatch(),"FileSaveAs",outputPath);



/**
* 关闭文件
* @param document Dispatch
要关闭的文件
*/
public void close(Dispatch doc)

Dispatch.call(doc,"Close",new Variant(saveOnExit));

word.invoke("Quit",new Variant[]);
word = null;



/**
* 根据模板、数据生成word文件
* @param inputPath
String 模板文件(包含路径)
* @param outPath String 输出文件(包含路径)
* @param
data HashMap 数据包(包含要填充的字段、对应的数据)
*/
public void toWord(String
inputPath,String outPath,HashMap data)
String oldText;

Object newValue;
try
if(doc==null)

doc = open(inputPath);

Dispatch selection =
select();

Iterator keys =
data.keySet().iterator();
while(keys.hasNext())

oldText = (String) keys.next();

newValue = data.get(oldText);

replaceAll(selection,oldText,newValue);



save(outPath);
catch(Exception
e)
System.out.println("操作word文件失败!");

e.printStackTrace();
finally
if(doc !=
null)
close(doc);

参考技术B 可以使用jacob,一个java到com桥的开源项目工具,目前该项目还在活跃追问

jacob虽然对word有很好的支持,但只能用在windows平台下。

追答

是的,只能用在windows下,对word比较好的支持也仅限于windows下的工具。没办法

参考技术C 百度或者谷歌查啊,资源丰富啊!!!本回答被提问者采纳

以上是关于java如何根据word模板生成word文档的主要内容,如果未能解决你的问题,请参考以下文章

java中如何生成word文档的目录页

java poi-tl 根据模板生成word合并多个word文档

使用freemarker生成的word文档,如何利用java代码将其转换为pdf格式?

java动态生成word,该怎么解决

java生成word文档的问题

poi-tl——Word模板生成器