一、導入依賴
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
二、編寫工具類
package cn.pms.util;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 導出Excel
* @author Guang
*
*/
public class ExportExcelUtils {
private static final Logger logger =LoggerFactory.getLogger(ExportExcelUtils.class);
/**
* 導出Excel
* @param excelName 要導出的excel名稱
* @param list 要導出的資料集合
* @param fieldMap 中英文字段對應Map,即要導出的excel表頭
* @param response 使用response可以導出到浏覽器
* @return
*/
public static <T> void export(String excelName,List<T> list,LinkedHashMap<String, String> fieldMap,HttpServletResponse response){
// 設定預設檔案名為目前時間:年月日時分秒
if (excelName==null || excelName=="") {
excelName = new SimpleDateFormat("yyyyMMddhhmmss").format(
new Date()).toString();
}
// 設定response頭資訊
response.reset();
response.setContentType("application/vnd.ms-excel"); // 改成輸出excel檔案
try {
response.setHeader("Content-disposition", "attachment; filename="
+new String(excelName.getBytes("gb2312"), "ISO-8859-1") + ".xls");
} catch (UnsupportedEncodingException e1) {
logger.info(e1.getMessage());
}
try {
//建立一個WorkBook,對應一個Excel檔案
HSSFWorkbook wb=new HSSFWorkbook();
//在Workbook中,建立一個sheet,對應Excel中的工作薄(sheet)
HSSFSheet sheet=wb.createSheet(excelName);
//建立單元格,并設定值表頭 設定表頭居中
HSSFCellStyle style=wb.createCellStyle();
//建立一個居中格式
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 填充工作表
fillSheet(sheet,list,fieldMap,style);
//将檔案輸出
OutputStream ouputStream = response.getOutputStream();
wb.write(ouputStream);
ouputStream.flush();
ouputStream.close();
} catch (Exception e) {
logger.info("導出Excel失敗!");
logger.error(e.getMessage());
}
}
/**
* 根據字段名擷取字段對象
*
* @param fieldName
* 字段名
* @param clazz
* 包含該字段的類
* @return 字段
*/
public static Field getFieldByName(String fieldName, Class<?> clazz) {
logger.info("根據字段名擷取字段對象:getFieldByName()");
// 拿到本類的所有字段
Field[] selfFields = clazz.getDeclaredFields();
// 如果本類中存在該字段,則傳回
for (Field field : selfFields) {
//如果本類中存在該字段,則傳回
if (field.getName().equals(fieldName)) {
return field;
}
}
// 否則,檢視父類中是否存在此字段,如果有則傳回
Class<?> superClazz = clazz.getSuperclass();
if (superClazz != null && superClazz != Object.class) {
//遞歸
return getFieldByName(fieldName, superClazz);
}
// 如果本類和父類都沒有,則傳回空
return null;
}
/**
* 根據字段名擷取字段值
*
* @param fieldName 字段名
* @param o 對象
* @return 字段值
* @throws Exception 異常
*
*/
public static Object getFieldValueByName(String fieldName, Object o)
throws Exception {
logger.info("根據字段名擷取字段值:getFieldValueByName()");
Object value = null;
//根據字段名得到字段對象
Field field = getFieldByName(fieldName, o.getClass());
//如果該字段存在,則取出該字段的值
if (field != null) {
field.setAccessible(true);//類中的成員變量為private,在類外邊使用屬性值,故必須進行此操作
value = field.get(o);//擷取目前對象中目前Field的value
} else {
throw new Exception(o.getClass().getSimpleName() + "類不存在字段名 "
+ fieldName);
}
return value;
}
/**
* 根據帶路徑或不帶路徑的屬性名擷取屬性值,即接受簡單屬性名,
* 如userName等,又接受帶路徑的屬性名,如student.department.name等
*
* @param fieldNameSequence 帶路徑的屬性名或簡單屬性名
* @param o 對象
* @return 屬性值
* @throws Exception 異常
*
*/
public static Object getFieldValueByNameSequence(String fieldNameSequence,
Object o) throws Exception {
logger.info("根據帶路徑或不帶路徑的屬性名擷取屬性值,即接受簡單屬性名:getFieldValueByNameSequence()");
Object value = null;
// 将fieldNameSequence進行拆分
String[] attributes = fieldNameSequence.split("\\.");
if (attributes.length == 1) {
value = getFieldValueByName(fieldNameSequence, o);
} else {
// 根據數組中第一個連接配接屬性名擷取連接配接屬性對象,如student.department.name
Object fieldObj = getFieldValueByName(attributes[0], o);
//截取除第一個屬性名之後的路徑
String subFieldNameSequence = fieldNameSequence
.substring(fieldNameSequence.indexOf(".") + 1);
//遞歸得到最終的屬性對象的值
value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
}
return value;
}
/**
* 向工作表中填充資料
*
* @param sheet
* excel的工作表名稱
* @param list
* 資料源
* @param fieldMap
* 中英文字段對應關系的Map
* @param style
* 表格中的格式
* @throws Exception
* 異常
*
*/
public static <T> void fillSheet(HSSFSheet sheet, List<T> list,
LinkedHashMap<String, String> fieldMap,HSSFCellStyle style) throws Exception {
logger.info("向工作表中填充資料:fillSheet()");
// 定義存放英文字段名和中文字段名的數組
String[] enFields = new String[fieldMap.size()];
String[] cnFields = new String[fieldMap.size()];
// 填充數組
int count = 0;
for (Entry<String, String> entry : fieldMap.entrySet()) {
enFields[count] = entry.getKey();
cnFields[count] = entry.getValue();
count++;
}
//在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
HSSFRow row=sheet.createRow((int)0);
// 填充表頭
for (int i = 0; i < cnFields.length; i++) {
HSSFCell cell=row.createCell(i);
cell.setCellValue(cnFields[i]);
cell.setCellStyle(style);
sheet.autoSizeColumn(i);
}
// 填充内容
for (int index = 0; index < list.size(); index++) {
row = sheet.createRow(index + 1);
// 擷取單個對象
T item = list.get(index);
for (int i = 0; i < enFields.length; i++) {
Object objValue = getFieldValueByNameSequence(enFields[i], item);
String fieldValue = objValue == null ? "" : objValue.toString();
row.createCell(i).setCellValue(fieldValue);
}
}
}
}
三、編寫Controller
package cn.pms.controller;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSON;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import cn.pms.model.User;
import cn.pms.service.UserService;
import cn.pms.util.ExcelImportUtil;
import cn.pms.util.ExportExcelUtils;
/**
* 使用者Controller
*
* @author eluzhu
*
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/excel/exportBankCheckInfo", method = RequestMethod.GET)
public void ExportBankCheckInfo(HttpServletRequest request, HttpServletResponse response) {
//得到所要導出的資料
List<User> errLst = userService.selectAllUser();
//定義導出excel的名字
String excelName="使用者表";
// 擷取需要轉出的excle表頭的map字段
LinkedHashMap<String, String> fieldMap =new LinkedHashMap<String, String>() ;
fieldMap.put("userNo", "編号");
fieldMap.put("userName", "姓名");
fieldMap.put("password", "密碼");
//導出使用者相關資訊
new ExportExcelUtils().export(excelName, errLst, fieldMap, response);
}
}
四、浏覽器輸入對應的URL進行測試(成功的辨別如下)
控制台列印和浏覽器顯示
