在項(xiàng)目持續(xù)集成的過程中,有時(shí)候需要實(shí)現(xiàn)報(bào)表導(dǎo)出和文檔導(dǎo)出,類似于excel中這種文檔的導(dǎo)出,在要求不高的情況下,有人可能會(huì)考慮直接導(dǎo)出csv文件來(lái)簡(jiǎn)化導(dǎo)出過程。但是導(dǎo)出xlsx文件,其實(shí)過程相對(duì)更復(fù)雜。解決方案就是使用poi的jar包。使用源生的poi來(lái)操作表格,代碼冗余,處理復(fù)雜,同時(shí)poi的相關(guān)聯(lián)的依賴還會(huì)存在版本兼容問題。所以直接使用poi來(lái)實(shí)現(xiàn)表格導(dǎo)出,維護(hù)成本大,不易于拓展。
我們需要學(xué)會(huì)站在巨人的肩膀上解決問題,jxls-poi這個(gè)就很好解決這個(gè)excel表格導(dǎo)出的多樣化的問題。類似jsp和thymealf的模板定義,使得表格導(dǎo)出變得簡(jiǎn)單可控。
不多BB上代碼
1.引入關(guān)鍵依賴包
1
2
3
4
5
6
7
8
9
10
11
12
|
<!-- jxls-api依賴 --> < dependency > < groupId >org.jxls</ groupId > < artifactId >jxls-poi</ artifactId > < version >1.0.15</ version > </ dependency > < dependency > < groupId >org.jxls</ groupId > < artifactId >jxls</ artifactId > < version >2.4.6</ version > </ dependency > |
這里只需要兩個(gè)依賴便操作excel表格了。
2.定義模板文件
新建一個(gè)excel文件,后綴名為.xlsx,在resources目錄下新增一個(gè)jxls的文件夾,把模板文件放在這個(gè)文件夾下,便于后續(xù)的spring-boot的集成。
3.導(dǎo)出工具類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
/** * @author machenike */ public class ExcelUtils { /*** * excel導(dǎo)出到response * @param fileName 導(dǎo)出文件名 * @param templateFile 模板文件地址 * @param params 數(shù)據(jù)集合 * @param response response */ public static void exportExcel(String fileName, InputStream templateFile, Map<String, Object> params, HttpServletResponse response) throws IOException { response.reset(); response.setHeader( "Accept-Ranges" , "bytes" ); OutputStream os = null ; response.setHeader( "Content-disposition" , String.format( "attachment; filename=\"%s\"" , fileName)); response.setContentType( "application/octet-stream;charset=UTF-8" ); try { os = response.getOutputStream(); exportExcel(templateFile, params, os); } catch (IOException e) { throw e; } } /** * 導(dǎo)出excel到輸出流中 * @param templateFile 模板文件 * @param params 傳入?yún)?shù) * @param os 輸出流 * @throws IOException */ public static void exportExcel(InputStream templateFile, Map<String, Object> params, OutputStream os) throws IOException { try { Context context = new Context(); Set<String> keySet = params.keySet(); for (String key : keySet) { //設(shè)置參數(shù)變量 context.putVar(key, params.get(key)); } Map<String, Object> myFunction = new HashMap<>(); myFunction.put( "fun" , new ExcelUtils()); // 啟動(dòng)新的jxls-api 加載自定義方法 Transformer trans = TransformerFactory.createTransformer(templateFile, os); JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) trans.getTransformationConfig().getExpressionEvaluator(); evaluator.getJexlEngine().setFunctions(myFunction); // 載入模板、處理導(dǎo)出 AreaBuilder areaBuilder = new XlsCommentAreaBuilder(trans); List<Area> areaList = areaBuilder.build(); areaList.get( 0 ).applyAt( new CellRef( "sheet1!A1" ), context); trans.write(); } catch (IOException e) { throw e; } finally { try { if (os != null ) { os.flush(); os.close(); } if (templateFile != null ) { templateFile.close(); } } catch (IOException e) { throw e; } } } /** * 格式化時(shí)間 */ public Object formatDate(Date date) { if (date != null ) { SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); String dateStr = sdf.format(date); return dateStr; } return "--" ; } /** * 設(shè)置超鏈接方法 */ public WritableCellValue getLink(String address, String title) { return new WritableHyperlink(address, title); } } |
這個(gè)工具類中我定義兩個(gè)導(dǎo)出用的方法
一個(gè)是直接是HttpServletResponse 導(dǎo)出在線下載文件
一個(gè)使用輸入流導(dǎo)出
同時(shí)模板中還支持方法傳入。
4.定義導(dǎo)出服務(wù)類
全局配置jxls模板的基礎(chǔ)路徑
1
2
|
#jxls模板的基礎(chǔ)路徑 jxls.template.path: classpath:jxls/ |
定義服務(wù)接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/** * excel用service */ public interface ExcelService { /** * 導(dǎo)出excel,寫入輸出流中 * @param templateFile * @param params * @param os * @return */ boolean getExcel(String templateFile,Map<String,Object> params, OutputStream os); /** * 導(dǎo)出excel,寫入response中 * @param templateFile * @param fileName * @param params * @param response * @return */ boolean getExcel(String templateFile,String fileName, Map<String,Object> params, HttpServletResponse response); /** * 導(dǎo)出excel,寫入文件中 * @param templateFile * @param params * @param outputFile * @return */ boolean getExcel(String templateFile, Map<String,Object> params, File outputFile); } |
excel導(dǎo)出用服務(wù)實(shí)現(xiàn)類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/** * excel用serviceImpl */ @Service public class ExcelServiceImppl implements ExcelService { private static final Logger logger = LoggerFactory.getLogger(ExcelServiceImppl. class ); /** * 模板文件的基礎(chǔ)路徑 */ @Value ( "${jxls.template.path}" ) private String templatePath; @Override public boolean getExcel(String templateFile, Map<String, Object> params, OutputStream os) { FileInputStream inputStream = null ; try { //獲取模板文件的輸入流 inputStream = new FileInputStream(ResourceUtils.getFile(templatePath + templateFile)); //導(dǎo)出文件到輸出流 ExcelUtils.exportExcel(inputStream, params, os); } catch (IOException e) { logger.error( "excel export has error" + e); return false ; } return true ; } @Override public boolean getExcel(String templateFile, String fileName, Map<String, Object> params, HttpServletResponse response) { FileInputStream inputStream = null ; try { //獲取模板文件的輸入流 inputStream = new FileInputStream(ResourceUtils.getFile(templatePath + templateFile)); //導(dǎo)出文件到response ExcelUtils.exportExcel(fileName,inputStream,params,response); } catch (IOException e) { logger.error( "excel export has error" + e); return false ; } return true ; } @Override public boolean getExcel(String templateFile, Map<String, Object> params, File outputFile) { FileInputStream inputStream = null ; try { //獲取模板文件的輸入流 inputStream = new FileInputStream(ResourceUtils.getFile(templatePath + templateFile)); File dFile = outputFile.getParentFile(); //文件夾不存在時(shí)創(chuàng)建文件夾 if (dFile.isDirectory()){ if (!dFile.exists()){ dFile.mkdir(); } } //文件不存在時(shí)創(chuàng)建文件 if (!outputFile.exists()){ outputFile.createNewFile(); } //導(dǎo)出excel文件 ExcelUtils.exportExcel(inputStream, params, new FileOutputStream(outputFile)); } catch (IOException e) { logger.error( "excel export has error" + e); return false ; } return true ; } } |
如上,服務(wù)類提供了,三種導(dǎo)出的實(shí)現(xiàn)方法
- 導(dǎo)出excel寫入response中
- 導(dǎo)出excel寫入輸出流中
- 導(dǎo)出excel寫入文件中
這三種方法足以覆蓋所有的業(yè)務(wù)需求
5.編輯jxls模板
這里為方便導(dǎo)出最好定義與模板匹配的實(shí)體類,便于數(shù)據(jù)的裝載和導(dǎo)出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class UserModel { private Integer id; private String name; private String sex; private Integer age; private String remark; private Date date; private String link; } |
插入標(biāo)注定義模板,定義迭代對(duì)象jx:each
1
|
jx:each(items= "list" var= "item" lastCell= "G3" ) |
上面G3 模板中迭代的結(jié)束位置,然后用類似EL表達(dá)式的方式填充到模板當(dāng)中
填寫范圍jx:area
1
|
jx:area(lastCell= "G3" ) |
模板編輯完成后保存即可,
6.代碼測(cè)試使用
導(dǎo)出為本地文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@SpringBootTest class BlogJxlsApplicationTests { @Autowired ExcelService excelService; @Test void contextLoads() { Map<String, Object> params = new HashMap(); List<UserModel> list = new ArrayList<>(); list.add( new UserModel( 1 , "test01" , "男" , 25 , "tttttttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 2 , "test02" , "男" , 20 , "tttttttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 3 , "test04" , "女" , 25 , "ttttddddasdadatttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 4 , "test08" , "男" , 20 , "ttttttdasdatttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 5 , "test021" , "女" , 25 , "ttttdatttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 7 , "test041" , "男" , 25 , "ttdadatttttttt" , new Date(), "htpp://wwww.baidu.com" )); params.put( "list" , list); excelService.getExcel( "t1.xlsx" , params, new File( "D:\\test05.xlsx" )); } } |
導(dǎo)出成功
在線導(dǎo)出文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@RestController public class TestController { @Autowired ExcelService excelService; @RequestMapping ( "test" ) public void testFile(HttpServletResponse response){ Map<String, Object> params = new HashMap(); List<UserModel> list = new ArrayList<>(); list.add( new UserModel( 1 , "test01" , "男" , 25 , "tttttttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 2 , "test02" , "男" , 20 , "tttttttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 3 , "test04" , "女" , 25 , "ttttddddasdadatttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 4 , "test08" , "男" , 20 , "ttttttdasdatttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 5 , "test021" , "女" , 25 , "ttttdatttttt" , new Date(), "htpp://wwww.baidu.com" )); list.add( new UserModel( 7 , "test041" , "男" , 25 , "ttdadatttttttt" , new Date(), "htpp://wwww.baidu.com" )); params.put( "list" , list); excelService.getExcel( "t1.xlsx" ,System.currentTimeMillis()+ ".xlsx" , params,response); } } |
導(dǎo)出成功
源碼地址
https://github.com/DavidLei08/BlogJxls.git
到此這篇關(guān)于SpringBoot快速集成jxls-poi(自定義模板,支持本地文件導(dǎo)出,在線文件導(dǎo)出)的文章就介紹到這了,更多相關(guān)SpringBoot集成jxls-poi內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.csdn.net/qq_42271561/article/details/108417408