1. 程式人生 > >java後臺利用Apache poi 生成excel文件提供前臺下載

java後臺利用Apache poi 生成excel文件提供前臺下載

之前在專案中會用到在Java在後臺把資料填入Word文件的模板來提供前臺下載,為了自己能隨時檢視當時的實現方案及方便他人學習我寫了這篇部落格,訪問量已經是我寫的部落格裡第一了。於是乎我在學會用Java在後臺利用Apache poi 生成excel文件提供前臺下載之後就想著來寫一篇姊妹篇啦。

在生成Excel文件的時候我採用了和生成Word時的不同方法,Apache poi。它是用Java編寫的免費開源的跨平臺的 Java API,提供API給Java程式對Microsoft Office格式檔案讀和寫的功能。想要實現這個功能,就按照下面的步驟來做吧,為了方便起見,我直接拿專案中遇到的例項來舉例說明,是的,我在寫這篇部落格的時候同時也在完成手上的專案。

step1:建立xls格式的模板

表頭含有我的甲方資訊就打碼了,可以看到我搞了一個空的模板檔案,現在有很多東西需要在後臺填入


step2:前臺觸發事件

搞一個按鈕,使用者點選的時候用JavaScript的window.location.href將頁面重定向到你處理下載的URL去

比方說,這是我專案的前臺,看到那個表面質量按鈕嗎,來看一下當它被點選的時候呼叫的函式


function exportBatch() {
        //get請求,可以傳遞引數,比方說我這裡就傳了一堆卷號,我只生成傳過去的這堆卷號的檢驗記錄
        //引數rollNumbers的細節就不展示了,業務相關
        window.location.href = '../ir/exportSurface?rollNumberList=' + rollNumbers;
    }

有朋友可能想用什麼Ajax來發送請求,我反正是沒搞出來,挺麻煩的,網上找的相關解決方案也都比較蛋疼,因此不傳什麼複雜的敏感的引數,就這麼寫就可以。

step3:後臺處理

首先你當然要把Apache poi那一套東西引入你的專案啦,我的專案是Maven專案,新增依賴很容易

<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.14</version>
		</dependency>
然後,為了方便匯出Excel,在專案中建了一個ExcelUtils工具類,後面給出原始碼,這麼一來匯出Excel會變得更簡單。ExcelUtils裡面除了一些既定的方法外,還有就是你具體怎麼去操作模板的方法了。當然你用的少的話可以不用我這工具類,而是在你需要的時候import相關的類,然後在你處理的時候就把操作模板的邏輯寫進去也可以。但我這個專案很多次用到匯出Excel,所以抽象出一個工具類是很有必要的,符合設計模式。

我的專案是基於SpringMVC的,來看看我後臺接收到請求以後做了些什麼吧

Controller:

/***
     * 批量匯出表面質量檢驗記錄
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "exportSurface", method = RequestMethod.GET)
    @ResponseBody
    public void exportSurface(HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
        //引數獲取及處理,業務相關不展示
//把要填寫的資料放在一個map裡
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("sequence", "0001");//mock編號
        map.put("date", DateUtils.toDateStr(new Date(), DateUtils.DEFAULT_DATE_PATTERN_CHINESE));
        map.put("chetaihao", "1#");//mock車臺號
        map.put("productName", "預應力鋼絞線");//mock品名
        map.put("specification", "規格");//mock規格
        map.put("memo", "備註");//mock備註
        map.put("inspectRecordBizList", inspectRecodeBizList);
        ExcelUtils.exportInspectionRecordSurface(request, response, map);
    }
最後呼叫ExcelUtils裡的相關匯出方法,這個方法是自定義的,它定義的是怎樣去操作模板

自定義的方法:

public static void exportInspectionRecordSurface(HttpServletRequest request, HttpServletResponse response, Map map) throws IOException {
        //模板的路徑,這個在自己的專案中很容易弄錯,相對位置一定要寫對啊
String psth = request.getRealPath("/") + INSPECTIONRECORD_SURFACE_TEMPLET_PATH;
        Workbook webBook = readExcel(psth);
        createCellStyle(webBook);
        Sheet sheet = webBook.getSheetAt(0);
//開始操作模板,找到某行某列(某個cell),需要注意的是這裡有個坑,行和列的計數都是從0開始的
//一次資料插入的位置不對,別灰心,多試幾次就好啦,你要是能看懂我下面的程式碼,資料插在了什麼位置,你就明白了
        int rows = 1;
        Row row = sheet.getRow(rows);
        row.createCell(1).setCellValue((String) map.get("sequence"));
        row.createCell(3).setCellValue((String) map.get("date"));
        row.createCell(9).setCellValue((String) map.get("chetaihao"));
        rows = 2;
        row = sheet.getRow(rows);
        row.createCell(1).setCellValue((String) map.get("productName"));
        row.createCell(3).setCellValue((String) map.get("specification"));
        row.createCell(9).setCellValue((String) map.get("memo"));
//檢驗記錄的插入業務相關,不展示,其實就是for迴圈在合適的行合適的列插入一個個物件的屬性即可,你這麼聰明,沒問題的
        writeExcel(response, webBook, "表面質量檢驗記錄");
    }

ExcelUtils:
//這裡得有你自己的package名

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by bwju on 2016/12/06.
 */
public class ExcelUtils {
    private static final String INSPECTIONRECORD_SURFACE_TEMPLET_PATH = "/asserts/templete/InspectionRecordSurface.xls";
    private static HSSFCellStyle cellstyle = null;

    public static void exportInspectionRecordSurface(HttpServletRequest request, HttpServletResponse response, Map map) throws IOException {
        //實現上文裡有,改個函式名,寫你的操作模板函式吧!
    }

    private static Workbook readExcel(String filePath) {
        InputStream in = null;
        Workbook work = null;
        try {
            in = new FileInputStream(filePath);
            work = new HSSFWorkbook(in);
        } catch (FileNotFoundException e) {
            System.out.println("檔案路徑錯誤");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("檔案輸入流錯誤");
            e.printStackTrace();
        }
        return work;
    }

    private static void writeExcel(HttpServletResponse response, Workbook work, String fileName) throws IOException {
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            response.setContentType("application/ms-excel;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName + ".xls", "UTF-8"))));
            work.write(out);
        } catch (IOException e) {
            System.out.println("輸出流錯誤");
            e.printStackTrace();
        } finally {
            out.close();
        }
    }

    private static Cell setCellStyleWithStyleAndValue(CellStyle style, Cell cell, String value) {
        cell.setCellStyle(style);
        cell.setCellValue(value);
        return cell;
    }

    private static Cell setCellStyleWithValue(Cell cell, String value) {
        cell.setCellStyle(cellstyle);
        cell.setCellValue(value);
        return cell;
    }


    private static Cell setCellStyleWithStyleAndValue(CellStyle style, Cell cell, RichTextString value) {
        cell.setCellStyle(style);
        cell.setCellValue(value);
        return cell;
    }

    private static Cell setCellStyleWithValue(Cell cell, int value) {
        cell.setCellStyle(cellstyle);
        cell.setCellValue(value);
        return cell;
    }

    private static Cell setCellStyleWithValue(Cell cell, double value) {
        cell.setCellStyle(cellstyle);
        cell.setCellValue(value);
        return cell;
    }

    private static HSSFCellStyle createCellStyle(Workbook wb) {
        cellstyle = (HSSFCellStyle) wb.createCellStyle();
        cellstyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        cellstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        cellstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        cellstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        cellstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        cellstyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        return cellstyle;
    }
}

step4:啟動專案,然後測試一下,看!完美的匯出了。。。有圖為證

嗯嗯,文章寫到這裡就結束啦,Apache poi還提供了很多API在本例中為得到展示,比如能夠指定樣式等等。希望大家進一步學習。

如果有收穫的話可以掃碼側面的二維碼打賞一下喲,感謝您的鼓勵~