聲明:
研究了好幾天,一開始使用工具類在本地可以導出,部署到服務器上就沒有文件,真是醉了.我把過程寫出來,希望可以讓小夥伴們增加個思路.
依賴:
導入導出都可以用,如果嫌少的話,可以去別的小夥伴文章多沾點哈哈
同一的版本
<poi.version>3.15</poi.version>
<!-- POI依賴 ,處理EXCEL WORD PDF-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
<exclusions>
<exclusion>
<artifactId>stax-api</artifactId>
<groupId>stax</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
<exclusions>
<exclusion>
<artifactId>stax-api</artifactId>
<groupId>stax</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- POI依賴 ,處理EXCEL WORD PDF-->
工具類:
我把整個工具類的代碼都放在裏面了,別閒多,粘貼過去你就能用,我保你的哈哈,實在用不了那也沒轍了哈哈
package com.platform.utils.excel;
import com.platform.utils.RRException;
import com.platform.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.*;
/**
* 導出EXCEL功能包主類
* 使用POI進行EXCEL導出的功能類。
* 目前簡單處理,未設置內存優化。 數據量偏大,出現性能問題時再處理。
*
* @author lipengjun
* @email [email protected]
* @date 2017年10月28日 13:11:27
*/
public class ExcelExport {
/**
* EXCEL 2003 擴展名
*/
public static final String EXCEL03_EXTENSION = ".xls";
/**
* EXCEL 2007 擴展名
*/
public static final String EXCEL07_EXTENSION = ".xls";
/**
* 工作表
*/
private Workbook workBook;
/**
* 導出文件名
*/
private String exportFileName;
/**
* 日誌
*/
private Log logger = LogFactory.getLog(ExcelExport.class);
/**
* 默認構造方法。
* 自動生成工作表。
*/
public ExcelExport() {
this("workbook.xlsx");
}
/**
* 指定導出文件名的構造方法
* 指定導出文件名。 同時根據指定文件名的擴展名確定導出格式是03或是07 。
* 不帶擴展名默認爲07格式。(POI 07格式支持內存優化)
*
* @param exportFileName 要導出的文件名(帶擴展名。不帶擴展名默認爲07)
*/
public ExcelExport(String exportFileName) {
if (StringUtils.isNullOrEmpty(exportFileName)) {
exportFileName = "workbook.xlsx";
}
String fileName = exportFileName.toLowerCase();
// 根據文件名擴展名生成EXCEL格式。
if (fileName.endsWith(ExcelExport.EXCEL03_EXTENSION)) {
workBook = new HSSFWorkbook();
} else if (exportFileName.endsWith(ExcelExport.EXCEL07_EXTENSION)) {
workBook = new XSSFWorkbook();
} else {
workBook = new XSSFWorkbook();
fileName += ".xlsx";
// 按正則替換? 處理文件名最後一個字符爲“.” 的問題
// fileName = fileName.replaceAll("..", ".");
}
// 最後按小寫文件名輸出
this.exportFileName = fileName;
}
/**
* 主要功能: 導出EXCEL到response
* 注意事項:無
*
* @param response HttpServletResponse
*/
public void export(HttpServletResponse response) {
// response.setHeader("Content-Disposition","attachment;filename=totalExcel.xls");
response.reset();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
// response.setContentType("text/html;charset=UTF-8");
// response.setContentType("APPLICATION/*");
String fileName = null;
// 處理編碼
try {
//modify by ld 2017年4月10日19:04:37 根據瀏覽器編碼文件名
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String userAgent = request.getHeader("User-Agent");
//針對IE或者以IE爲內核的瀏覽器:
if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
fileName = URLEncoder.encode(exportFileName, "UTF-8");
} else {
//非IE瀏覽器的處理:
fileName = new String(exportFileName.getBytes("UTF-8"), "ISO-8859-1");
}
} catch (UnsupportedEncodingException e) {
fileName = "export.xls";
}
response.setHeader("Content-Disposition", "attachment;filename="
+ fileName);
ServletOutputStream output;
try {
output = response.getOutputStream();
workBook.write(output);
output.flush();
output.close();
} catch (IOException e) {
logger.error("導出文件出錯了", e);
throw new RRException("文件導出錯誤");
}
}
/**
* 主要功能: 在EXCEL中添加一個Sheet
* 注意事項:添加Sheet 並將List<Object[]> 中的數據填充
*
* @param sheetName 表單名字
* @param list 要填充的數據 以Object[] 表示單條記錄
* @param colCaption 要生成的表頭
*/
public void addSheetByArray(String sheetName, List<Object[]> list,
String[] colCaption) {
// 創建表單
Sheet sheet;
if (StringUtils.isNullOrEmpty(sheetName)) {
sheet = workBook.createSheet();
} else {
sheet = workBook.createSheet(sheetName);
}
// 生成標題行 (表頭)
createCaptionRow(colCaption, sheet);
// 記錄列數
int colNum = 0;
// 從第二行開始
int startRow = 1;
for (Object[] obj : list) {
Row row = sheet.createRow(startRow++);
int cols = createRowData(row, Arrays.asList(obj));
row.setHeight((short) 400);
colNum = colNum > cols ? colNum : cols;
}
adjustCellWidth(colNum, startRow, sheet);
}
/**
* 主要功能:在EXCEL中添加一個Sheet
* 注意事項:添加Sheet 並將List<Object[]> 中的數據填充
*
* @param sheetName 表單名字
* @param list 要填充的數據 以Map<String,Object> 表示單條記錄
* @param colCaption 要生成的表頭
*/
public void addSheetByMap(String sheetName, List<Map<String, Object>> list,
String[] colCaption) {
// 創建表單
Sheet sheet;
if (StringUtils.isNullOrEmpty(sheetName)) {
sheet = workBook.createSheet();
} else {
sheet = workBook.createSheet(sheetName);
}
// 生成標題行 (表頭)
createCaptionRow(colCaption, sheet);
int colNum = 0;
// 轉換數據
// 從第二行開始
int startRow = 1;
for (Map<String, Object> map : list) {
Row row = sheet.createRow(startRow++);
int cols = createRowData(row, map.values());
row.setHeight((short) 400);
colNum = colNum > cols ? colNum : cols;
}
adjustCellWidth(colNum, startRow, sheet);
// 處理寬度
}
/**
* 主要功能: 判斷fiel
* 注意事項:無
*
* @param name 要判斷的字符
* @param ignores 要忽略的數組
* @return 存在返回true
*/
private boolean isInIgnors(String name, String[] ignores) {
for (String ignore : ignores) {
if (name.equals(ignore)) {
return true;
}
}
return false;
}
/**
* 主要功能: 生成每一行的數據
* 注意事項:無
*
* @param row 要處理的行
* @param coll 集合類型(List Map.values) 要處理的數據
* @return int 列數
*/
private int createRowData(Row row, Collection<Object> coll) {
int cellNum = 0;
for (Object obj : coll) {
// 空值 按照 "" 字符串處理
if (obj == null) {
obj = "";
}
// 轉換一個字符串值, 以方便判斷
String strValue = obj.toString();
// 創建單元格
Cell cell = row.createCell(cellNum);
// 根據單元格的類型設置值
// 公式型(普通BEAN和MAP中暫時並不存在)
if (strValue.startsWith("FORMULA:")) {
} else {
// 處理寬度
// 設置單元格的值
setCellValue(cell, obj);
}
// 處理下一個單元格
cellNum++;
}
return cellNum;
}
/**
* 主要功能: 設置某單元格的值
* 注意事項: 同時根據值類型設置樣式
* TODO: 對數字類型做進一步解析和判斷。 對需要按%顯示的進行處理。 %可以從表頭中獲取?
* 對於CellType 和CellValue 的設置還需要詳細參考文檔,避免產生不必要的錯誤轉換
* 日期類型格式以通用格式。 待替換爲全局變量
* 數字保留小數和顯示百分比格式暫時未設置
*
* @param cell 單元格
* @param obj 原始值( null已轉換爲"" 空字符串)
*/
private void setCellValue(Cell cell, Object obj) {
CreationHelper createHelper = workBook.getCreationHelper();
String strValue = obj.toString();
// 時間戳類型 要先判斷時間戳類型再判斷時期類型
if (obj instanceof Timestamp) {
// 轉換爲Date後賦值
Date dt = (Timestamp) obj;
// String value = DateUtil.format(dt, "yyyy-MM-dd HH:mm:ss");
CellStyle cellStyle = workBook.createCellStyle();
cellStyle.setDataFormat(createHelper.createDataFormat().getFormat(
"yyyy-MM-dd HH:mm:ss"));
cell.setCellValue(dt);
cell.setCellStyle(cellStyle);
}
// 日期型
else if (obj instanceof Date) {
// String value = DateUtil.format((Date)obj, "yyyy-MM-dd");
// cell.setCellValue(value);
CellStyle cellStyle = workBook.createCellStyle();
cellStyle.setDataFormat(createHelper.createDataFormat().getFormat(
"yyyy-MM-dd"));
cell.setCellValue((Date) obj);
cell.setCellStyle(cellStyle);
}
/*
* 由於數字類型有int、long、double、BigDecimal 多種類型 輸出格式可能要求數字、百分比、保留幾位小數等多種格式. 目前僅按照數字格式輸出
*/
else if (obj instanceof Integer) {
cell.setCellType(CellType.NUMERIC);
DecimalFormat df = new DecimalFormat("0");
String value = df.format(obj);
cell.setCellValue(value);
} else if (obj instanceof Long) {
cell.setCellType(CellType.NUMERIC);
DecimalFormat df = new DecimalFormat("0");
String value = df.format(obj);
cell.setCellValue(value);
} else if (obj instanceof Float) {
cell.setCellType(CellType.NUMERIC);
DecimalFormat df = new DecimalFormat("0.0000");
String value = df.format(obj);
cell.setCellValue(value);
} else if (obj instanceof Double) {
cell.setCellType(CellType.NUMERIC);
DecimalFormat df = new DecimalFormat("0.0000");
String value = df.format(obj);
cell.setCellValue(value);
}
// BigDecimal
else if (obj instanceof BigDecimal) {
cell.setCellType(CellType.STRING);
cell.setCellValue(strValue);
}
// 數字 //數字型要判斷 對於百分比顯示 、單位是萬元等的顯示細節要處理
// else if (StringUtil.isFloatNumeric(strValue)) {
// cell.setCellType(CellType.NUMERIC);
// 暫時未處理BigDecimal 類型的數據,如果有問題,只能使用String
// cell.setCellValue(Double.valueOf(strValue));
// modi by zhang @2016年11月14日14:13:11 處理浮點小數格式 暫時無法統一位數
// DecimalFormat df = new DecimalFormat("0.0000");
// String whatYourWant = df.format();
// 按String 方式輸出數字
// BigDecimal bd = new BigDecimal(strValue);
// cell.setCellValue(bd.toPlainString());
// 主要處理小數的位數格式,暫時不好判斷,輸出原值
// cell.setCellValue(strValue);
// CellStyle style = workBook.createCellStyle();
// style.setDataFormat(workBook.createDataFormat().getFormat("0.00%"));
// }
// 字符串類型
else if (obj instanceof String) {
// modi at 2016年11月14日14:27:51 by zhang
// 補充設置單元格類型,避免編碼類被當作數字類型
cell.setCellType(CellType.STRING);
// end modi
cell.setCellValue(strValue);
} else {
cell.setCellType(CellType.STRING);
cell.setCellValue(strValue);
}
}
/**
* 主要功能: 生成EXCEL的第一行表頭
* 注意事項: 默認按第一行生成表頭。
*
* @param colCaption 表頭字符數組
* @param sheet 表單
*/
private void createCaptionRow(String[] colCaption, Sheet sheet) {
// 默認第一行
Row row = sheet.createRow(0);
row.setHeight((short) 400);
if (colCaption == null) {
return;
}
// 按列生成表頭
for (int i = 0; i < colCaption.length; i++) {
Cell cell = row.createCell(i);
cell.setCellStyle(getStyle("title"));
cell.setCellType(CellType.STRING);
cell.setCellValue(colCaption[i]);
}
}
/**
* 主要功能: 調整列寬
* 注意事項:無
*
* @param cols 列數
* @param rows 行數
* @param sheet sheet
*/
private void adjustCellWidth(int cols, int rows, Sheet sheet) {
int[] cellWidth = new int[cols];
// 取列中最長的行
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
Cell cell = sheet.getRow(row).getCell(col);
String value = getCellValue(cell);
int length = value.getBytes().length;
if (length > cellWidth[col]) {
cellWidth[col] = length;
}
}
}
for (int j = 0; j < cellWidth.length; j++) {
if (cellWidth[j] > 254) {
cellWidth[j] = 254;
}
// 設置列寬度 單位爲 1/256 個字符 設置加10%
sheet.setColumnWidth(j,
cellWidth[j] * 12 > 255 ? (255 * 256 / 10) : (cellWidth[j] * 12 * 256 / 10));
}
}
/**
* 主要功能: 取單元格的值
* 注意事項:按數字和字符兩種類型先處理。 BOOLEAN FORMULA 先不處理。 日期格式如何判斷?
*
* @param cell 單元格
* @return 單元格的值
*/
@SuppressWarnings("deprecation")
private String getCellValue(Cell cell) {
String value = "";
try {
// 按數字和字符兩種類型先處理。 BOOLEAN FORMULA 先不處理。 日期格式如何判斷?
switch (cell.getCellTypeEnum()) {
case NUMERIC:
value = cell.getNumericCellValue() + "1111"; // 增加4位的長度
// 數字格式包含日期格式,但暫時無法判斷日期格式
// 除非使用固定寬度。。。。。。。
break;
case STRING:
value = cell.getStringCellValue();
break;
default:
break;
}
} catch (Exception e) {
// 不對異常做處理。僅打印到控制檯以供調試
// 佔不打印
// e.printStackTrace();
}
return value;
}
/**
* 主要功能: 生成表頭樣式(默認樣式)
* 注意事項:僅生成默認樣式
*
* @param type 類型 title 或 data
* @return CellStyle
*/
private CellStyle getStyle(String type) {
CellStyle cs = workBook.createCellStyle();// 創建一個style
if ("title".equals(type)) {// 表頭樣式
Font font = workBook.createFont();// 創建一個字體
// font.setBoldweight(Font.BOLDWEIGHT_BOLD); // 粗體
font.setBold(true);
// cs.setAlignment(CellStyle.ALIGN_CENTER);// 水平居中
cs.setAlignment(HorizontalAlignment.CENTER);
cs.setFillBackgroundColor(HSSFColor.SKY_BLUE.index);// 設置背景色
cs.setFont(font);
}
return cs;
}
/**
* 取得wb的值
*
* @return wb值.
*/
public Workbook getWorkbook() {
return workBook;
}
/**
* 設定wb的值
*
* @param workBook 設定值
*/
public void setWorkbook(Workbook workBook) {
this.workBook = workBook;
}
/**
* 取得exportFileName的值
*
* @return exportFileName值.
*/
public String getExportFileName() {
return exportFileName;
}
/**
* 設定exportFileName的值
*
* @param exportFileName 設定值
*/
public void setExportFileName(String exportFileName) {
this.exportFileName = exportFileName;
}
}
前端代碼:
這個就是比較折磨了,剛開始查閱資料,有用異步的,有用跳轉的,我也用了異步發現這個下載框就是彈不出來,改進後,後端代碼也不用返回值,改成跳轉的了,上代碼
<i-button type="warning" @click="submit">導出Excel</i-button>
這是我後端需要的參數,使用vue做的,你們正常拼接你們定義的參數就行
submit: function () {
location.href = "../black/export?carNo=" + vm.q.carNo + "&createTime=" + vm.q.createTime + "&stopTime=" + vm.q.stopTime
+ "&createMoney=" + vm.q.createMoney + "&stopMoney=" + vm.q.stopMoney + "&num=" + vm.q.num + "&mobile=" + vm.q.mobile;
}
Controller層: 實
體類改成你自己的就ok了
/**
* 黑名單導出功能
*/
@RequestMapping("/export")
public void exportStudent(HttpServletResponse response, HttpServletRequest request) {
Map<String, Object> params = new HashMap<>();
params.put("carNo",request.getParameter("carNo"));
params.put("createTime",request.getParameter("createTime"));
params.put("stopTime",request.getParameter("stopTime"));
params.put("createMoney",request.getParameter("createMoney"));
params.put("stopMoney",request.getParameter("stopMoney"));
params.put("num",request.getParameter("num"));
params.put("mobile",request.getParameter("mobile"));
String filename = "黑名單列表";
List<CarBlack> blackList = blackService.queryAllList(params);
ExcelExport ee1 = new ExcelExport();
List<Object[]> list1 = new ArrayList<Object[]>();
List<Object> obj = new ArrayList<Object>();
for (CarBlack carBlack : blackList) {
obj.add(carBlack.getId());
obj.add(carBlack.getCarNo());
obj.add(carBlack.getDebtSum() / 100);
obj.add(carBlack.getDebtCount());
obj.add(carBlack.getCreateTime());
obj.add(carBlack.getUserName());
obj.add(carBlack.getMobile());
list1.add(obj.toArray());
obj.clear();
}
String[] header = new String[]{"編號", "車牌號", "欠費金額(元)", "欠費次數", "欠費生成時間", "車主姓名",
"手機號碼"};
ee1.addSheetByArray("黑名單列表", list1, header);
ee1.export(response);
效果:
至此完成,呼呼呼 希望可以幫到小夥伴們