前几天和大家分享了poi导出excel,设置自适应列宽,今天再跟大家分享poi模板导出excel。
模板导出,相比前几天用LinkedHashMap,excel样式和所需导出内容修改,只需修改模板即可,无需修改代码,可后期维护和可扩展性更强,可保存模板的样式(列宽,背景色,字号等)。
**poi excel模板导出操作思想:
1. 读取模板,获取表头中每列对应的属性(Map中的key值)。
2. 复制模板文件,重命名,遍历数据,将对应属性的值,填充到对应的列。
3. 删除模板文件,从响应流输出,生成下载。**
**excel模板要求:
- 只有一个sheet,命名与之后输出时的sheet不要重复。
- sheet中有两行数据,第一行即是输出excel的表头显示内容,包含自己所需格式。第二行为该列所对应的对象的属性。**
以下为excelExportUtil代码,仅供参考。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.eos.system.annotation.Bizlet;
import commonj.sdo.DataObject;
/**
* @author RangoLan
* @param fileName 生成的文件名前缀
* @param sheetName sheet名称前缀
* @param response 响应对象,获取响应输出流生成下载
* @param criteriaEntity 查询实体对象,用于检索获取Excel填充数据
* @param templatePath 倒出时选取的Excel文件路径和文件名 模板文件中必须只有一个sheet
* @param datePattern 日期数据格式化
* @throws Exception
*/
@Bizlet("数据写入Excel并生成下载")
public static void exportExcelByTemplate(String fileName,String sheetName,HttpServletResponse response,DataObject criteriaEntity,String templatePath,String datePattern) throws Exception {
//根据查询对象criteria填充数据源
DataObject[] datas = (DataObject[])com.eos.foundation.database.DatabaseUtil.queryEntitiesByCriteriaEntity("default", criteriaEntity);
if (datas != null && datas.length > 0) {
if(datePattern==null){
datePattern = "yyyy-MM-dd";
}
//读取导出模板文件
FileInputStream inputStream = new FileInputStream(templatePath);
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
inputStream.close();
//获得模板sheet
Sheet sheetTmp = workbook.getSheetAt(0);
//属性行,限定为第二行,rowIndex=1
Row propertyRow = sheetTmp.getRow(1);
//获取输出的列数
int columns = propertyRow.getLastCellNum();
//DataObject属性Property数组
String[] properties = new String[columns];
for (int i = 0; i < columns; i++) {
properties[i]=propertyRow.getCell(i).getStringCellValue();
}
/** 设置格式* */
// 单元格样式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
//垂直居中
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
//设置边框
cellStyle.setBorderTop(CellStyle.BORDER_THIN);
cellStyle.setBorderRight(CellStyle.BORDER_THIN);
cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
//设置自动换行
cellStyle.setWrapText(true);
//设置字体
Font cellFont = workbook.createFont();
cellFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
cellStyle.setFont(cellFont);
// 遍历集合数据,产生数据行,填充Excel
int rowIndex = 0;
Sheet sheet = null;
int sheetIndex=1;//sheet索引,从模板之后开始,所以为1
for (DataObject data : datas) {
if (rowIndex == 65535 || rowIndex == 0) {
//复制sheet
sheet = workbook.cloneSheet(0);// 如果数据超过了,则在第二页显示
//sheet命名
workbook.setSheetName(sheetIndex, sheetName+sheetIndex);
//删除第二行中的内容
sheet.removeRow(sheet.getRow(1));
rowIndex = 1;// 数据内容从 rowIndex=1开始
sheetIndex++;
}
//创建行
Row dataRow = sheet.createRow(rowIndex);
for (int i = 0; i < properties.length; i++) {
//创建单元格
Cell newCell = dataRow.createCell(i);
Object o = data.get(properties[i]);
String cellValue = "";
if (o == null) {//为空处理
cellValue = "";
} else if (o instanceof Date) {//日期格式化处理
cellValue = new SimpleDateFormat(datePattern).format(o);
} else {
cellValue = o.toString();
}
//单元格赋值
newCell.setCellValue(cellValue);
//单元格格式设置
newCell.setCellStyle(cellStyle);
}
rowIndex++;
}
OutputStream out = null;
try {
out = response.getOutputStream();
fileName = fileName
+ "_"
+ new SimpleDateFormat("yyyyMMDDhh24mmssSSS")
.format(System.currentTimeMillis()) + ".xlsx";
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition",
"attachment; filename="
+ URLEncoder.encode(fileName, "UTF-8"));
//删除模板
workbook.removeSheetAt(0);
// 保存报表文件
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null)
out.close();
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
以下是调用代码(由于项目架构,是在jsp中调用的。):
try{
DataObject criteria = (DataObject)request.getAttribute("criteria");
//输出文件名前缀
String fileName="PRODUCT";
//sheet名前缀
String sheetName="产品明细表";
//日期格式
String datePattern = "yyyy-MM-dd";
//获取项目在服务器目录中的路径
String realPath=request.getSession().getServletContext().getRealPath("/");
//模板相对路径+文件名
String template="abframe\\excel-config\\productDetailTemplate.xlsx";
String templatePath=realPath+template;
ExcelExportUtil.exportExcelByTemplate(fileName,sheetName,response,criteria,templatePath,datePattern);
} finally {
out.clear();
out = pageContext.pushBody();
}
另外,在完成本项目时,excel的数据时条件查询的,所以根据条件检索后不一定有数据,所以为了用户体验(系统友好),在导出之前先调用Ajax检验是否有数据,有数据调用下载,无数据即可弹出提示。