1. 程式人生 > >POI 匯出列表 excel ( Java Web通用工具類 )

POI 匯出列表 excel ( Java Web通用工具類 )

最近開發一個java Web專案,需要用到POI匯出列表資料,在此記錄一下。

專案使用的是SpringBoot + maven + redis + SpringJdbcTemplate等技術實現,全程使用的是註解的方式,而不是xml配置檔案。

這裡不包含專案搭建,只是記錄一下主要的實現部分。

第一步:向maven的pom.xml檔案中新增以下依賴:

<!-- 匯出列表資料 POI-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.15</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.15</version>
</dependency>

第二步:在自己的專案工具包中寫一個匯出列表資料的工具類(ExportExcelKit.java)。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 匯出Excel工具包
 * 通用類
 * 需要Map<String, String> title, Map<String, Integer> position, List<Map<String, Object>> data,
 * String sheetName, OutputStream outputStream
 * title: 表格列頭
 * position: 表頭列的位置
 * data: 資料集合,物件資料需要轉為Map<k, v>
 * sheetName: 出資料後在excel表格中左下角顯示的工作簿名稱(注意:不是匯出後的檔名)
 * outputStream: 輸出流,通常在controller層以response.getOutputStream的形式獲取
 * 三個Map集合key值保持一致
 * @author HongYang
 * @since 2018/4/26
 */
public class ExportExcelKit {
    // 這是記錄log日誌的,沒有配的話可忽略
    public static final Logger log = LogManager.getLogger(ExcelExportException.class);

    /**
     * 匯出列表資料
     * @param title 表頭集合
     * @param position  表頭欄位位置集合
     * @param data 需要匯出的資料
     * @param sheetName 匯出資料後在excel表格中左下角顯示的工作簿名稱(注意:不是匯出後的檔名)
     * @param outputStream 從controller層通過response獲取到的輸出流
     * @throws IOException
     * @throws ExcelExportException
     */
    public static void exportDataToExcel(Map<String, String> title, Map<String, Integer> position, List<Map<String, Object>> data, String sheetName, OutputStream outputStream) throws IOException, ExcelExportException {
        if (data == null || data.size() < 1) {
            return;
        }
        try (Workbook workbook = new XSSFWorkbook()) {
            Sheet sheet = workbook.createSheet(sheetName);
            Row header = sheet.createRow(0);
            // 設定表頭樣式
            CellStyle headerStyle = workbook.createCellStyle();
            headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            // 字型樣式
            XSSFFont font = ((XSSFWorkbook) workbook).createFont();
            font.setFontName("Arial");
            font.setFontHeightInPoints((short)14);
            headerStyle.setFont(font);

            int col = 0;
            // 遍歷表頭map集合
            for (String key: title.keySet()) {
                sheet.setColumnWidth(col, 6000);
                // 設定表格頭部
                Cell headerCell = header.createCell(position.get(key));
                headerCell.setCellValue(title.get(key) + "");
                headerCell.setCellStyle(headerStyle);
                col++;
            }
            CellStyle style = workbook.createCellStyle();
            style.setWrapText(true);

            /*
             * 遍歷要匯出列表的資料data 並與title的key相比較, 確認後插入值
             * 建立列時,根據title的key然後將值插入到對應的列中(position,dataMap,title三個集合的key值是一一對應的)
             */
            if (data != null && data.size() > 0) {
                int r = 0;
                for (Map<String, Object> dataMap : data) {
                    Row row = sheet.createRow(r + 1);
                    for (String dkey : dataMap.keySet()) {
                        for (String key : title.keySet()) {
                            if (key.equals(dkey)) {
                                Cell cell = row.createCell(position.get(key));
                                cell.setCellValue(dataMap.get(dkey) + "");
                                cell.setCellStyle(style);
                                break;
                            }
                        }
                    }
                    r++;
                }
            }
            workbook.write(outputStream);
        } catch (Exception ex) {
            log.error("export data", ex);
            throw new ExcelExportException("匯出列表失敗。");
        }
    }
}

第三步:依賴匯入了,工具類也寫好了,接下來直接從控制層呼叫匯出資料的方法就OK了。

在這裡我就不連線資料庫了,先隨便寫個實體類User.java

然後在控制層新增假資料模擬匯出。

User.java:

public class User {
    private String name;
    private Integer age;
    private String gender;
    private String email;
    private String address;
    public String getName() {
      return name;
  }

  public void setName(String name) {
      this.name = name;
  }

  public Integer getAge() {
      return age;
  }

  public void setAge(Integer age) {
      this.age = age;
  }

  public String getGender() {
      return gender;
  }

  public void setGender(String gender) {
      this.gender = gender;
  }

  public String getEmail() {
      return email;
  }

  public void setEmail(String email) {
      this.email = email;
  }

  public String getAddress() {
      return address;
  }

  public void setAddress(String address) {
      this.address = address;
  }
}

實體類好了,接下來我們看一下controller。

/**
 * UserController
 */
@RestController
@RequestMapping("user")
public class UserController{
    /**
     * 匯出User列表資訊    頁面訪問路徑:"/user/export_users"
     * @param response
     * @param cycle
     * @param departmentId
     */
    @GetMapping("/export_users")
    public void exportWorkSchedules (HttpServletResponse response) throws ParseException, BeanNotFoundException, IOException {
        Map<String, String> title = new HashMap<>();    // 表頭
        List<Map<String, Object>> data = new ArrayList<>();     // 需要匯出的資料
        Map<String, Integer> position = new HashMap<>();        // 表頭欄位對應的位置(自定義位置)
        
        // 模擬從資料庫獲取資料(實則手動新增)
        List<User> uList = new ArrayList<>();
        User u1 = new User();
        u1.setName("張三");
        u1.setAge(25);
        u1.setGender("男");
        u1.setEmail("[email protected]");
        u1.setAddress("上海市浦東區");

        User u2 = new User();
        u2.setName("李四");
        u2.setAge(28);
        u2.setGender("男");
        u2.setEmail("[email protected]");
        u2.setAddress("深圳市羅湖區");

        User u3 = new User();
        u3.setName("貝爾·格里爾斯");
        u3.setAge(45);
        u3.setGender("男");
        u3.setEmail("[email protected]");
        u3.setAddress("英國特種兵1部");

        User u4 = new User();
        u4.setName("埃德");
        u4.setAge(50);
        u4.setGender("男");
        u4.setEmail("[email protected]");
        u4.setAddress("英國首府");
 
        uList.add(u1);
        uList.add(u2);
        uList.add(u3);
        uList.add(u4);

        // 設定表頭欄位位置
        position.put("name", 0);
        position.put("age", 1);
        position.put("gender", 2);
        position.put("email", 3);
        position.put("address", 4);

        // 設定表頭資訊
        title.put("name", "姓名");
        title.put("age", "年齡");
        title.put("gender", "性別");
        title.put("email", "郵箱");
        title.put("address", "地址");

        Map<String, Object> userMap = null;
        // 遍歷模擬的資料填充到userMap集合
        for (User user : uList) {
            userMap = new HashMap<>();
            userMap.put("name", user.getName());
            userMap.put("age", user.getAge());
            userMap.put("gender", user.getGender());
            userMap.put("email", user.getEmail());
            userMap.put("address", user.getAddress());
            data.add(userMap);     // 將userMap新增到List集合中
        }
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        String date = df.format(new Date());
        String excelName = "user列表" + date + ".xlsx";
        String sheetName = "使用者列表資料";
        excelName = URLEncoder.encode(excelName, "UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + excelName);
        response.setContentType("application/x-download");
        // 呼叫寫好的工具類的匯出資料方法   傳入對應的引數
        ExportExcelKit.exportDataToExcel(title, position, data, sheetName, response.getOutputStream());
    }
}

第四步:就是在前端的實現了,前端很簡單,只需要呼叫window.open(url)方法就行。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
  <div>
    <button id="export">匯出使用者資料</button>
  </div>
</body>
<script>
  window.onload = function () {
    document.getElementById('export').onclick = function () {
      let url = 'xxxxx/user/export_users'  // 對應後臺匯出列表方法的路徑
      window.open(url)
    }
  }
</script>
</html>

這就是整個匯出列表資料的方法步驟,希望能幫到你,純手寫,因為本人也是一枚菜鳥,所以請見諒,如果有不對或待優化的地方,希望大神指點,謝謝!!!


如需分享,請帶上地址,謝謝