java使用POI导出word数据以及生成word表格

暑期在杭州实习了两个月,主要是使用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文件中新建空白表格,并设置表头即可,系统可以根据相应单元格的位置对表格数据进行设置。
    java使用POI导出word数据以及生成word表格_第1张图片
    模板文件编辑完成之后,记得将模板文件放在项目中。本项目放在了template文件夹中,当然,放在哪里,在代码中就要使用相应的路径来获取相应的模板文件。
    java使用POI导出word数据以及生成word表格_第2张图片

2)文件导出

在第一步中已经使用 ${} 的格式对标签进行了设置,那么在代码中,我们只需要使用给相应的标签设置值即可。具体代码如下:

public boolean Export2GeotechnicalLayeringTable(Map map_data,ArrayList> 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

其中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 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> list_data = new ArrayList<>();
		Map 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文档中,本人亲测之后,问题未得到解决。

三、结果展示

java使用POI导出word数据以及生成word表格_第3张图片

你可能感兴趣的:(word)