1. 程式人生 > >匯出List列表中的資料到Excel檔案,並提供下載

匯出List列表中的資料到Excel檔案,並提供下載

整體思路

客戶在頁面點選“匯出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檔案:



模版檔案: