POI导出到模板
需求
最近连续两个需求都是:导出的Excel能直接再导入到系统中,而导入功能依赖于导入模板,今天写了一个通用的方法,可以先读取系统本地的导入模板,再写入数据生成一个文件供用户下载。
首先添加一条导入导出任务,保存导出生成的文件的服务器地址和该任务的其它信息,在文件生成完成后,将该任务记录设置为已完成,用户根据该任务记录的文件信息下载即可,这样可以优化文件生成过慢的弊端
思路
导入模板的第一行作为数据标识,可以通过反射来到对应的位置填写数据。不同的sheet页写入的数据可能不一样,所以考虑用Map作为数据容器,
Map<Integer, List> map
其中Integer不仅作为key,而且直接就能用来表示这个list需要填入的sheet[index]
代码
下面用的是POI的XSSFWorkbook用来读取生成xlsx文件。
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.0</version>
</dependency>
package com.demo.utils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class ExportExcelUseTemplate<T> implements Serializable {
private String tempPath;
private String tempName;
private String fileName;
private String filePath;
private Map<Integer, List<T>> map;
private XSSFWorkbook wb;
private ExportExcelUseTemplate(){}
public ExportExcelUseTemplate(String tempPath,String tempName,
String filePath,String fileName,Map<Integer,List<T>> map){
this.tempPath = tempPath;
this.tempName = tempName;
this.filePath = filePath;
this.fileName = fileName;
this.map = map;
}
protected void export(){
readTemplate();
writeData();
createFile();
}
protected void readTemplate(){
try{
FileInputStream fileInputStream = new FileInputStream(this.tempPath+this.tempName);
this.wb = new XSSFWorkbook(fileInputStream);
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
protected void writeData(){
for(Integer index:map.keySet()){
if(map.get(index).isEmpty()){
continue;
}
XSSFSheet sheet = wb.getSheetAt(index-1);//第index-1个sheet
XSSFRow row = sheet.getRow(0);
List<T> list = map.get(index);
sheet.shiftRows(3,3+list.size(),list.size());//从第三行开始,结束与size+3,动态添加size行
for(int i =0 ;i< list.size();i++){//遍历数据
XSSFRow createRow = sheet.createRow(3+i);
for(int j=0;j<row.getLastCellNum();j++){//遍历key再通过反射写入数据(导入模板的第一行作为数据标识)
try {
String key = row.getCell(j).getStringCellValue();
String value = getMethod(list.get(i),key);//根据key找到对象中对应的值
createRow.createCell(j).setCellValue(value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
private void createFile(){
try{
File dir = new File(this.filePath);
if(!dir.exists()){
dir.mkdir();
}
FileOutputStream fileOutputStream = new FileOutputStream(this.filePath+this.fileName);
this.wb.write(fileOutputStream);
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private String getMethod(T t, String key) throws Exception{
Class<?> clazz = t.getClass();
PropertyDescriptor pd = new PropertyDescriptor(key,clazz);
Method getMethod = pd.getReadMethod();
Object o = getMethod.invoke(t);
if(o instanceof Date){
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
return o==null? "" : sd.format(o);
}
return o==null? "":o.toString();
}
}