重構:以Java POI 導出EXCEL爲例

正文

咱們先來看代碼,有點長java

public class ExportExcel<T> {
    private HSSFWorkbook workbook;
    
    public ExportExcel() {
        this(new HSSFWorkbook());
    }

    public ExportExcel(HSSFWorkbook workbook) {
        this.workbook = workbook;
    }

    public void exportExcel(Collection<T> dataset, OutputStream out) {
        exportExcel("測試POI導出EXCEL文檔", null, dataset, out, "yyyy-MM-dd");
    }

    public void exportExcel(String[] headers, Collection<T> dataset, OutputStream out) {
        exportExcel("測試POI導出EXCEL文檔", headers, dataset, out, "yyyy-MM-dd");
    }

    public void exportExcel(String[] headers, Collection<T> dataset, OutputStream out, String pattern) {
        exportExcel("測試POI導出EXCEL文檔", headers, dataset, out, pattern);
    }

    public void exportExcel(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern) {
        // 生成一個表格
        HSSFSheet sheet = workbook.createSheet(title);
        
        // 生成數據標題和數據行樣式
        HSSFCellStyle rowTirtleStyle = getRowTitleStyle();
        HSSFCellStyle rowDataStyle = getRowDataStyle();
        
        //建立數據標題和數據行
        createRowTitle(headers, sheet, rowTirtleStyle);
        createRowData(dataset, pattern, sheet, rowDataStyle);
        
        //寫入流
        writeExecl(out);
    }

    /**
     * Description:寫入到OutputStream
     */
    private void writeExecl(OutputStream out) {
        try {
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Description: 產生數據行
     */
    private void createRowData(Collection<T> dataset, String pattern, HSSFSheet sheet, HSSFCellStyle rowDataStyle) {
        // 遍歷集合數據,產生數據行
        Iterator<T> it = dataset.iterator();
        int index = 0;
        while (it.hasNext()) {
            index++;
            HSSFRow row = sheet.createRow(index);
            T t = (T) it.next();
            // 利用反射,根據javabean屬性的前後順序,動態調用getXxx()方法獲得屬性值
            Field[] fields = t.getClass().getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(rowDataStyle);
                Field field = fields[i];
                String fieldName = field.getName();
                String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                try {
                    Class tCls = t.getClass();
                    Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
                    Object value = getMethod.invoke(t, new Object[] {});
                    // 判斷值的類型後進行強制類型轉換
                    String textValue = null;
                    if (value instanceof Boolean) {
                        boolean bValue = (Boolean) value;
                        textValue = "男";
                        if (!bValue) {
                            textValue = "女";
                        }
                    } else if (value instanceof Date) {
                        Date date = (Date) value;
                        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                        textValue = sdf.format(date);
                    } else {
                        // 其它數據類型都看成字符串簡單處理
                        textValue = value.toString();
                    }
                    // 若是不是圖片數據,就利用正則表達式判斷textValue是否所有由數字組成
                    if (textValue != null) {
                        Pattern p = Pattern.compile("^//d+(//.//d+)?$");
                        Matcher matcher = p.matcher(textValue);
                        if (matcher.matches()) {
                            // 是數字看成double處理
                            cell.setCellValue(Double.parseDouble(textValue));
                        } else {
                            HSSFRichTextString richString = new HSSFRichTextString(textValue);
                            HSSFFont font3 = workbook.createFont();
                            font3.setColor(HSSFColor.BLUE.index);
                            richString.applyFont(font3);
                            cell.setCellValue(richString);
                        }
                    }
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } finally {
                    // 清理資源
                }
            }
        }
    }

    /**
     * Description: 產生表格標題行
     */
    private void createRowTitle(String[] headers, HSSFSheet sheet, HSSFCellStyle rowTirtleStyle) {
        HSSFRow row = sheet.createRow(0);
        for (int i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(rowTirtleStyle);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }
    }

    /**
     * Description:生成數據標題樣式
     */
    private HSSFCellStyle getRowTitleStyle() {
        HSSFCellStyle style = workbook.createCellStyle();
        // 設置這些樣式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        
        // 生成一個字體
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        
        // 把字體應用到當前的樣式
        style.setFont(font);
        
        return style;
    }
    
    /**
     * Description:生成數據行樣式
     */
    private HSSFCellStyle getRowDataStyle() {
        HSSFCellStyle style = workbook.createCellStyle();
        // 設置這些樣式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        
        // 生成另外一個字體
        HSSFFont font = workbook.createFont();
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        
        style.setFont(font);
                
        return style;
    }

}

那麼接下來咱們要如何重構呢?咱們從問題的角度來重構吧正則表達式

1. 在上面代碼中咱們能夠看到有兩個建立樣式的函數,這兩個函數getRowTitleStyle()和getRowDataStyle()能夠說是導出execl的默認樣式。在這裏咱們思考下,若是咱們對導出的樣式有變更是否是又要修改ExportExcel類?數據庫

/**
     * Description:生成數據標題樣式
     */
    private HSSFCellStyle getRowTitleStyle() {
        HSSFCellStyle style = workbook.createCellStyle();
        // 設置這些樣式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        
        // 生成一個字體
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        
        // 把字體應用到當前的樣式
        style.setFont(font);
        
        return style;
    }
    
    /**
     * Description:生成數據行樣式
     */
    private HSSFCellStyle getRowDataStyle() {
        HSSFCellStyle style = workbook.createCellStyle();
        // 設置這些樣式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        
        // 生成另外一個字體
        HSSFFont font = workbook.createFont();
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        
        style.setFont(font);
                
        return style;
    }

2. 接下來咱們看看導出的主方法exportExcel(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern)。有沒有以爲參數有點多了,能不能將一些參數合併成一個類或者去除沒用的參數?設計模式

3. 咱們再來看看產生數據行函數createRowData的數據處理方式,以下。雖然這裏只有兩個if...else,可是咱們能不能用什麼設計模式將他們提取出來,方便之後增長類型時沒必要修改原有的類?app

if (value instanceof Boolean) {
                        boolean bValue = (Boolean) value;
                        textValue = "男";
                        if (!bValue) {
                            textValue = "女";
                        }
                    } else if (value instanceof Date) {
                        Date date = (Date) value;
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        textValue = sdf.format(date);
                    } else {
                        // 其它數據類型都看成字符串簡單處理
                        textValue = value.toString();
                    }

4. 咱們在思考下第三個問題,數據的轉換不只僅只有上面那麼循序漸進的,就比如一輛車的狀態有正常,損壞、維修中、報廢等等,可是在數據庫中是以0、一、二、3來存儲的,那麼有什麼好的方法能夠在不修改原有代碼下進行轉換呢?ide

好了,這篇博文就圍繞着上面四個問題進行重構,你們能夠試着按照這幾個問題對上面代碼進行重構,相信通過本身思考和動手後會對代碼的設計有進一步的理解。函數

問題1:若是咱們對導出的樣式有變更是否是又要修改ExportExcel類?

針對上面問題,咱們是否是能夠將樣式建立抽象成類?工具

/**
     * Description:生成數據標題樣式
     */
    private HSSFCellStyle getRowTitleStyle() {
        HSSFCellStyle style = workbook.createCellStyle();
        // 設置這些樣式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        
        // 生成一個字體
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        
        // 把字體應用到當前的樣式
        style.setFont(font);
        
        return style;
    }

從上面代碼能夠置頂HSSFCellStyle的建立須要用到Workbook對象,因此接口就不適用。測試

而後上面代碼中能夠看出一個總體的樣式還包含了字體,那麼就能夠設計一個抽象類,以下字體

public abstract class AbstractCellStyle {
    HSSFWorkbook workbook;
    HSSFCellStyle style;
    HSSFFont font;

    public AbstractCellStyle(HSSFWorkbook workbook) {
        this.workbook = workbook;
        style = workbook.createCellStyle();
        font = workbook.createFont();
    }
    
    public abstract void setStyle();
    
    public abstract void setFont();

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

該抽象類AbstractCellStyle有一個有參構造函數、三個成員變量、一個得到樣式的方法和兩個抽象方法setStyle和setFont。

子類經過繼承AbstractCellStyle,而後重寫方法setStyle和setFont便可。

構造函數須要傳入Workbook,而後在構造函數裏建立樣式和字體對象,最後調用getCellStyle方法得到HSSFCellStyle便可。

我這裏弄了兩個默認的樣式了,以下

默認數據行樣式類

DefaultDataCellStyle.java

public class DefaultDataCellStyle extends AbstractCellStyle{
    public DefaultDataCellStyle(HSSFWorkbook workbook) {
        super(workbook);
    }

    @Override
    public void setStyle() {
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
    }
    @Override
    public void setFont() {
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
    }

}

默認一個數據標題樣式,

DefaultTitleCellStyle.java

public class DefaultTitleCellStyle extends AbstractCellStyle{
    public DefaultTitleCellStyle(HSSFWorkbook workbook) {
        super(workbook);
    }

    @Override
    public void setStyle() {
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    }
    @Override
    public void setFont() {
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
    }
}

而後ExportExcel這個類也須要作出相應的修改,修改內容以下

1. 刪除兩個函數getRowTitleStyle()和getRowDataStyle()

2. 增長兩個成員變量,且將Workbook也抽象成成員變量

private HSSFWorkbook workbook;
    private AbstractCellStyle titleCellStyle;//標題行樣式
    private AbstractCellStyle dataCellStyle;//數據行樣式

3. 修改構造函數,以下

public ExportExcel() {
        this(new HSSFWorkbook());
    }

    /**
     * 這裏能夠定義兩個常量,可是這裏須要workbook,因此就沒有抽取出來
     * @param workbook
     */
    public ExportExcel(HSSFWorkbook workbook) {
        this(workbook,new DefaultTitleCellStyle(workbook),new DefaultDataCellStyle(workbook));
    }

    public ExportExcel(HSSFWorkbook workbook, AbstractCellStyle titleCellStyle, AbstractCellStyle dataCellStyle) {
        this.workbook = workbook;
        this.titleCellStyle = titleCellStyle;
        this.dataCellStyle = dataCellStyle;
    }

2. 其餘調用getRowTitleStyle()和getRowDataStyle()方法的修改爲調用成員變量的方法。

重構後

那麼如今咱們再來看看這個問題,若是咱們對導出的樣式有變更是否是又要修改ExportExcel類?

如今咱們須要修改導出的標題樣式或者數據行樣式的話,咱們只須要寫個類繼承AbstractCellStyle,而後設置字體和樣式便可,是否是很方便。若是你有更好的建議在評論處留言哦

問題2:導出的主方法exportExcel參數有點多了,能不能將一些參數合併成一個類或者去除沒用的參數?

 原來的以下

public void exportExcel(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern) {...}

每一個工做簿(sheet)都有本身的表格,每一個表格都有本身的行和列

在咱們處處這裏是以每一行對應數據庫中一張表的一條記錄,每一列就比如數據庫中的一張表的一個屬性。

如今咱們現將每一列抽象成一個類,每一列中包含一個標題和數據所對應的實體屬性,例如,學號是標題,學號在實體Student中對應的屬性是id

抽象出來的類以下

public class CellEntity {
    private String title;
    private String filedName;
    
    //set get方法...
}

接下來咱們把每一個工做簿(sheet)也抽象成一個類,這個類中包含多個列(CellEntity)、工做簿名稱(sheetName)、數據集合。

public class SheetEntity {
    private String sheetName;

    private List<CellEntity> cellEntitys;

    private Collection dataset;

    //set get方法  
}

最後修改導出的主方法exportExcel和其餘一些參數的獲取

public void exportExcel(SheetEntity sheetEntity, OutputStream out) {...}

問題3:函數createRowData的數據處理能不能用什麼設計模式將他們提取出來,方便之後增長類型時沒必要修改原有的類?

String textValue = null;
    if (value instanceof Boolean) {
        boolean bValue = (Boolean) value;
        textValue = "男";
        if (!bValue) {
            textValue = "女";
        }
    } else if (value instanceof Date) {
        Date date = (Date) value;
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        textValue = sdf.format(date);
    } else {
        // 其它數據類型都看成字符串簡單處理
        textValue = value.toString();
    }

從上面代碼中能夠看出value被判斷是哪一種類型,而後再進行賦值操做,顯示被判斷是不是Boolean,而後判斷Date,最後都被當成字符串處理。

這裏博主採用的是以下方法,將數據轉換抽象成一個抽象類,以下

public abstract class AbstractDataHandler {
    private AbstractDataHandler abstractDataHandler;

    public AbstractDataHandler(AbstractDataHandler abstractDataHandler) {
        this.abstractDataHandler = abstractDataHandler;
    }

    public abstract String dataHandle(Object value);

    protected String nextHandle(Object value) {
        if (abstractDataHandler != null) {
            return abstractDataHandler.dataHandle(value);
        }
        return null;
    }
}

 

子類經過集成該抽象類,實現dataHandle方法,若是是當前類型,則處理後返回,不然調用抽象類AbstractDataHandler的nextHandle方法繼續調用下個數據處理方法。如今來看看我寫的幾個數據處理類

Boolean數據處理

public class BooleanDataHandler extends AbstractDataHandler {

    public BooleanDataHandler(AbstractDataHandler abstractDataHandler) {
        super(abstractDataHandler);
    }

    @Override
    public String dataHandle(Object value) {
        if (value instanceof Boolean) {
            boolean bValue = (Boolean) value;
            String textValue = "是";
            if (!bValue) {
                textValue = "否";
            }
            return textValue;
        } else {
            return nextHandle(value);
        }
    }

}

Date數據處理

public class DateDataHandler extends AbstractDataHandler {
    
    public DateDataHandler(AbstractDataHandler abstractDataHandler) {
        super(abstractDataHandler);
    }

    @Override
    public String dataHandle(Object value) {
        if (value instanceof Date) {
            Date date = (Date) value;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.format(date);
        } else {
            return nextHandle(value);
        }
    }

}

String數據處理

public class StringDataHandler extends AbstractDataHandler {

    public StringDataHandler(AbstractDataHandler abstractDataHandler) {
        super(abstractDataHandler);
    }

    @Override
    public String dataHandle(Object value) {
        return value.toString();
    }

}

而後建立一個工廠類DataHandlerFactory,工具類調用這個工廠類的dataHandle方法,數據處理就會按照Boolean-->Date-->String流程走下去,都沒有處理就返回null

public class DataHandlerFactory {

    private static AbstractDataHandler dataHandler = new BooleanDataHandler(
            new DateDataHandler(
                    new StringDataHandler(null)));

    public static String dataHandle(Object value) {
        return dataHandler.dataHandle(value);
    }
}

修改後的代碼以下,是否是簡便了許多

       

 -------------->     

 

如今若是須要增長默認的類型處理,只須要增長AbstractDataHandler的子類,而後修改DataHandlerFactory工廠類便可。

問題4:數據的轉換並非按照預期進行的那麼有什麼好的方法能夠在不修改原有代碼下進行轉換呢?

關於這個問題,咱們須要增長一個轉換接口,而後將數據轉換交給子類來實現便可。其實在實體類CellEntity增長一個類型轉換的成員變量便可。接口以下

public interface DataConversion {
    String transferData(Object data);
}

實體類CellEntity也須要作相應的修改,增長一個成員變量便可

public class CellEntity {
    private String title;
    private String fieldName;
    private DataConversion conversion;
    ......
}

而後處處工具類中也要作修改,由原先交給工廠處理的修改成判斷cellEntity對象的成員變量conversion是否爲null,爲null則交給默認的數據處理類處理,不爲null則交給conversion處理

if (cellEntity.getConversion() == null)
        textValue = DataHandlerFactory.dataHandle(value);
    else
        textValue = cellEntity.getConversion().transferData(value);

就按上面車輛狀態來舉個相應的例子吧,判斷傳入的類型是否爲0或者1,0返回正常,1返回異常,其餘的都返回null,以下

public class CarStatusExportConversion implements DataExportConversion {

    @Override
    public String transferData(Object data) {
        if (data == null) return null;
        Integer carStatus = (Integer) data;
        switch (carStatus){
            case 0:
                return "正常";
            case 1:
                return "異常";
        }
        return null;
    }
}

完整的工具類和測試代碼

ExportExecl工具類

public class ExportExcel<T> {
    private HSSFWorkbook workbook;
    private AbstractCellStyle titleCellStyle;//標題行樣式
    private AbstractCellStyle dataCellStyle;//數據行樣式

    public ExportExcel() {
        this(new HSSFWorkbook());
    }

    /**
     * 這裏能夠定義兩個常量,可是這裏須要workbook,因此就沒有抽取出來
     * @param workbook
     */
    public ExportExcel(HSSFWorkbook workbook) {
        this(workbook,new DefaultTitleCellStyle(workbook),new DefaultDataCellStyle(workbook));
    }

    public ExportExcel(HSSFWorkbook workbook, AbstractCellStyle titleCellStyle, AbstractCellStyle dataCellStyle) {
        this.workbook = workbook;
        this.titleCellStyle = titleCellStyle;
        this.dataCellStyle = dataCellStyle;
    }

    public void exportExcel(SheetEntity sheetEntity, OutputStream out) {
        // 生成一個表格
        HSSFSheet sheet = workbook.createSheet(sheetEntity.getSheetName());
        // 生成數據標題和數據行樣式
        HSSFCellStyle rowTirtleStyle = titleCellStyle.getCellStyle();
        HSSFCellStyle rowDataStyle = dataCellStyle.getCellStyle();
        
        //建立數據標題和數據行
        createRowTitle(sheetEntity.getCellEntitys(), sheet, rowTirtleStyle);
        createRowData(sheetEntity.getCellEntitys(),sheetEntity.getDataset(), sheet, rowDataStyle);
        
        //寫入流
        writeExecl(out);
    }

    /**
     * Description:寫入到OutputStream
     */
    private void writeExecl(OutputStream out) {
        try {
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Description: 產生數據行
     */
    private void createRowData(List<CellEntity> cellEntitys, Collection<T> dataset, HSSFSheet sheet, HSSFCellStyle rowDataStyle) {
        // 遍歷集合數據,產生數據行
        Iterator<T> it = dataset.iterator();
        int index = 0;
        while (it.hasNext()) {
            index++;
            HSSFRow row = sheet.createRow(index);
            T t = (T) it.next();
            for (int i = 0; i < cellEntitys.size(); i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(rowDataStyle);
                try {
                    String textValue = null;

                    CellEntity cellEntity = cellEntitys.get(i);
                    Object value = PropertyUtils.getProperty(t, cellEntity.getFiledName());

                    if (cellEntity.getConversion() == null)
                        textValue = DataHandlerFactory.dataHandle(value);
                    else
                        textValue = cellEntity.getConversion().transferData(value);

                    cell.setCellValue(textValue);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Description: 產生表格標題行
     */
    private void createRowTitle(List<CellEntity> cellEntitys, HSSFSheet sheet, HSSFCellStyle rowTirtleStyle) {
        HSSFRow row = sheet.createRow(0);
        for (int i = 0; i < cellEntitys.size(); i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(rowTirtleStyle);
            HSSFRichTextString text = new HSSFRichTextString(cellEntitys.get(i).getTitle());
            cell.setCellValue(text);
        }
    }

}

Test導出測試類

public class Test {

    public static void main(String[] args) {
        // 測試學生
        ExportExcel<Student> ex = new ExportExcel<Student>();
        // 測試圖書
        ExportExcel<Book> ex2 = new ExportExcel<Book>();

        List<Student> studentList = getStudentList();

        try {


            OutputStream out = new FileOutputStream("E://a.xls");

            ex.exportExcel(getStudentSheetEntity("學生",studentList), out);

            out.close();
            System.out.println("excel導出成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static SheetEntity getStudentSheetEntity(String sheetName,List<Student> studentList){

        List<CellEntity> cellEntitys = new ArrayList<CellEntity>();
        cellEntitys.add(new CellEntity("學號","id"));
        cellEntitys.add(new CellEntity("姓名","name"));
        cellEntitys.add(new CellEntity("年齡","age"));
        cellEntitys.add(new CellEntity("性別","sex", new SexDataConversion()));
        cellEntitys.add(new CellEntity("出生日期","birthday"));

        SheetEntity entity = new SheetEntity(sheetName,cellEntitys , studentList);

        return entity;
    }

    private static List<Student> getStudentList() {
        List<Student> datas = new ArrayList<Student>();
        datas.add(new Student(10000001, "張三", 20, true, new Date()));
        datas.add(new Student(20000002, "李四", 24, false, new Date()));
        datas.add(new Student(30000003, "王五", 22, true, new Date()));
        return datas;
    }

}

class SexDataConversion implements DataConversion{

    @Override
    public String transferData(Object data) {
        if (data instanceof Boolean) {
            boolean bValue = (Boolean) data;
            String textValue = "男";
            if (!bValue) {
                textValue = "女";
            }
            return textValue;
        }
        return null;
    }
}
相關文章
相關標籤/搜索