重构:以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;
    }
}
相关文章
相关标签/搜索