1. 程式人生 > >使用POI導出Excel

使用POI導出Excel

方法 += wechat 截取 賦值 .cn llc 我不 isp

先分享幾個鏈接:(POI的中文API,別人總結的拿來用特別方便)

  http://blog.csdn.net/m0_37505412/article/details/71109503

  https://www.cnblogs.com/fqfanqi/p/6172223.html

我在項目中做這個功能的時候,其實項目中是有現成代碼的,本來我以為我只需要修改一下,後來看過代碼才發現和我要的不一樣,於是只能重寫一個。

導出功能:

  1、在action層拿到要導出的數據 -- results

  2、同樣在action層拿到要導出數據的字段集,即列 -- exportFields

    解釋一下,一般我們在獲取數據的時候,往往會把一些表中的冗余字段或者一些我不需要的字段也獲取了,我們不可能也把它們導出來。其實這個字段集,就是我們在Excel表中要顯示的列。在現成的功能中支持在頁面選擇要導出的字段,而我的導出功能不支持選擇,導出的字段是寫死的。

  3、拿到導出時一張表中存多少條數據 -- rowNum

    在現成的功能中還支持這個由用戶選,就是導出到一張表,要太多條數據,然後我們根據這個值去劃分數據,比如這個值是5000,然後我們就每5000條數據新建一個工作表,再繼續存放數據。我的功能……這個值同樣寫死的。

  4、調用Service層方法,傳入上面的參數和HttpServletResponse 。傳哪些參數大家隨意,當然 results是肯定不能少的。

  5、在Service層寫方法,接受剛才的四個參數

 1     @Override
 2     public void createExcelWorkBookInfo(HttpServletResponse response, List<BaseAlumni> results, String exportFields,
3 Integer rowNum) { 4 String nowStr = new Date().getTime() + ""; 5 //這個out我還不太了解就不給你們說了,大致意思就是導出動作吧 6 OutputStream out = null; 7 try { 8 out = response.getOutputStream(); 9 response.reset(); 10 //設置表名 11 response.setHeader("content-disposition",
12 "attachment;filename=" + new String(("校友信息" + nowStr).getBytes("gb2312"), "ISO8859-1") + ".xls"); 13 response.setContentType("APPLICATION/msexcel"); 14 //創建Excel表 15 HSSFWorkbook workbook = new HSSFWorkbook(); 16 //調用導出方法 17 excelSrv.export(results, exportFields, workbook, rowNum); 18 workbook.write(out); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 } finally { 22 try { 23 // 強行將響應緩存中的內容發送到目的地 24 response.flushBuffer(); 25 if (out != null) { 26 out.flush(); 27 out.close(); 28 } 29 } catch (IOException e) { 30 LOGGER.error(e); 31 } 32 } 33 }

  5、寫export方法,在現成的方法中,封裝好了一個方法,行,列的生成都是通過foreach,很高大上。在這裏,我先附上我寫的,後面再附上現成的,給自己做一個對比。

 1     @Override
 2     public void alumniBranchExport(List<BaseAlumniBranch> results, Map<String, String> fildsMap, HSSFWorkbook wb) {
 3         //因為之前沒有傳,所以在這寫死,這個功能大家不想要也是可以的  -- rowMaxNum = 10000
 4         Integer rowNum = rowMaxNum;
 5         for (int i = 0; i < results.size(); i += rowNum) {
 6             List<BaseAlumniBranch> newlist = new ArrayList<>();
 7             if ((i + rowNum) < results.size()) {
 8                 //數據的截取
 9                 newlist = results.subList(i, i + rowNum);
10             } else {
11                 newlist = results.subList(i, results.size());
12             }
13             //創建工作表
14             HSSFSheet sheet = wb.createSheet();
15             for (int j = 0; j < fildsMap.size(); j++) {
16                 //設置列寬,第一個參數是列,第二個參數是寬值
17                 sheet.setColumnWidth(i, 5000);
18             }
19             //填充表頭
20             this.fillClubExcelHeader(wb, sheet, fildsMap);
21             //填充內容
22             this.fillClubExcelBody(newlist, sheet, wb, fildsMap);
23         }
24     }

6、其實現成的代碼和我這個是差不多一樣的,不一樣的地方就是在填充的那兩個方法裏面

  這是現成的header填充:

 1     private void fillCommonHeader(HSSFWorkbook wb, HSSFSheet sheet, Map<String, String> fildsMap) {
 2         //創建樣式
 3         HSSFCellStyle style = wb.createCellStyle();
 4         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
 5         //字體的顏色,大小
 6         HSSFFont font = wb.createFont();
 7         font.setColor(HSSFColor.BLACK.index);
 8         font.setFontHeightInPoints((short) 18);
 9         style.setFont(font);
10         //創建第一行,從0開始,參數是第幾行的索引,第一行是0
11         HSSFRow row = sheet.createRow(0);
12         //在這裏說一下,foreach是拿不到index的,這裏在外面聲明一個i,在表示第幾列
13         int i = 0;
14         //循環傳過來的字段集
15         for (String key : fildsMap.keySet()) {
16             //創建一個單元格,創建完後i自增1
17             HSSFCell cell = row.createCell(i++);
18             String value = fildsMap.get(key);
19             //給單元格賦值
20             cell.setCellValue(value);
21             //給單元格設置樣式
22             cell.setCellStyle(style);
23         }
24         //在這裏有一個順序的問題,我也是用傳參的方式,但是我的fildsMap的順序就是亂了,我又不會調,尷尬
25     }

  這是我的header填充:

 1     private void fillClubExcelHeader(HSSFWorkbook wb, HSSFSheet sheet, Map<String, String> fildsMap) {
 2         HSSFCellStyle style = wb.createCellStyle();
 3         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
 4         HSSFFont font = wb.createFont();
 5         font.setColor(HSSFColor.BLACK.index);
 6         font.setFontHeightInPoints((short) 18);
 7         style.setFont(font);
 8         // 創建第一行
 9         HSSFRow row = sheet.createRow(0);
10         // 創建第一列
11         HSSFCell cell = row.createCell(0);
12         // 賦值
13         cell.setCellValue(fildsMap.get("clubName"));
14         cell.setCellStyle(style);
15         // 創建第二列,在這裏不能再出現HSSFCell聲明,為什麽……我也是一知半解,就不說了
16         cell = row.createCell(1);
17         cell.setCellValue(fildsMap.get("clubWechatId"));
18         cell.setCellStyle(style);
19         // 創建第三列……
20         cell = row.createCell(2);
21         cell.setCellValue(fildsMap.get("clubAddress"));
22         cell.setCellStyle(style);
23         cell = row.createCell(3);
24         cell.setCellValue(fildsMap.get("clubEmail"));
25         cell.setCellStyle(style);
26         cell = row.createCell(4);
27         cell.setCellValue(fildsMap.get("clubEstablishedTime"));
28         cell.setCellStyle(style);
29         cell = row.createCell(5);
30         cell.setCellValue(fildsMap.get("name"));
31         cell.setCellStyle(style);
32         cell = row.createCell(6);
33         cell.setCellValue(fildsMap.get("staff"));
34         cell.setCellStyle(style);
35         cell = row.createCell(7);
36         cell.setCellValue(fildsMap.get("phone"));
37         cell.setCellStyle(style);
38         cell = row.createCell(8);
39         cell.setCellValue(fildsMap.get("email"));
40         cell.setCellStyle(style);
41     }

  這是現成的body填充:

 1     private <T> void fillCommonBody(List<T> results, HSSFSheet sheet, HSSFWorkbook wb, Map<String, String> fildsMap) {
 2         HSSFCellStyle style = wb.createCellStyle();
 3         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
 4         HSSFFont font = wb.createFont();
 5         font.setColor(HSSFColor.BLACK.index);
 6         font.setFontHeightInPoints((short) 16);
 7         style.setFont(font);
 8         int i = 1;
 9         for (T inst : results) {
10             HSSFRow row = sheet.createRow(i++);
11             row.setRowStyle(style);
12             int j = 0;
13             for (String key : fildsMap.keySet()) {
14                 HSSFCell cell = row.createCell(j++);
15                 String val = setCell(key, inst);  //在裏我這差點被騙了,也不知道是誰命名的,還以為單元格帶有的get,set方法
16                 cell.setCellValue(val);
17             }
18         }
19     }

  這個方法主要是寫如何從results中拿值的,我看了半天沒看懂

 1     @SuppressWarnings("rawtypes")
 2     private <T> String setCell(String field, T data) {
 3         String val = "";
 4 
 5         Class clazz = data.getClass();
 6         Field[] fields = ArrayUtils.addAll(clazz.getDeclaredFields(), clazz.getSuperclass().getDeclaredFields());
 7         for (int i = 0; i < fields.length; i++) {
 8             if (fields[i].getName().equals(field)) {
 9                 try {
10                     Object resultObject = invokeMethod(data, fields[i].getName(), null);
11                     if (resultObject == null) {
12                         resultObject = "";
13                     }
14                     val = resultObject.toString();
15                     break;
16                 } catch (SecurityException | NoSuchMethodException | IllegalArgumentException | IllegalAccessException
17                         | InvocationTargetException e) {
18                     e.printStackTrace();
19                 }
20             }
21         }
22 
23         return val;
24     }

  我的body方法:

 1     private <T> void fillClubExcelBody(List<BaseAlumniBranch> results, HSSFSheet sheet, HSSFWorkbook wb,
 2             Map<String, String> fildsMap) {
 3         HSSFCellStyle style = wb.createCellStyle();
 4         style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
 5         HSSFFont font = wb.createFont();
 6         font.setColor(HSSFColor.BLACK.index);
 7         font.setFontHeightInPoints((short) 16);
 8         style.setFont(font);
 9         int k = 1;
10         if (results.size() < 2 || "null".equals(results.size())) {
11             LOGGER.error("alumniBranchExport but results is empty !");
12             return;
13         }
14         for (int i = 0; i < results.size(); i++) {
15             BaseAlumniBranch inst = results.get(i);
16             if (inst.getStaffList().size() < 1 || "null".equals(inst.getStaffList().size())) {
17                 HSSFRow row = sheet.createRow(k++);
18                 row.setRowStyle(style);
19                 HSSFCell cell = row.createCell(0);
20                 cell.setCellValue(inst.getName());
21                 cell.setCellStyle(style);
22                 cell = row.createCell(1);
23                 cell.setCellValue(inst.getWechatId());
24                 cell.setCellStyle(style);
25                 cell = row.createCell(2);
26                 cell.setCellValue(inst.getAddress());
27                 cell.setCellStyle(style);
28                 cell = row.createCell(3);
29                 cell.setCellValue(inst.getEmail());
30                 cell.setCellStyle(style);
31                 cell = row.createCell(4);
32                 cell.setCellValue(inst.getEstablishedTime());
33                 cell.setCellStyle(style);
34                 cell = row.createCell(5);
35                 cell.setCellValue("");
36                 cell.setCellStyle(style);
37                 cell = row.createCell(6);
38                 cell.setCellValue("");
39                 cell.setCellStyle(style);
40                 cell = row.createCell(7);
41                 cell.setCellValue("");
42                 cell.setCellStyle(style);
43                 cell = row.createCell(8);
44                 cell.setCellValue("");
45                 cell.setCellStyle(style);
46             } else {
47                 for (int j = 0; j < inst.getStaffList().size(); j++) {
48                     HSSFRow row = sheet.createRow(k++);
49                     row.setRowStyle(style);
50                     HSSFCell cell = row.createCell(0);
51                     cell.setCellValue(inst.getName());
52                     cell.setCellStyle(style);
53                     cell = row.createCell(1);
54                     cell.setCellValue(inst.getWechatId());
55                     cell.setCellStyle(style);
56                     cell = row.createCell(2);
57                     cell.setCellValue(inst.getAddress());
58                     cell.setCellStyle(style);
59                     cell = row.createCell(3);
60                     cell.setCellValue(inst.getEmail());
61                     cell.setCellStyle(style);
62                     cell = row.createCell(4);
63                     cell.setCellValue(inst.getEstablishedTime());
64                     cell.setCellStyle(style);
65                     cell = row.createCell(5);
66                     cell.setCellValue(inst.getStaffList().get(j).getName());
67                     cell.setCellStyle(style);
68                     cell = row.createCell(6);
69                     cell.setCellValue(inst.getStaffList().get(j).getStaff());
70                     cell.setCellStyle(style);
71                     cell = row.createCell(7);
72                     cell.setCellValue(inst.getStaffList().get(j).getPhone());
73                     cell.setCellStyle(style);
74                     cell = row.createCell(8);
75                     cell.setCellValue(inst.getStaffList().get(j).getEmail());
76                     cell.setCellStyle(style);
77                 }
78                 for (int column = 0; column < 5; column++) {
79                     mergeCell(sheet, k - inst.getStaffList().size(), k - 1, column, column);
80                 }
81 
82             }
83         }
84     }

  7、我在方法的最後做了合並單元格,這是在原方法上改不動的,所以我必須再寫一個方法。

    傳的參數中,從左到右:工作表名,起始行,結束行,起始列,結束行

    就是要合並單元格,合並從哪行開始到哪行,從哪列開始到哪列

1     public void mergeCell(HSSFSheet sheet, int rolStart, int rolEnd, int cowStart, int cowEnd) {
2         CellRangeAddress region = new CellRangeAddress(rolStart, rolEnd, cowStart, cowEnd);
3         sheet.addMergedRegion(region);
4     }

  8、到此,導出結束。

  9、過程中碰到的坎坷:

    Excel表我聲明了兩次,導致到後來導出的內容是沒有行的,如圖:(要註意,不止是表,行,列也不能重復,否則就會出錯)

  技術分享

  10、最後的成功:

技術分享

使用POI導出Excel