jexcelapi写excel文件的抽象类(一)

原创 2007年09月24日 14:21:00

开发过程中,需要把数据导出到excel中,用jxl_2_6_4.jar包实现java对excel的操作。

下面介绍两种方法写excel文件,一个是sheet模板,填入数据;一个是row模板,然后填入excel。

利用模板操作excel比较方便,可以用excel设置好所需要的单元格格式,然后读入按照业务规则填写,实现所有的excel格式设置,而不用研究jxl的api,是一种偷懒的做法。

我的项目中,报表全部是生成excel文件输出。

首先,建立一个excel报表接口

/**
 * 报表生成器
 * @author zhengmw
 *
 */
public interface IReportMaker {

 /**
  * 输出报表
  * @return 报表文件路径,让调用者直接打开文件,可能生成多个文件
  * @throws GeneException 自定义异常
  */
 public List<String> report() throws GeneException;
}

然后实现一个excel报表的抽象类

/**
 * EXCEL报表基类
 *
 * @author zhengmw
 *
 */
public abstract class AbstractExcelReportMaker implements IReportMaker {
 /**
  * 模板文件名, 构造函数传入
  */
 private String fileName;

 /**
  * 每页行数, 构造函数传入
  */
 private int iRowAmt;

 /**
  * 当前行
  */
 private int iRow = 0;

 /**
  * 报表页数
  */
 private int iPageAmt = 0;

 /**
  * 报表数据, 构造函数传入
  */
 protected List data;

 /**
  * 报表列表,保存报表的文件路径
  */
 private List<String> reports = new ArrayList<String>();

 /**
  * 输出默认地址
  */
 private final String default_report_path =  "report_bak/";

 /**
  * 工作簿
  */
 private WritableSheet ws;

 /**
  * @param data
  *            报表数据
  * @param fileName
  *            模板文件名
  * @param iRowAmt
  *            每页行数
  */
 public AbstractExcelReportMaker(List data, String fileName, int iRowAmt) {
  this.data = data;
  this.fileName = fileName;
  this.iRowAmt = iRowAmt;
 }

 /**
  * 报表输出路径
  *
  * @return
  */
 protected String getReportOutputDirectory() {
  return "";
 }

 /**
  * 获取模板文件
  *
  * @return
  */
 protected File getSourceFile() {
  return new File(PluginUtil.getFullPath(DrawbackPlugin.PLUGIN_ID, "report/") + fileName);
 }

 /**
  * 获取生成报表文件
  *
  * @return
  */
 protected File getReportFileUrl() {
  return new File(getReportOutputDirectory() + getOutputFileName());
 }

 /**
  * 获取报表文件名
  *
  * @return
  */
 private String getOutputFileName() {
  return fileName.substring(0, fileName.length() - 4) + iPageAmt + ".xls";
 }

 /**
  * 取字符CELL,用于替换数字类型的CELL
  *
  * @return
  */
 protected abstract Label getLabelCell(WritableSheet ws);

 /**
  * 给单元格赋值
  *
  * @param wc
  * @param value
  * @throws GeneException
  */
 protected void setLableValue(Cell wc, Object value) throws GeneException {
  try {
   // 判断单元格的类型, 做出相应的转化
   if (wc.getType() == CellType.LABEL) {
    setCellValue(wc, value);
   } else if (wc.getType() == CellType.DATE) {
    if (value == null) {
     WritableCell c = getLabelCell(ws).copyTo(wc.getColumn(), wc.getRow());
     setCellValue(c, value);
     ws.addCell(c);
    } else {
     setCellValue(wc, value);
    }
   } else if (wc.getType() == CellType.NUMBER) {
    if (value == null) {
     WritableCell c = getLabelCell(ws).copyTo(wc.getColumn(), wc.getRow());
     setCellValue(c, value);
     ws.addCell(c);
    } else {
     setCellValue(wc, value);
    }
   }
  } catch (GeneException e) {
   throw e;
  } catch (Exception e) {
   throw GeneException.getGeneException(ERR.ERROR_ERR_MSG, "数据类型不匹配");
  }
 }

 private void setCellValue(Cell wc, Object value) throws GeneException {
  try {
   // 判断单元格的类型, 做出相应的转化
   if (wc.getType() == CellType.LABEL) {
    ((Label) wc).setString((String) value);
   } else if (wc.getType() == CellType.DATE) {
    ((DateTime) wc).setDate((Date) value);
   } else if (wc.getType() == CellType.NUMBER) {
    if (value instanceof Integer) {
     ((jxl.write.Number) wc).setValue(((Integer) value).doubleValue());
    } else if (value instanceof BigDecimal) {
     ((jxl.write.Number) wc).setValue(Double.parseDouble(StringUtility
       .strNull((BigDecimal) value)));
    }
   }
  } catch (Exception e) {
   throw GeneException.getGeneException(ERR.ERROR_ERR_MSG, "数据类型不匹配");
  }
 }

 /**
  * 设置拷贝cell的值,一般应用与无限制行的模板
  *
  * @param cell
  * @param col
  * @param row
  * @param value
  * @throws GeneException
  */
 protected void setCopyCellValue(WritableCell cell, int col, int row, Object value)
   throws GeneException {
  WritableCell wc = cell.copyTo(col, row);
  setCellValue(wc, value);
  try {
   ws.addCell(wc);
  } catch (Exception e) {
   throw GeneException.getGeneException(ERR.ERROR_ERR_MSG, "EXCEL数据操作失败");
  }
 }

 /**
  * 生成报表头部
  *
  * @param ws
  */
 protected abstract void reportHeadMaker(WritableSheet ws) throws GeneException;

 /**
  * 生成报表内容
  *
  * @param ws
  * @param i
  *            从0行开始
  */
 protected abstract void reportContentMaker(WritableSheet ws, Object obj, int iRow)
   throws GeneException;

 /**
  * 生成报表底部
  *
  * @param ws
  */
 protected abstract void reportBottomMaker(WritableSheet ws) throws GeneException;

 /**
  * 清除报表模板内容
  *
  * @param ws
  * @param i
  */
 protected abstract void clearReport(WritableSheet ws, int i) throws GeneException;

 /**
  * 每页生成报表小计
  *
  * @param ws
  * @throws GeneException
  */
 protected abstract void reportSubtotalMaker(WritableSheet ws) throws GeneException;

 /**
  * 最后一页生成报表总计
  *
  * @param ws
  * @throws GeneException
  */
 protected abstract void reportTotalizeMaker(WritableSheet ws) throws GeneException;

 /**
  * 对数据进行额外处理
  */
 protected void reportDataProcessor() {
  // do nothing
 }

 /**
  * 是否新页面
  *
  * @return
  */
 protected boolean isNewPage() {
  return iRow % iRowAmt == 0;
 }

 /**
  * 拷贝报表模板到指定路径
  *
  * @throws GeneException
  */
 protected void copyFileToDirectory() throws GeneException {
  try {
   FileUtils.copyFile(getSourceFile(), getReportFileUrl(), false);
  } catch (IOException e) {
   throw GeneException.getGeneException(ERR.FW_IO_FILE_ERR);
  }
 }

 /**
  * 生成报表
  *
  * @throws GeneException
  */
 protected void reportMaker() throws GeneException {
  reportDataProcessor();
  if (data == null || data.size() < 1) {
   throw GeneException.getGeneException(ERR.ERROR_INFO_MSG, "没有找到数据!");
  }
  Workbook rwb = null;
  WritableWorkbook wwb = null;
  try {
   for (int i = 0; i < data.size(); i++) {
    if (isNewPage()) {
     // 关闭原来的工作簿
     if (wwb != null) {
      reportSubtotalMaker(ws);
      wwb.write();
      wwb.close();
      rwb.close();
     }
     // 填写报表
     rwb = Workbook.getWorkbook(this.getSourceFile());
     // 页面加1
     iPageAmt++;
     // 行重置为0
     iRow = 0;
     // 加入报表列表
     reports.add(getReportFileUrl().getPath());
     // copyFileToDirectory();
     // 利用已经创建的Excel工作薄创建新的可写入的Excel工作薄
     wwb = Workbook.createWorkbook(this.getReportFileUrl(), rwb);
     // 读取第一张工作表
     ws = wwb.getSheet(0);
     reportHeadMaker(ws);
     reportBottomMaker(ws);
    }
    reportContentMaker(ws, data.get(i), iRow);
    // 行加1
    iRow++;
   }
   // 清空剩余行内容
   int iClear = data.size() % iRowAmt;
   iClear = iClear == 0 || iRowAmt == Integer.MAX_VALUE ? 0 : iRowAmt - iClear;
   for (int i = 0; i < iClear; i++) {
    clearReport(ws, iRow + i);
   }
   // 生成报表总计
   reportTotalizeMaker(ws);
   // 写入Excel对象
   wwb.write();
  } catch (GeneException e) {
   throw e;
  } catch (IOException e) {
   throw GeneException.getGeneException(ERR.FW_IO_FILE_ERR);
  } catch (Exception e) {
   throw GeneException.getGeneException(ERR.ERROR_ERR_MSG, new String[] { "报表生成意外终止" }, e);
  } finally {
   // 操作完成时,关闭对象,释放占用的内存空间
   if (wwb != null) {
    try {
     wwb.close();
    } catch (Exception e) {
     throw GeneException.getGeneException(ERR.FW_IO_FILE_ERR);
    }
   }
   if (rwb != null) {
    rwb.close();
   }
  }

 }

 /*
  * (non-Javadoc)
  *
  * @see com.jl.drawback.business.entity.IReportMaker#report()
  */
 public List<String> report() throws GeneException {
  // 生成报表
  reportMaker();
  // 返回报表文件路径
  return reports;

 }

 /**
  * 当前报表页数
  *
  * @return
  */
 protected int getPageAmt() {
  return iPageAmt;
 }
}

这个抽象类主要实现按照模板生成报表,出入每页条数,自动生成多个文件(其实可以改成生成一个文件,多个sheet)。下次再举一个实现类。

相关文章推荐

在Java中读取EXCEL文件 JExcelAPI与Apache POI两者对比

一,JExcelAPI与Apache POI两者对比   1、JExcelAPI不适合商业应用,它都是会莫名其妙的读不出来数据。   2、Apache POI是一纯Java的实现,不仅能读微软的E...

jsp jexcelapi servlet 实现 从数据库中导出EXCEL文件

效果: 1  JSP 上有 导出按钮 2 点导出 3 直接 弹出窗口 问你 是  保存EXCEL  还是打开   1  建立 jsp 文件         ...
  • mfc2003
  • mfc2003
  • 2012年08月03日 21:44
  • 1818

Java中通过修改配置文件实现接口或抽象类子类的切换

我们开发的项目中有可能针对不同的数据库,因此同一个Dao接口可能提供了针对不同数据库的实现。下面我们通过修改properties配置文件的方式来实现同一个接口调用不同子类的实现,这样我们不用去修改源代...

实现抽象类求面积方法

  • 2015年05月31日 19:27
  • 44KB
  • 下载

抽象类和接口的区别

  • 2014年04月23日 19:24
  • 3KB
  • 下载

深入理解Java的接口和抽象类(转载---写的非常好~)

深入理解Java的接口和抽象类   对于面向对象编程来说,抽象是它的一大特征之一。在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类。这两者有太多相似的地方,又有太多不同的地方。很多...

关于接口和抽象类的案例

  • 2014年08月25日 21:28
  • 619B
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:jexcelapi写excel文件的抽象类(一)
举报原因:
原因补充:

(最多只允许输入30个字)