|
開發(fā)過程中經常會遇到 Excel 導出的情況,尤其是在企業(yè)開發(fā)中,涉及到客戶信息、財務報表、市場分析等,情景非常多。平常開發(fā)過程中大多都會針對每個導出單獨寫一套代碼,隨著導出越來越多,心里便想:有沒有一個足夠通用東西可以讓我們不用寫這么多代碼來實現(xiàn) Excel 導出? 帶著這個問題便開始了自己的“ExcelUtil”之路,在這過程中主要接觸過 easypoi,但還是不太滿足。因為 easypoi 和大多數(shù) Java 庫一樣:基于字段寫配置。當然不是說這個不好,有很多庫都這樣,比如 fastjson、Jackson 等都是在字段上寫注解,描述這個字段有些什么信息或作用等。但對于 Excel 導出,我總覺得還有更加通用的方式。 經過一段時間的摸索和發(fā)掘,在前端的 table 標簽上找到了靈感,認為這個方式很好、非常好。table 標簽本身包含了很多描述信息,像行、列、合并行、合并列這些與 excel 的 sheet 頁“驚人的相似”,再加上近幾年前端三大框架的大力發(fā)展,尤其是 angular 和 vue 這兩個框架在標簽上自定義屬性的方式進一步讓我在寫 ExcelUtil 過程中得到了不少啟發(fā)。 簡介ExcelUtil 和RunnerUtil( GitHub ) 一樣,大概是在今年 5 到 6 月寫的,最近又重新整理了一下,已上傳 GitHub # ExcelUtil 。 ExcelUtil 根據(jù) excel 文件、sheet 頁、row 行、cell 單元格這樣的層次結構分別定義了自己的作用域,每個作用域內可以一定程度上自定義變量等,作用域之間互不影響,同名變量下層作用域等聲明優(yōu)先于上層作用域等這些與 java、JavaScript 等語言的作用域結構一致。 不同的是 ExcelUtil 使用頻率比 RunnerUtil 頻率高很多,寫 RunnerUtil 的初衷也是為了這個 ExcelUtil 導出,最開始想到了 Java 內置腳本引擎(ScriptEngine),但內置腳本引擎的效率實在太低,數(shù)據(jù)量稍微大一點(不用太大)情況下直接卡死(不該這么吐槽的,但的確不適合這個場景)。但是 RunnerUtil 的功能獨立且完善,完全可以單獨使用。 使用介紹
// 在什么地方導出,就在那個方法上進行聲明式“注解編程”// 首先要聲明這是一個 Excel,用 type 指定是 xls 或者 xlsx@TableExcel(type = TableExcel.Type.XLS, value = { /* * value 包含的是左右 sheet 頁的信息 * 自 sheet 向下,每個標簽可以判斷、循環(huán)等 * 用 sheetName 指定 sheet 名 * 為什么要用單引號再多包裹一層呢?詳見 RunnerUtil * 因為這里面的所有內容都是用 RunnerUtil 解析的,需要符合它的格式 */ @TableSheet(sheetName = ''人員信息'', value = { /* * 在這兒聲明了一個名為 names 的數(shù)組,用作標題 */ @TableRow(var = 'names = {'序號','姓名','性別','年齡','電話','家庭住址', '備注'}', value = { /* * 這兒用了迭代,迭代 row 上聲明的 names * 這個迭代將按 names 的內容生成對應數(shù)量和內容的 cell 單元格 */ @TableCell(var = 'name:names', value = name) }), /* * 上面 cell 的迭代用的是冒號,這兒用了 in,二者意義完全一樣 * 支持 in 完全是為了向靈感的來源(前端)致敬 * 但是 in 并不是關鍵字,仍可作為普通變量 * 不同的是 in 的兩端至少各有一個空格 * 可迭代的數(shù)據(jù)類型一會兒詳細介紹 */ @TableRow(var = '($rowData, index) in collect', value = { @TableCell('index + 1'), // 序號 @TableCell('$rowData.name'), // 姓名 @TableCell('$rowData.sex'), // 性別 @TableCell('$rowData.age'), // 年齡 @TableCell('$rowData.mobile'), // 電話 @TableCell('$rowData.address'), // 家庭住址 // 最后這個對于上面的備注,這兒有個 when,只有 index == 0 才創(chuàng)建這個單元格 // 同時這兒還用到了并合并行,另外 colspan 是合并列 @TableCell(when = 'index == 0', rowspan = 'data.size()') }) })})public Workbook exportExcel(Object data){ /* * 寫好注解后只需要調用這個方法便可得到一個 Workbook */ return ExcelUtil.render(data);}復制代碼
使用效果:
性能測試貼一個本工具導出的 10 列 Excel 的性能測試表(本機環(huán)境 i7-8700K 16G Win10)
從這個數(shù)據(jù)可以看出,隨著數(shù)據(jù)量增加,時間與數(shù)據(jù)的關系呈正相關性,比較接近線性關系,100 萬行數(shù)據(jù)生成 Workbook 耗時 6s,總耗時 12s,在正常業(yè)務場景下能滿足時間的要求。 |
|
|
來自: 西北望msm66g9f > 《培訓》