excle因为是单元格为单位,所以操作十分简便,相对于它来说,word操作相对复杂一些,word操作主要用来做文本内容的替换来实现动态生成word,下面把我对这一块的思想,以及操作进行一下总结。
0.和excle一样有一个老版本的文件格式为doc格式,对应对象名称为HWPFDocument,最新的docx格式对应的对象为XWPFDocument,这里以后者为例。因为在工作中处理表格,一般抬头为一行描述,如标题年月日名称等,然后下面是表格内容填充这种形式,所以以下操作就以这种文件内容作为处理对象举例。
1.XWPFDocument docx = new XWPFDocument(inputstream);// word主要就通过传入文件流的方式进行实例化。
2.List<XWPFParagraph> allXWPFParagraphs = docx.getParagraphs(); 拿到文本段落 一行数据为一个XWPFParagraph对象。
遍历上面的allXWPFParagraphs -> for (XWPFParagraph xwpfParagraph : paragraphs)
通过List<XWPFRun> run = xwpfParagraph.getRuns();拿到段落中的文本 以符号或者不同数据类型终结,就像是一句话会以句号结束。
遍历上面 话语集合 -> for (int i = 0; i < run.size(); i++)
run.get(i).setText(要设置的值, 从哪个位置开始) ,替换掉某句话
3. 因为在网上找了很多例子不太好用,所以在工作中自行写了一个文本转换的工具类,以方便使用。代码如下:
/**
* 导出word(新)
* @param tempMap 名字替换
* @param tempFilePath 读取文件路径
* @param response 响应
* @param fileName 下载文件名
* @throws Exception
*/
public void docxFileExport(Map<String, String> tempMap, String tempFilePath,
HttpServletResponse response, String fileName) throws Exception {
XWPFDocument docx = new XWPFDocument(new FileInputStream(tempFilePath));
List<XWPFParagraph> paragraphs = docx.getParagraphs();
for (XWPFParagraph xwpfParagraph : paragraphs) {
List<XWPFRun> run = xwpfParagraph.getRuns();
for (int i = 0; i < run.size(); i++) {
for (Map.Entry<String, String> entry : tempMap.entrySet()) {
String val = run.get(i).getText(run.get(i).getTextPosition());
if (val != null && val.equals(entry.getKey())) {
run.get(i).setText(entry.getValue(), 0);
}
}
}
}
// 美滋滋循环
List<XWPFTable> tables = docx.getTables();
for (XWPFTable table : tables) {
List<XWPFTableRow> rows = table.getRows();
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
List<XWPFParagraph> cellPara = cell.getParagraphs();
for (XWPFParagraph xwpfParagraph : cellPara) {
List<XWPFRun> run = xwpfParagraph.getRuns();
for (int i = 0; i < run.size(); i++) {
for (Map.Entry<String, String> entry : tempMap.entrySet()) {
String val = run.get(i).getText(run.get(i).getTextPosition());
if (val != null && val.equals(entry.getKey())) {
run.get(i).setText(entry.getValue(), 0);
}
}
}
}
}
}
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
docx.write(os);
byte[] content = os.toByteArray();
InputStream is = new ByteArrayInputStream(content);
response.reset();
response.setContentType("application/x-download;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename="
+ new String((fileName+ System.currentTimeMillis() + ".docx").getBytes(), "iso-8859-1"));
response.setHeader("Set-Cookie", "fileDownload=true; path=/");
ServletOutputStream out = response.getOutputStream();
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(out);
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null)
bis.close();
if (bos != null)
bos.close();
}
}
4.该代码简单讲解,以便日后复用
需要自己先设定好word模板,然后将需要添字部分设置为任意的英文组合例如 nmy。然后设置要替换的map,key为要替换的关键字,value为要替换成的内容,该方法最后会弹出下载, response.setHeader("Set-Cookie", "fileDownload=true; path=/");防止多次点击下载,通过内存流最后弹出下载。为了防止乱码设置new String((fileName+ System.currentTimeMillis() + ".docx").getBytes(), "iso-8859-1")) 然后好像也没啥了吧。。。