前言

上一篇博文已经将一些对象抽象成成员变量以及将一些代码块提炼成函数。这一节将会继续重构原有的代码,将一些函数抽象成类,增加成员变量,将传入的参数合成类等等。

上一篇博文地址:http://www.cnblogs.com/fixzd/p/8982739.html

正文

我们先来看看上一篇博文重构后的代码,还是有点长

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,但是我们能不能用什么设计模式将他们提取出来,方便以后增加类型时不必修改原有的类?
                        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、1、2、3来存储的,那么有什么好的方法可以在不修改原有代码下进行转换呢?

好了,这篇博文就围绕着上面四个问题进行重构,大家可以试着按照这几个问题对上面代码进行重构,相信经过自己思考和动手后会对代码的设计有进一步的理解。

问题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;
    }
  4. 其他调用getRowTitleStyle()和getRowDataStyle()方法的修改成调用成员变量的方法。

重构后

那么现在我们再来看看这个问题,如果我们对导出的样式有变动是不是又要修改ExportExcel类?

现在我们需要修改导出的标题样式或者数据行样式的话,我们只需要写个类继承AbstractCellStyle,然后设置字体和样式即可,是不是很方便。如果你有更好的建议在评论处留言哦


问题2:导出的主方法exportExcel参数有点多了,能不能将一些参数合并成一个类或者去除没用的参数?

原来的如下

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

现在让我们来思考思考下execl文件,一个execl文件可能有多个工作簿(也就是sheet),如下

每个工作簿(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;
}
}

这一篇修改后的github地址如下

github地址:https://github.com/rainbowda/utils/tree/master/poi/src/main/java/com/utils/poi/update_2

后续会增加其他各种各样的工具项目,觉得不错的给个star,谢谢

重构:以Java POI 导出EXCEL为例2的更多相关文章

  1. 重构:以Java POI 导出EXCEL为例

    重构 开头先抛出几个问题吧,这几个问题也是<重构:改善既有代码的设计>这本书第2章的问题. 什么是重构? 为什么要重构? 什么时候要重构? 接下来就从这几个问题出发,通过这几个问题来系统的 ...

  2. Java POI 导出EXCEL经典实现 Java导出Excel

    转自http://blog.csdn.net/evangel_z/article/details/7332535 在web开发中,有一个经典的功能,就是数据的导入导出.特别是数据的导出,在生产管理或者 ...

  3. java:POI导出excel

    POI是一个开源项目,专用于java平台上操作MS OFFICE,企业应用开发中可用它方便导出Excel. 下面是使用示例: 1.maven中先添加依赖项 <dependency> < ...

  4. Java POI 导出excel表

    1.首先下载poi-3.6-20091214.jar,下载地址如下: http://download.csdn.net/detail/evangel_z/3895051 2.Student.java ...

  5. java POI导出Excel文件数据库的数据

    在web开发中,有一个经典的功能,就是数据的导入导出.特别是数据的导出,在生产管理或者财务系统中用的非常普遍,因为这些系统经常要做一些报表打印的工作.这里我简单实现导出Excel文件. POI jar ...

  6. Java POI导出Excel不弹框选择下载路径(下载文件不选择下载路径,默认) Chrome

    在Chrome浏览器中,Java导出Excel文件时,浏览器弹出提示框,需要选择下载路径 在Chrome中的高级设置中,把“下载前询问每个文件的保存位置”去掉就解决了 DEEPLOVE(LC)

  7. JAVA POI导出EXCEL 动态表头、多级表头、动态数据

    导出Excel文件是业务中经常遇到的需求,以下是经常遇到的一些问题: 1,导出中文文件名乱码 String filename = "sheet1";response.setChar ...

  8. java poi导出EXCEL xls文件代码

    String _currentPage = request.getParameter("currentPage"); Integer currentPage = 0; if(_cu ...

  9. Java POI 导出EXCEL经典实现

    import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; i ...

随机推荐

  1. Floyd 算法求多源最短路径

    Floyd算法: Floyd算法用来找出每对顶点之间的最短距离,它对图的要求是,既可以是无向图也可以是有向图,边权可以为负,但是不能存在负环(可根据最小环的正负来判定). 基本算法: Floyd算法基 ...

  2. Zookeeper简介和安装(二)

    一.简介: Zookeeper是一个分布式协调服务,提供的服务如下: 命名服务:类似于DNS,但仅对于节点 配置管理:服务配置信息的管理 集群管理:Dubbo使用Zookeeper实现服务治理 分布式 ...

  3. Redis的Java使用入门

    因项目需要,最近简单学习了redis的使用 redis在服务器centos环境下安装比较简单. 如果要在windows上安装,可以参考别人的文章 http://blog.csdn.net/renfuf ...

  4. python中的类

    以下内容是python tutorial的读书笔记: 一.命名空间的分层 二.local赋值语句,nonlocal和global的区别 local赋值语句,它是无法实现对于最里层的作用域的重新绑定的 ...

  5. ArrayList源码分析超详细

    ArrayList源码分析超详解 想要分析下源码是件好事,但是如何去进行分析呢?以我的例子来说,我进行源码分析的过程如下几步: 找到类:利用 IDEA 找到所需要分析的类(ztrl+N查找ArraLi ...

  6. Oracle VM VirtualBox(一) 快速拷贝一个新的虚拟机

    快速拷贝一个新的虚拟机 一 找到虚拟机vdi文件,复制一份并重命名. 二 修改新虚拟机的UUID 注:不修改创建不了虚拟机,会抛出Oracle VM VirtualBox UUID already e ...

  7. 分布式缓存管理平台XXL-CACHE

    <分布式缓存管理平台XXL-CACHE> 一.简介 1.1 概述 XXL-CACHE是一个分布式缓存管理平台,其核心设计目标是"让分布式缓存的接入和管理的更加的简洁和高效&quo ...

  8. python爬虫入门(五)Selenium模拟用户操作

    爬虫(Spider),反爬虫(Anti-Spider),反反爬虫(Anti-Anti-Spider) 之间恢宏壮阔的斗争... 小莫想要某站上所有的电影,写了标准的爬虫(基于HttpClient库), ...

  9. webpack4.x版本splitChunksPlugin的配置项详解与实际应用场景

    在工程化地使用webpack时,公共代码抽离是不可或缺的,4.x版本之后,commonsChunkPlugin已经被去掉,splitChunksPlugins登上舞台,并且优化了很多配置选项,集体课件 ...

  10. Robot Framework和Selenium简介

    1.1  RF简介 Robot Framework是一款python编写的功能自动化测试框架.具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行.主要用于 ...