Springboot POI導(dǎo)出Excel(瀏覽器)
本文實(shí)例為大家分享了Springboot POI導(dǎo)出Excel的具體代碼,供大家參考,具體內(nèi)容如下
需求:頁面根據(jù)查詢條件導(dǎo)出(瀏覽器)
由于本次導(dǎo)出數(shù)據(jù)量較大,這里采用XSSFWorkbook多線程進(jìn)行導(dǎo)出,注:XSSFWorkbook導(dǎo)出excel文件結(jié)尾為:“.xlsx”。
導(dǎo)出不需要返回,如有返回則會(huì)報(bào)異常!
//Controller
@RequestMapping("/stateExport")
public void stateExport(HttpServletResponse response,@RequestParam("deviceId") Long deviceId, String startTime,String endTime) {
try {
deviceMonitorService.stateExport(response, deviceId, startTime,endTime);
LOG.info("導(dǎo)出成功");
} catch (Exception e) {
LOG.error("導(dǎo)出異常:",e.getMessage());
}
}
//Service
@Override
public void stateExport(HttpServletResponse response, Long deviceId, String startTime, String endTime) throws Exception{
//list自己查詢得出
List<StateDetailsResult> list = queryStateDetails(deviceId, startTime, endTime);
String time = TimeUtils.YEAR_DAY_SECOND_FORMAT.format(new Date());
//sheet名稱
String sheetName = deviceDtls.getName() + "狀態(tài)"+time;
//文件名稱
String excelName = deviceDtls.getName() + "狀態(tài)"+time+".xlsx";
//文件頭
String[] strings = {"狀態(tài)名稱","開始時(shí)間","結(jié)束時(shí)間","狀態(tài)時(shí)長(zhǎng)"};
String path = this.getClass().getResource("").getPath() + "excel";
DownloadFileUtil.createDirs(path);
String filePath = path + "/" + sheetName + ".xls";
stateCreateExcel(list,strings,sheetName,excelName,filePath);
DownloadFileUtil.download(filePath, response);
}
public String stateCreateExcel(List<StateDetailsResult> list, String[] strArray,String sheetName,String excelName,String filePath)throws Exception {
// 總數(shù)據(jù)條數(shù)
int dataSize = list.size();
// 線程數(shù)
int threadNum = 2;
int threadSize = dataSize / threadNum;
ExecutorService exec = Executors.newFixedThreadPool(threadNum);
//cutList 和輸入list類型保持一致
List<StateDetailsResult> cutList = null;
// 第一步,創(chuàng)建一個(gè)webbook,對(duì)應(yīng)一個(gè)Excel文件
XSSFWorkbook wb = new XSSFWorkbook();
// 第二步,在webbook中添加一個(gè)sheet,對(duì)應(yīng)Excel文件中的sheet
XSSFSheet sheet = wb.createSheet(sheetName);
sheet.setDefaultColumnWidth(20);// 默認(rèn)列寬
// 第三步,在sheet中添加表頭第0行,注意老版本poi對(duì)Excel的行數(shù)列數(shù)有限制short
XSSFRow row = sheet.createRow((int) 0);
// 第四步,創(chuàng)建單元格,并設(shè)置值表頭 設(shè)置表頭居中
XSSFCellStyle style = wb.createCellStyle();
// 創(chuàng)建一個(gè)居中格式
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 添加excel title
XSSFCell cell = null;
for (int i = 0; i < strArray.length; i++) {
cell = row.createCell((short) i);
cell.setCellValue(strArray[i]);
cell.setCellStyle(style);
}
List<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>();
Callable<Integer> task = null;
// 第五步,寫入實(shí)體數(shù)據(jù) 實(shí)際應(yīng)用中這些數(shù)據(jù)從數(shù)據(jù)庫(kù)得到,list中字符串的順序必須和數(shù)組strArray中的順序一致
int startNum ;
System.out.println("任務(wù)開始,總數(shù):"+list.size());
// 開始時(shí)間
long start = System.currentTimeMillis();
System.out.println("線程任務(wù)執(zhí)行");
for (int i = 0; i < threadNum; i++) {
startNum = threadSize * i;
if (i == threadNum - 1) {
cutList = list.subList(threadSize * i, dataSize);
} else {
cutList = list.subList(threadSize * i, threadSize * (i + 1));
}
//listStr 和輸入list類型保持一致
final List<StateDetailsResult> listStr = cutList;
int finalStartNum = startNum;
task = new Callable<Integer>() {
final int s= finalStartNum;
@Override
public Integer call() throws Exception {
for(int j=0;j<listStr.size();j++){
XSSFRow row =getRow(sheet,s+j);
//設(shè)置每一列展示內(nèi)容自己設(shè)置
row.createCell(0).setCellValue(listStr.get(j).getName());
row.createCell(1).setCellValue(listStr.get(j).getStartDateTime());
row.createCell(2).setCellValue(listStr.get(j).getEndDateTime());
row.createCell(3).setCellValue(listStr.get(j).getDateTime());
}
return 1;
}
};
// 這里提交的任務(wù)容器列表和返回的Future列表存在順序?qū)?yīng)的關(guān)系
tasks.add(task);
}
try {
List<Future<Integer>> results = exec.invokeAll(tasks);
} catch (Exception e) {
e.printStackTrace();
}
// 關(guān)閉線程池
exec.shutdown();
DownloadFileUtil.delfile(filePath);
// 第六步,將文件存到指定位置
try {
FileOutputStream fout = new FileOutputStream(filePath);
wb.write(fout);
fout.flush();
fout.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("線程任務(wù)執(zhí)行結(jié)束");
System.err.println("執(zhí)行任務(wù)消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
return filePath;
}
//線程同步,保證不會(huì)多插入數(shù)據(jù)
private synchronized XSSFRow getRow(XSSFSheet sheet, int rownum) {
//如果不包含列頭,+1去掉即可
return sheet.createRow(rownum+1);
}
最后附上使用的工具類
package com.sec.deviceband.utils;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
public class DownloadFileUtil {
/**
* 判斷路徑是否存在不存在則創(chuàng)建
* @param path
*/
public static void createDirs(String path) {
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
}
/**
* 下載
*
* @param path
* @param response
*/
public static void download(String path, HttpServletResponse response) {
try {
// path是指欲下載的文件的路徑。
File file = new File(path);
// 取得文件名。
String filename = file.getName();
// 以流的形式下載文件。
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 設(shè)置response的Header
response.addHeader("Content-Disposition", "attachment;filename="
+ URLEncoder.encode(filename, "utf-8"));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(
response.getOutputStream());
response.setContentType("application/vnd.ms-excel;charset=utf-8");
toClient.write(buffer);
toClient.flush();
toClient.close();
delfile(path);
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 判斷文件是否存在則刪除
*
* @param filepath
*/
public static void delfile(String filepath) {
File file = new File(filepath);
if (file.exists()) {
file.delete();
}
}
}
測(cè)試方式:瀏覽器輸入請(qǐng)求路徑

測(cè)試效果:


由于水平有限,博客中難免會(huì)有一些錯(cuò)誤,有紕漏之處懇請(qǐng)各位大佬不吝賜教!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
使用java實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲
這篇文章主要介紹了使用java實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Guava自動(dòng)加載緩存LoadingCache使用實(shí)戰(zhàn)詳解
這篇文章主要為大家介紹了Guava自動(dòng)加載緩存LoadingCache使用實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
關(guān)于JAVA經(jīng)典算法40題(超實(shí)用版)
本篇文章小編為大家介紹一下,關(guān)于JAVA經(jīng)典算法40題(超實(shí)用版),有需要的朋友可以參考一下2013-04-04

