论坛首页 Java企业应用论坛

自动创建Excel报表的小工具

浏览 8747 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-04-02  
功能:将List或者其他对象导出为excel 报表.
只需在ReportHeader中设置单元格的基本信息,
包括ReportContents中handler的数据Object中属性与单元格的对应关系就能生成excel 文件.

btw:最新的版本在最后一个回复上.这上面的删不去.

使用方式如下:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.dovecat.excel.handler.ExcelReportGenerator;
import com.dovecat.excel.handler.impl.ExcelReportGeneratorImpl;
import com.dovecat.excel.report.exception.ReportContentException;
import com.dovecat.excel.report.exception.ReportFootException;
import com.dovecat.excel.report.exception.ReportHeaderException;
import com.dovecat.excel.report.exception.ReportTitleException;
import com.dovecat.excel.report.model.ReportContents;
import com.dovecat.excel.report.model.ReportFooter;
import com.dovecat.excel.report.model.ReportFooters;
import com.dovecat.excel.report.model.ReportHeaderCell;
import com.dovecat.excel.report.model.ReportHeaders;
import com.dovecat.excel.report.model.ReportTitle;
import com.dovecat.excel.report.model.ReportTitles;

public class ExcelReportTest extends TestCase {
  StaffInfoVO staff = new StaffInfoVO();

  StaffInfoVO staffOther = new StaffInfoVO();

  private ExcelReportGenerator generator = new ExcelReportGeneratorImpl();

  protected void setUp() throws Exception {
    List roles = new ArrayList();
    roles.add(new RoleVO("111"));
    roles.add(new RoleVO("222"));
    roles.add(new RoleVO("333"));
    staff.setRoles(roles);
    staff.setName("www");
    staff.setStaffNo("e1234567");

    staffOther.setName("other");
    staffOther.setStaffNo("e1111111111111");
    staffOther.setRoles(roles);
  }

  public void testFormat() {
    HSSFWorkbook workBook = generator.getHSSFWorkbook();
    HSSFSheet sheet = generator.getHSSFSheet(workBook);
    HSSFCellStyle cellStyle = workBook.createCellStyle();
    HSSFFont font = workBook.createFont();
    font.setItalic(true);
    cellStyle.setFont(font);
    ReportHeaders headers = new ReportHeaders();
    ReportHeaderCell header = new ReportHeaderCell();
    // 报表头的名称
    header.setHeaderName("姓名");
    // 这里是对应报表头的,在StaffInfoVO 中的属性的名称name,报表会去找对应的值
    header.setValueCellPath("name");
    header.setHeaderCellStyle(cellStyle);
    header.setValueCellStyle(cellStyle);
    // 设置报表头从第几个单元格开始
    header.setStartHeaderCellIndex((short) 3);
    // 其对应的值从第几个单元格开始
    header.setStartValueCellIndex((short) 3);
    // 放入表头集合
    headers.putHeader(header);

    header = new ReportHeaderCell();
    header.setHeaderName("编号");
    header.setValueCellPath("staffNo");
    header.setHeaderCellStyle(cellStyle);
    header.setValueCellStyle(cellStyle);
    headers.putHeader(header);
    List roles = staff.getRoles();
    for (int i = roles.size(); i-- > 0;) {
      header = new ReportHeaderCell();
      // 生成动态表头和其对应的属性
      header.setHeaderName("角色[" + i + "]");
      // 对应的属性
      header.setValueCellPath("roles[" + i + "].roleName");
      header.setHeaderCellStyle(cellStyle);
      header.setValueCellStyle(cellStyle);
      headers.putHeader(header);
    }
    // 注册报表的内容对象,可以是List,Set等对象
    ReportContents contents = new ReportContents();
    contents.registerContentObject(staff);
    contents.registerContentObject(staffOther);
    
    // 测试数据为List时的情况
    List list = new ArrayList();
    list.add(staff);
    list.add(staffOther);

    contents.registerContentObject(list);
    
    // 创建报表标题对象
    ReportTitles titles = new ReportTitles();
    ReportTitle title = new ReportTitle();
    // 设置标题内容
    title.setTitle("title!");
    // 设置下标
    title.setCellIndex((short) 5);
    // 设置样式
    title.setTitleStyle(cellStyle);
    // 测试多标题的情况
    titles.putTitle(title);
    titles.putTitle(title);

    // 创建报表脚,处理同标题
    ReportFooters footers = new ReportFooters();
    ReportFooter footer = new ReportFooter();

    footer.setCellIndex((short) 5);
    footer.setFoot("footer");
    footer.setFooterStyle(cellStyle);
    footers.putFooter(footer);
    footers.putFooter(footer);

    try {
      // 格式化为excel
      generator.format(sheet, titles, headers, contents, footers);
      FileOutputStream fos = new FileOutputStream(new File("d:\\111.xls"));
      // 写文件
      generator.writeExcelReport(workBook, fos);
    } catch (ReportTitleException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ReportHeaderException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ReportContentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ReportFootException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}



import java.io.Serializable;

public class RoleVO implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -1098554921423097300L;

	public RoleVO(String roleName) {
		this.roleName = roleName;
	}

	public String roleName;

	public String getRoleName() {
		return roleName;
	}

	public void setRoleName(String roleName) {
		this.roleName = roleName;
	}

}

import java.io.Serializable;
import java.util.List;

public class StaffInfoVO implements Serializable {

  /**
   * 
   */
  private static final long serialVersionUID = -57676961756664705L;

  private String name;

  private String staffNo;

  private List roles;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public List getRoles() {
    return roles;
  }

  public void setRoles(List roles) {
    this.roles = roles;
  }

  public String getStaffNo() {
    return staffNo;
  }

  public void setStaffNo(String staffNo) {
    this.staffNo = staffNo;
  }

}
   发表时间:2007-04-03  
btw:javaeye好象对文件的操作,只有在有文件提交的时候,当设置为准备删除flag时,提交后并没有删除文件。
  • poi.rar (719.1 KB)
  • 下载次数: 202
0 请登录后投票
   发表时间:2007-04-03  
试用过OK,以后也许用得上,谢谢楼主分享
0 请登录后投票
   发表时间:2007-04-03  
CherryRemind 写道
试用过OK,以后也许用得上,谢谢楼主分享


更新一下版本:
增加了对数组对象和集合对象的处理功能,
对标题头和脚的处理功能,
针对字段的过滤功能和过滤后及被过滤的数据的处理功能
增加了报表缩进

添加报表内容过滤器的方法:
ReportContents contents = new ReportContents();
    contents.registerContentObject(staff);
    contents.registerContentObject(staffOther);
    // 任何对象 将被作为过滤的其他条件(可选)处理
    contents.setCondition(new Object());
    contents.putExcelReportContentFilter(new ExcelReportContentFilterTest());

过滤器的实现example:
package com.dovecat.excel.util.test;

import java.util.List;

import com.dovecat.excel.filter.ExcelReportContentFilter;
import com.dovecat.excel.report.exception.ReportContentException;
import com.dovecat.excel.report.model.ReportContents;
import com.dovecat.excel.report.model.ReportHeaderCell;
import com.dovecat.excel.report.model.ReportHeaders;
import com.dovecat.excel.util.test.model.RoleVO;
import com.dovecat.excel.util.test.model.StaffInfoVO;

public class ExcelReportContentFilterTest implements ExcelReportContentFilter {

	/**
	 * 过滤实现的example
	 */
	public boolean contentFilter(ReportContents contents, Object contentObject,
			int contentObjectIndex, ReportHeaders headers,
			ReportHeaderCell header, int headerIndex, Object otherCondition)
			throws ReportContentException {
		StaffInfoVO staff = (StaffInfoVO) contentObject;
		List roles = staff.getRoles();
		if (header.getValueCellPath().startsWith("roles[")) {
			for (int i = roles.size(); i-- > 0;) {
				RoleVO role = (RoleVO) roles.get(i);
				System.out.println("roleName:" + role.getRoleName());
				if (role.getRoleName().startsWith(header.getHeaderName())) {
					return true;
				}
			}
			return false;
		}
		return true;
	}

}

btw:突然发现ruby对excel等win32Ole的支持超级方便和好用。
java写这些excel的代码确实比较烦琐。
0 请登录后投票
   发表时间:2007-04-10  
为什么导出的文件大小是5K,打开后保存一下就变成14k了?
0 请登录后投票
   发表时间:2007-04-10  
pigfans 写道
为什么导出的文件大小是5K,打开后保存一下就变成14k了?

excel文件分几个部分,其中包含内容部分(数据流)和文件属性部分(谁创建的,什么类型的文件,创建时间,修改时间等)或者还有一个宏的流,现在POI好象还没有支持宏的方法(哪位知道,还请发帖告诉一下哈.)
工具下载的,只是EXCEL的数据部分,然后我们打开下载的文件重新保存一下,OFFICE会将缺少的文件属性的部分也保存到EXCEL文件中,因此文件的大小会有变化.并不会改变我们导出的内容.
0 请登录后投票
   发表时间:2007-04-10  
lz 我下载最后的 回复的rar  里面怎么没有src得
0 请登录后投票
   发表时间:2007-04-19  
dovecat 写道
pigfans 写道
为什么导出的文件大小是5K,打开后保存一下就变成14k了?

excel文件分几个部分,其中包含内容部分(数据流)和文件属性部分(谁创建的,什么类型的文件,创建时间,修改时间等)或者还有一个宏的流,现在POI好象还没有支持宏的方法(哪位知道,还请发帖告诉一下哈.)
工具下载的,只是EXCEL的数据部分,然后我们打开下载的文件重新保存一下,OFFICE会将缺少的文件属性的部分也保存到EXCEL文件中,因此文件的大小会有变化.并不会改变我们导出的内容.


POI包读取前面提到的5K的文件会报异常,后来查了下资料,是poi包中的一个bug。

楼主有没有尝试过分别读5k和14k这两个文件?读取出来的列数好像不一样,5k那个的列数比14k的少1。

还有就是如果excel文件比较大的时候(超过4M),实例化HSSFWorkbook的时候,会抛OutOfMemory异常,除了分配多些内存给JVM之外还有没有什么办法解决??
0 请登录后投票
   发表时间:2007-06-11  
import com.dovecat.excel.report.model.ReportFooter;
这个包 是那个包改的?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics