匯出List列表中的資料到Excel檔案,並提供下載
阿新 • • 發佈:2019-02-18
整體思路
客戶在頁面點選“匯出Excel”連結-->>進入Java邏輯處理程式碼-->>複製Excel模版檔案-->>向這個複製過的模版檔案中寫入List資料-->>把資料寫入完成的Excel檔案下載到客戶端
適用場景
資料格式固定、需要把List資料匯出到Excel檔案的情況下
具體程式碼
1.頁面連結
// 新增“匯出Excel”連結 $("div#paddingDiv").append( " <a href='exportStatisticsData.sp?dateStart=" + $("#dateStartId").val() + "&dateEnd=" + $("#dateEndId").val() + "&selectOrgan=" + $("#selectOrgan").val() + "''>匯出查詢結果到Excel</a>");
2.SpringMVC的ModelAndView
<!-- 工作量報表,匯出Excel的Action跳轉 -->
<bean name="/exportStatisticsData.sp" class="com.peak.acc.action.ExportStatisticsAction">
<property name="commonDao">
<ref bean="commonDao" />
</property>
</bean>
try { // 接下來,取出資料,進行頁面顯示 list = commonDao.getObjectListByArguments("queryStatisticsT", null); // 將資料庫查詢出來的列表集,轉成頁面展示需要的格式,單獨放在一個方法裡 listShowInPage = exchangeToShowList(list, organString); /** * 最後展示到頁面上的列表元素數量 */ int rows = listShowInPage.size(); // 模版檔案物件(模版在專案中有) File templateFirst = null; if (rows <= 2) {// 如果只有少於等於兩行資料,就使用模版2 templateFirst = new File(request.getRealPath("/") + "upload/acc/template/Acc任務數量統計模版2.xls"); } else {// 否則,使用模版1 templateFirst = new File(request.getRealPath("/") + "upload/acc/template/Acc任務數量統計模版1.xls"); } // 使用模版,生成Excel檔案的目標路徑 targetPath = "D:/acc_rm/Excel/createWhatYouWant/"; // 拷貝模版,生成一個新的檔案,用於寫入統計資料,使用UUID生成唯一檔名 String newFileName = targetPath + UUID.randomUUID().toString() + ".xls"; File newTargetFile = new File(targetPath); // 若目錄不存在,就建立一個 if (!newTargetFile.exists()) { newTargetFile.mkdirs(); } // 建立目標Excel檔案,.xls格式的 newTargetFile = new File(newFileName); // 呼叫靜態方法copyFile()複製模版檔案 到目標檔案 AccFileUtil.copyFile(templateFirst, newTargetFile); log.info("任務統計的寫入檔案準備就緒"); // 把資料,寫入到目標檔案 createTheTargetExcel(rows, newTargetFile); // 附件名稱 String filename = "會計標準化任務統計報表 " + startDate + " -- " + endDate + " " + organString + ".xls"; // 設定response的編碼方式 response.setContentType("application/x-msdownload"); // 寫明要下載的檔案的大小 response.setContentLength((int) newTargetFile.length()); // 設定下載附件的檔名 response.setHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("GBK"), "iso-8859-1")); // 讀出檔案到i/o流 FileInputStream fis = new FileInputStream(newTargetFile); byte[] b = new byte[1024];// 相當於我們的快取 int k = 0;// 該值用於計算當前實際下載了多少位元組 // 從response物件中得到輸出流,準備下載 OutputStream myout = response.getOutputStream(); // 開始迴圈下載 while (-1 != (k = fis.read(b, 0, b.length))) { // 將b中的資料寫到客戶端的記憶體 myout.write(b, 0, k); } // 將寫入到客戶端的記憶體的資料,重新整理到磁碟 myout.flush(); myout.close(); } catch (Exception e) { log .info("ExportExcel ------------------任務數量統計查詢轉換出現錯誤--------------------------:" + e.getMessage()); e.printStackTrace(); } finally { // 清空列表所佔有的記憶體 clearAllList(); // 最後,檢查一下目錄下的檔案個數,大於100的話,就進行清空 deleteDirFiles(targetPath, 100); } // 展示,這裡無需返回檢視 return null;
public static void copyFile(File sourceFile, File targetFile) throws IOException { BufferedInputStream bufIS = null; BufferedOutputStream bufOS = null; try { // 帶緩衝的輸入流 bufIS = new BufferedInputStream(new FileInputStream(sourceFile)); // 帶緩衝的輸出流 bufOS = new BufferedOutputStream(new FileOutputStream(targetFile)); // 緩衝陣列 byte[] bytes = new byte[1024 * 5]; // 位置記錄 int len = 0; while ((len = bufIS.read(bytes)) != -1) { // 把讀入的資料流寫入到輸出流衝 bufOS.write(bytes, 0, len); } // 強制寫入到輸出流 bufOS.flush(); } catch (FileNotFoundException e) { log.info("複製檔案時找不到檔案:" + e.getMessage()); e.printStackTrace(); } catch (IOException e) { log.info("複製檔案時出現IO錯誤:" + e.getMessage()); e.printStackTrace(); } finally { // 重要:記得關閉流 if (bufIS != null) { bufIS.close(); } if (bufOS != null) { bufOS.close(); } } }
/**
* 向目標Excel檔案寫入資料
*
* @param rows
* 需要寫多少行Excel
* @param newTargetFile
* 目標檔案
* @throws IOException
*/
private void createTheTargetExcel(int rows, File newTargetFile)
throws IOException {
FileOutputStream localFile = null;
try {
// 獲取到拷貝過後的Excel模版檔案
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(
newTargetFile));
// 根據Excel檔案,獲取到 工作簿
HSSFWorkbook workbook = new HSSFWorkbook(fs);
// 獲取到第一頁工作表
HSSFSheet sheet = workbook.getSheetAt(0);
// 定義行
HSSFRow row;
// 列表中的把資料寫入到Excel裡面,從第四行開始(前三行是標題)
for (int i = 0; i < rows; i++) {
StatisticsShowE aline = (StatisticsShowE) listShowInPage.get(i);
row = sheet.getRow(i + 3); // 獲取第(i+3)行,前三行是標題
// 單元格的位置,從0開始
short tempCellCounter = 0;
// 解決中文亂碼問題(Excel檔案內容裡面的亂碼)
row.getCell(tempCellCounter).setEncoding(
HSSFWorkbook.ENCODING_UTF_16);
row.getCell(tempCellCounter).setCellValue(aline.getJgm());
tempCellCounter++;
// 每日
row.getCell(tempCellCounter).setCellValue(
aline.getMrrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMrrw().getWwcCount());
tempCellCounter++;
// 日終
row.getCell(tempCellCounter).setCellValue(
aline.getRzrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getRzrw().getWwcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getRzrw().getCbCount());
tempCellCounter++;
// 每週
row.getCell(tempCellCounter).setCellValue(
aline.getMzrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMzrw().getWwcCount());
tempCellCounter++;
// 每旬
row.getCell(tempCellCounter).setCellValue(
aline.getMxrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMxrw().getWwcCount());
tempCellCounter++;
// 每月
row.getCell(tempCellCounter).setCellValue(
aline.getMyrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMyrw().getWwcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMyrw().getCbCount());
tempCellCounter++;
// 每季
row.getCell(tempCellCounter).setCellValue(
aline.getMjrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMjrw().getWwcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMjrw().getCbCount());
tempCellCounter++;
// 半年
row.getCell(tempCellCounter).setCellValue(
aline.getBnrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getBnrw().getWwcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getBnrw().getCbCount());
tempCellCounter++;
// 每年
row.getCell(tempCellCounter).setCellValue(
aline.getMnrw().getWcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMnrw().getWwcCount());
tempCellCounter++;
row.getCell(tempCellCounter).setCellValue(
aline.getMnrw().getCbCount());
tempCellCounter++;
}
// 新建一輸出檔案流
localFile = new FileOutputStream(newTargetFile);
// 把資料寫入到相應的Excel 工作簿
workbook.write(localFile);
localFile.flush();
localFile.close();
} catch (FileNotFoundException e) {
log.info("向Excel檔案寫入資料時出現異常:" + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
log.info("向Excel檔案寫入資料時出現異常:" + e.getMessage());
e.printStackTrace();
} finally {
if (localFile == null) {
// 操作結束,關閉檔案
localFile.close();
}
}
}
/**
* 當指定的目錄下,檔案個數超過一定數量時,進行清空
*
* @param path
* @param targetNum
*/
private void deleteDirFiles(String path, int targetNum) {
File dirPath = new File(path);
if (dirPath.exists()) {// 如果找到了這個目錄
File[] excelFiles = dirPath.listFiles();
// 當該目錄下的檔案個數大於指定引數時
if (excelFiles.length > targetNum) {
for (int i = 0; i < excelFiles.length; i++) {
File tempFile = excelFiles[i];
// 日誌記錄刪除的檔案的名稱
log.info(tempFile.getName() + " 已經刪除");
if (tempFile.isFile()) {// 如果是檔案,就進行刪除
tempFile.delete();
}
}
}
}
}
注:使用的Excel解析框架是POI,此處僅提供實現思路和部分實現程式碼
匯出效果:
最後匯出的Excel檔案:
模版檔案: