天天看點

excel導出工具

介紹

excel導出工具

整個項目的代碼結構如下

com
\---utils
    +---demo # 案例相關
    |   |   ExcelExportApplication.java # springboot啟動類
    |   |
    |   +---bean
    |   |       DemoBean.java # 測試bean
    |   |
    |   +---controller
    |   |       ExcelExportController.java # 測試url通路彈出下載下傳excel檔案和導出excel到檔案
    |   |
    |   \---exportParam
    |       |   DemoExportParam.java # 導出參數
    |       |
    |       \---dataConversion
    |               HobbyConversion.java # 愛好屬性導出轉換類
    |               SexConversion.java # 性别屬性導出轉換類
    |
    \---excelExport # 導出工具包
        |   AsyncExportExcel.java #多線程導出
        |   ExportExcel.java # 導出工具類
        |
        +---data
        |       BaseParam.java # 基礎導出參數類
        |
        +---dataConversion
        |       DataExportConversion.java # 屬性導出轉換接口
        |
        +---defaultDataHandle # 預設的資料處理
        |       AbstractDataHandler.java
        |       BooleanDataHandler.java
        |       DataHandlerFactory.java
        |       DateDataHandler.java
        |       StringDataHandler.java
        |
        \---style # 預設的樣式
                AbstractCellStyle.java
                DefaultDataCellStyle.java
                DefaultTitleCellStyle.java           

簡單的來說excel導出可以分為幾步

  1. 獲得需要導出的資料
  2. 設定excel的工作表(sheet)名稱
  3. 設定目前工作表的第一行,也就是标題行
  4. 将資料逐行填充,有需要的資料進行轉換

使用

ExportExcel工具類

首先執行個體化ExportExcel工具類,我這裡提供了三個構造函數

public ExportExcel() 

public ExportExcel(SXSSFWorkbook workbook) 

public ExportExcel(SXSSFWorkbook workbook, AbstractCellStyle titleCellStyle, AbstractCellStyle dataCellStyle)            

通常使用的是無參構造函數。另外兩個都需要自己執行個體化workbook對象,有三個參數的構造函數,需要傳入workbook、标題行樣式對象、資料行樣式對象。關于樣式對象下方有說明。

執行個體化ExportExcel工具類之後,需要調用exportExcel方法,方法定義如下

public void exportExcel(String sheetName, BaseParam baseParam, OutputStream out)           
參數名稱 參數内容
sheetName 工作表(sheet)的名稱
baseParam 繼承BaseParam的導出參數對象(後面會說明)
out OutputStream對象、例如FileOutputStream

樣式抽象類AbstractCellStyle

public abstract class AbstractCellStyle {
    Workbook workbook;
    CellStyle style;
    Font font;

    public AbstractCellStyle(Workbook workbook) {
        this.workbook = workbook;
        style = workbook.createCellStyle();
        font = workbook.createFont();
    }

    protected abstract void setStyle();

    protected abstract void setFont();


    public CellStyle getCellStyle() {
        style.setFont(font);
        return style;
    }
}           

通過繼承樣式抽象類AbstractCellStyle,可以實作下方兩個方法

// 設定樣式
protected abstract void setStyle();
// 設定字型
protected abstract void setFont();           

通過這兩個方法可以修改單元格的樣式和字型。

基礎導出參數類BaseParam

BaseParam類代碼如下

public class BaseParam {
    public List data = new ArrayList<>();
    public List<ColumnParam> columnParams = new ArrayList<>();
    
    //Set Get Constructor

    /**
     * 資料行參數
     */
    public class ColumnParam{```}
}           

屬性

可以看到BaseParam類有兩個屬性

public List data = new ArrayList<>();
public List<ColumnParam> columnParams = new ArrayList<>();           

data毫無疑問是存放需要導出的資料,而columnParams是存放每一列的資料,現在來看看内部類ColumnParam

内部類ColumnParam

public class ColumnParam{
        private String headerName;
        private String fieldName;
        private DataExportConversion conversion;//資料轉換
        
        //Set Get Constructor
    }           
屬性名稱 屬性内容
headerName 标題名稱
fieldName 實體類對應的屬性名
conversion 資料轉換對象
資料轉換接口DataExportConversion
public interface DataExportConversion<T> {
    String transferData(T data);
}           

比如說,擷取出來的資料是0、1,然後你需要将資料轉換成女、男,那麼就可以實作資料轉換接口DataExportConversion,自定義轉換輸出的格式,代碼如下

public class SexConversion implements DataExportConversion<Integer> {
    @Override
    public String transferData(Integer data) {
        if (0 == data){
            return "女";
        } else if (1 == data){
            return "男";
        }
        return "不詳";
    }
}           

案例

場景

原始資料如下

姓名 性别 出生日期 愛好(List對象)
塵心 2018-08-08 14:59:11 [舞刀,弄槍]
千月 1 [唱歌,跳舞]

需要轉換為下方内容

愛好
舞刀,弄槍
唱歌,跳舞

實體類如下

public class DemoBean {

    //姓名
    private String name;

    //性别,0->女,1->男
    private Integer sex;

    //出生日期
    private Date birthday;

    //愛好
    private List<String> hobbies;

    //Set Get
    
}           

資料轉換

可以看到有兩個屬性需要轉換,分别是性别和愛好。性别的資料轉換上面已經有了,就不貼出來了,下面是愛好的資料轉換

public class HobbyConversion implements DataExportConversion<List<String>> {
    @Override
    public String transferData(List<String> data) {
        StringBuilder hobby = new StringBuilder();

        for (String s:data){
            hobby.append(s).append(",");
        }

        //移除最後一個逗号
        if (hobby.length() >= 1){
            hobby.deleteCharAt(hobby.length()-1);
        }

        return hobby.toString();
    }
}           

導出參數類

資料轉換類寫好了之後,開始編寫導出參數類,代碼如下

public class DemoExportParam extends BaseParam {
    public DemoExportParam(List<DemoBean> list) {
        setData(list);
        setColumnParam();
    }

    private void setColumnParam() {
        columnParams.add(new ColumnParam("姓名","name"));
        columnParams.add(new ColumnParam("性别","sex", new SexConversion()));
        columnParams.add(new ColumnParam("出生日期","birthday"));
        columnParams.add(new ColumnParam("愛好","hobbies", new HobbyConversion()));
    }
}           

在執行個體化DemoExportParam時,需要傳入導出的資料,同時設定每一列對應的列參數ColumnParam。

可以看到總共有4個列參數

  • 第一列标題名稱為姓名,對應的屬性名稱為name
  • 第二列标題名稱為性别,對應的屬性名稱為sex,還有資料轉換對象SexConversion
  • 第三列标題名稱為出生日期,對應的屬性名稱為birthday
  • 第四列标題名稱為愛好,對應的屬性名稱為hobbies,資料轉換對象HobbyConversion

導出

先寫一個生成資料的方法,如下

private List<DemoBean> getDemoBeanList(){
    DemoBean man = new DemoBean();
    DemoBean woman = new DemoBean();

    String[] manHobbys = {"舞刀", "弄槍"};
    String[] womanHobbys = {"唱歌", "跳舞"};

    man.setName("塵心").setBirthday(new Date()).setSex(0).setHobbies(Arrays.asList(manHobbys));
    woman.setName("千月").setBirthday(new Date()).setSex(1).setHobbies(Arrays.asList(womanHobbys));


    //将兩個bean添加到list中
    List<DemoBean> list = new ArrayList<>();
    list.add(man);
    list.add(woman);

    return list;
}           

接下來有兩種資料導出方式,一種是url通路彈出下載下傳excel檔案,另外一種是導出excel到檔案

url通路彈出下載下傳excel檔案

@ResponseBody
@RequestMapping("/export")
public void exportByWeb(HttpServletResponse response) throws IOException {

    OutputStream out = new BufferedOutputStream(response.getOutputStream());

    response.reset();
    String headStr = "attachment; filename=" + URLEncoder.encode("導出demo.xlsx", "utf-8");
    response.setContentType("application/vnd.ms-excel;charset=UTF-8");
    response.setHeader("Content-Disposition", headStr);

    //獲得導出資料
    List<DemoBean> list = getDemoBeanList();

    DemoExportParam demoExportParam = new DemoExportParam(list);

    ExportExcel exportExcel = new ExportExcel();
    exportExcel.exportExcel("demo", demoExportParam, response.getOutputStream());

    out.flush();
    out.close();
}           

導出excel到檔案

@Test
public void exportByFile() throws IOException {

    File file = new File("F:\\導出demo.xlsx");
    FileOutputStream out = new FileOutputStream(file);

    //獲得導出資料
    List<DemoBean> list = getDemoBeanList();

    DemoExportParam demoExportParam = new DemoExportParam(list);

    ExportExcel exportExcel = new ExportExcel();
    exportExcel.exportExcel("demo", demoExportParam, out);

    out.flush();
    out.close();
}           

項目位置:

https://github.com/rainbowda/utils/tree/master/excel_export

,有需要的可以去下載下傳。