沒想到啊,Java操作Excel竟然這麼簡單!

前言

在工作中,使用excel表格處理數據是很常見的操作,本文就來講解下如何使用開源輪子實現下載、導入、導出的功能。

在之前,很多Java程序員都喜歡使用POI的類庫來操作excel,但是非常的不方便,不僅代碼寫的很臃腫,還要處理各種office版本兼容問題,最怕的就是使用不當很容易造成內存溢出,因此今天給大家推薦阿里的一款開源項目 easyexcel

項目介紹

easyexcel是一款快速、簡單避免OOM的java處理Excel工具

github地址:https://github.com/alibaba/easyexcel

Start:15.2k

看了下,兩天前項目團隊還有在完善代碼,可見項目還是挺活躍的

image-20200611173444558

項目集成

使用idea開發工具簡單創建了一個easyexcel-demo項目,加入了web模塊以及easyexcel maven依賴,依賴如下:

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.4</version>
</dependency>

版本的話我們使用2.2.4,2020年6月份上傳的,算是最新的版本了。

image-20200611174114531

好了,我們就開始寫功能了。

1、實現已有Excel模板下載

很多系統有數據批量導入的場景,因爲在頁面上批量加數據時間成本太大了,但是一般導入的時候得按照一定的格式改,所以一般好的產品會先讓用戶下載一個帶有格式的文檔,然後按照格式寫好以後上傳導入,我們來實現這個功能吧!

創建模板文件

首先我們創建一個模板文件,內容如圖

image-20200611175645484

###將模板文件放置再項目裏

然後我們把它放在項目的配置文件下,如圖

image-20200611184415028

然後下載代碼也很簡單,主要分爲加載資源->讀取資源->寫入響應流

@RestController
@RequestMapping("/user")
public class UserController {
    /**
     * 下載模板
     */
    @GetMapping("/downloadTemplate")
    public void downloadTemplate(HttpServletResponse response) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource("excelTemplate/easyexcel.xlsx");
        InputStream inputStream = classPathResource.getInputStream();
        Workbook workbook = new HSSFWorkbook(inputStream);
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("content-Disposition", "attachment;filename=" + URLEncoder.encode("easyexcel.xlsx", "utf-8"));
        response.setHeader("Access-Control-Expose-Headers", "content-Disposition");
        OutputStream outputStream = response.getOutputStream();
        workbook.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }
}

測試

啓動項目,訪問,如圖所示,可以下載。

Jun-11-2020 18-41-52

2.寫入數據並生成文件

將數據導出到文檔這種場景可以說是最常見的了,那麼怎麼使用easyExcel快速實現呢,我們同樣還是以上面的模板爲例

定義模型映射對象 UserExcelModel

@Data
public class UserExcelModel  extends BaseRowModel implements Serializable {

    @ExcelProperty(value = "用戶名", index = 0)
    private String name;

    @ExcelProperty(value = "年齡", index = 1)
    private Integer age;

    @ExcelProperty(value = "手機號", index = 2)
    private String mobile;

    @ExcelProperty(value = "性別", index = 3)
    private String sex;
}

定義這個對象的目的有兩個:當前場景下寫入文件作爲model對象構造數據以及下個要講的數據讀取了。

「簡要代碼流程如下:」

定義列標題->創建sheet->自定義字體和風格->構造數據->寫入數據->寫入到瀏覽器響應流

 /**
     * 導出數據
     */
    @GetMapping("/exportData")
    public void exportData(HttpServletResponse response) throws Exception {
        XSSFWorkbook workbook = new XSSFWorkbook();

        String []columnNames = {"用戶名","年齡","手機號","性別"};

        Sheet sheet = workbook.createSheet();
        Font titleFont = workbook.createFont();
        titleFont.setFontName("simsun");
        titleFont.setBold(true);
        titleFont.setColor(IndexedColors.BLACK.index);

        XSSFCellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        titleStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
        titleStyle.setFont(titleFont);

        Row titleRow = sheet.createRow(0);

        for (int i = 0; i < columnNames.length; i++) {
            Cell cell = titleRow.createCell(i);
            cell.setCellValue(columnNames[i]);
            cell.setCellStyle(titleStyle);
        }
        //模擬構造數據
        List<UserExcelModel> dataList = new ArrayList<>();
        dataList.add(new UserExcelModel("張三",12,"13867098765","男"));
        dataList.add(new UserExcelModel("張三1",12,"13867098765","男"));
        dataList.add(new UserExcelModel("張三2",12,"13867098765","男"));
        dataList.add(new UserExcelModel("張三3",12,"13867098765","男"));

        //創建數據行並寫入值
        for (int j = 0; j < dataList.size(); j++) {
            UserExcelModel userExcelModel = dataList.get(j);
            int lastRowNum = sheet.getLastRowNum();
            Row dataRow = sheet.createRow(lastRowNum + 1);
            dataRow.createCell(0).setCellValue(userExcelModel.getName());
            dataRow.createCell(1).setCellValue(userExcelModel.getAge());
            dataRow.createCell(2).setCellValue(userExcelModel.getMobile());
            dataRow.createCell(3).setCellValue(userExcelModel.getSex());
        }
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("content-Disposition", "attachment;filename=" + URLEncoder.encode("easyexcel.xls", "utf-8"));
        response.setHeader("Access-Control-Expose-Headers", "content-Disposition");
        OutputStream outputStream = response.getOutputStream();
        workbook.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }


3.讀取數據

image-20200619140427117

我們再回過頭來看我們定義的這個Model對象,通過指定index可以對應讀取的excel裏面的列,然後定義的數據類型就對應到excel裏面具體的值,來看看如何實現:

    @PostMapping("/readExcel")
    public List<UserExcelModel> readExcel(@RequestParam("file") MultipartFile file){
        List<UserExcelModel> list = new ArrayList<>();
        try {
            list = EasyExcel.read(file.getInputStream(),UserExcelModel.class,new ModelExcelListener()).sheet().doReadSync();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

看完代碼是不是心裏一萬頭草擬嗎飛過~ 看完這個代碼再看用poi工具處理的,是不是相當簡潔了。對於代碼中的ModelExcelListener,其實是我們自定義的一個讀取監聽類,貼貼代碼:

public static class ModelExcelListener extends AnalysisEventListener {
        private List<Object> datas = new ArrayList<>();
        /**
         * 通過 AnalysisContext 對象還可以獲取當前 sheet,當前行等數據
         */
        @Override
        public void invoke(Object data, AnalysisContext context) {
            //數據存儲到list,供批量處理,或後續自己業務邏輯處理。
            log.info("讀取到數據{}",data);
            datas.add(data);
            //根據業務自行處理,可以寫入數據庫等等
        }

        //所以的數據解析完了調用
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            log.info("所有數據解析完成");
        }
    }

這是一個讀取數據監聽類,有特殊業務需求的都可以在這個類裏面自定義實現,比如邊讀邊寫庫啊,數據過濾和處理等等,用的好了絕對是一把利劍。

PostMan模擬調用

image-20200619145720559

控制檯輸出

image-20200619145829105

總結

通過本篇文章,我們演示瞭如何使用easyexcel進行一些excel的操作,在實際的項目應用中,可以對以上示例代碼進行進一步的封裝,使其不管是讀取、導出等操作都能幾行代碼搞定,這個就得根據情況大家自由發揮了。

項目代碼獲取

  1. 地址:https://github.com/pengziliu/GitHub-code-practice/ 

  2. 點擊底部閱讀原文

喜歡做關注做個標記唄。點個再看,發文第一時間知道~


之前,給大家發過四份Java面試寶典,這次新增了更全面的資料,相信在跳槽前準備準備,基本沒大問題。

java基礎:設計模式等(初中級)

JVM:整理BAT最新題庫》《併發編程(中高級)

分佈式微服務架構》《架構|軟技能(資深)

一線互聯網公司面試指南(資深)

分別適用於初中級,中高級資深級工程師的面試複習。

內容包含java基礎、JVM併發編程分佈式微服務架構|軟技能算法等等。

 

學習視頻包含 深入運行時數據區、垃圾回收、詳解類裝載過程及類加載機制、手寫Spring-IOC容器、redis入門到高性能緩存組件等等

獲取方式:掃描下方二維碼加微信即可領取,資料持續更新

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章