excel匯出工具

雲梟發表於2018-08-08

介紹

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物件)
塵心 0 2018-08-08 14:59:11 [舞刀,弄槍]
千月 1 2018-08-08 14:59:11 [唱歌,跳舞]

需要轉換為下方內容

姓名 性別 出生日期 愛好
塵心 2018-08-08 14:59:11 舞刀,弄槍
千月 2018-08-08 14:59:11 唱歌,跳舞

實體類如下

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();
}
複製程式碼

專案位置:github.com/rainbowda/u…,有需要的可以去下載。

相關文章