java使用POI导出word数据以及生成word表格
暑期在杭州实习了两个月,主要是使用vue+SpringMVC进行一个网页开发。而在开发的过程中,也遇到了比较常见的文件导出问题–以固定格式将数据存储在word、excel等office文件格式中。在网上搜索了许多方法,了解到要导出word文件,其实办法由很多,如jacob,java2word,FreeMarker,Apatch POI等等。本文采用的是Apatch POI中的一系列API,它...
暑期在杭州实习了两个月,主要是使用vue+SpringMVC进行一个网页开发。
而在开发的过程中,也遇到了比较常见的文件导出问题–以固定格式将数据存储在word、excel等office文件格式中。
在网上搜索了许多方法,了解到要导出word文件,其实办法由很多,如jacob,java2word,FreeMarker,Apatch POI等等。
本文采用的是Apatch POI中的一系列API,它可以操作基于MicroSoft OLE 2 Compound Document Format的各种格式文件,可以通过这些API在Java中读写Excel、Word等文件。原则意义上来讲,POI更适合excel文件格式的导出,格式固定且代码简单。
而在使用POI操作word文档时,比较麻烦的一点是.doc文件和.docx文件是不同的,也就是说,需要使用不同的API来操作.doc文件和.docx文件。
一、.doc文件:使用HWPFDocument
1)模板文件
新建word模板文件,并在word文件中设置【标签】。
- 普通数据:一般标签以 ${变量名} 的格式命名,其中 $ 和 {} 一定是英文符号,如 ${project} , ${time}。注意标签名不要重复
- 表格文件:由于表格数据是由多组相同格式的数据组成,在计算机语言中,及由数组组成。其与普通数据不同,无需设置标签,只需要在word文件中新建空白表格,并设置表头即可,系统可以根据相应单元格的位置对表格数据进行设置。
模板文件编辑完成之后,记得将模板文件放在项目中。本项目放在了template文件夹中,当然,放在哪里,在代码中就要使用相应的路径来获取相应的模板文件。
2)文件导出
在第一步中已经使用 ${} 的格式对标签进行了设置,那么在代码中,我们只需要使用给相应的标签设置值即可。具体代码如下:
public boolean Export2GeotechnicalLayeringTable(Map<String, Object> map_data,ArrayList<Map<String, String>> list_data,String templatePath,OutputStream out) {
boolean result = false;
FileInputStream in = null;
HWPFDocument document = null;
try {
in = new FileInputStream(templatePath);
document = new HWPFDocument(in);
Range range = document.getRange();
range.replaceText("${project_id}", map_data.get("project_id").toString()); //
range.replaceText("${project_name}", map_data.get("project_name").toString()); //
range.replaceText("${depth}", map_data.get("depth").toString()); //
range.replaceText("${hole_id}", map_data.get("hole_id").toString()); //
range.replaceText("${hole_altitude}", map_data.get("hole_altitude").toString()); //
range.replaceText("${hole_mileage}", map_data.get("hole_mileage").toString()); //
range.replaceText("${endhole_depth}", map_data.get("endhole_depth").toString()); //
//写入表格数据
//遍历range范围内的table。
TableIterator tableIter = new TableIterator(range);
Table table;
TableRow row;
while (tableIter.hasNext()) {
table = tableIter.next();
int rowNum = table.numRows();
for (int i=0, j=2; i<list_data.size()&&j<rowNum; i++,j++) {
row = table.getRow(j);
row.getCell(0).insertBefore(list_data.get(i).get("layer_id"));
row.getCell(1).insertBefore(list_data.get(i).get("start_depth"));
row.getCell(2).insertBefore(list_data.get(i).get("end_depth"));
row.getCell(3).insertBefore(list_data.get(i).get("geotechnical_name"));
row.getCell(4).insertBefore(list_data.get(i).get("geotechnical_description"));
row.getCell(5).insertBefore(list_data.get(i).get("sample_id"));
row.getCell(6).insertBefore(list_data.get(i).get("sample_depth"));
}
}
document.write(out);
out.close();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
其中map_data中存储的是普通数据,而list_data中存储的是要生成word表格的数组数据。
由于代码都是较简单的java代码,这里不做解释。
代码封装好之后,进行单元测试:
public void testTestWord() throws FileNotFoundException {
WordUtils wordUtils = new WordUtils();
String templatePath = "D:\\Program Files\\eclipse\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp0\\wtpwebapps\\ZJICInformationManagement\\"+"template/钻孔岩土分层表模板.doc";
Map<String, Object> map_data = new HashMap<>();
map_data.put("project_id", "2019.21");
map_data.put("project_name", "ZJIC");
map_data.put("depth", "10.22");
map_data.put("hole_id", "ZKS12");
map_data.put("hole_altitude", "100");
map_data.put("hole_mileage", "23.21");
map_data.put("endhole_depth", "43");
ArrayList<Map<String, String>> list_data = new ArrayList<>();
Map<String, String> temp = new HashMap<>();
for(int i=0;i<10;i++){
temp = new HashMap<>();
temp.put("layer_id", i+"");
temp.put("start_depth", "start_depth");
temp.put("end_depth", "end_depth");
temp.put("geotechnical_name", "geotechnical_name");
temp.put("geotechnical_description", "geotechnical_description");
temp.put("sample_id", "sample_id");
temp.put("sample_depth", "sample_depth");
list_data.add(temp);
}
File file = new File("d:\\word\\test.doc");
FileOutputStream out = new FileOutputStream(file);
wordUtils.Export2GeotechnicalLayeringTable(map_data, list_data, templatePath, out);
}
最后生成的文件路径为:d:\word\test.doc。
二、.docx文件:使用XWPFDocument
遇到的巨大的坑!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
XWPFDocument比HWPFDocument灵活,但是在生成word文件过程中,对于普通的数据,前者与后者一样,同样通过设置标签来进行导出。但是操作标签的方式不同,XWPFDocument可以读取段落中的所有字符,然后通过XWPFRun(文本对象),使用正则表达式对文本中的标签进行提取,然后设置标签的值…但是在获取标签(正则表达式匹配)的过程中,总是出现中断。如${project},系统会将该标签分为两个字符串 ${ 和 project} ,导致无法与正则表达式匹配,系统判断该段文本并不是标签,导致判断错误。
暂时未找到该问题的解决办法。网上说是因为使用了中文的括号 {。需要将标签先使用文本编辑器–记事本等编辑之后,再复制粘贴到word文档中,本人亲测之后,问题未得到解决。
三、结果展示
更多推荐
所有评论(0)