`
tedeyang
  • 浏览: 319026 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Excel领域的Velocity:JXLS,强烈推荐!

阅读更多

Excel领域的Velocity:JXLS,强烈推荐!

我终于找到了导出excel视图的最好实现:JXLS
http://jxls.sourceforge.net/

使用JXLS,能够达到Velocity的效果.将excel视图"模板化" .
而jxls不光能输出字符串,还能输出图像,公式计算,自动由sql生成报表等等.
实在是导出excel必备利器啊!
(实在是了不起的创意!如果Word也能有类似实现,哈哈,想想都爽.)

这种模板方式操作excel比POI,JExcelAPI优越之处:
可视化编辑,实现任意复杂的excel,精确控制版面;
使用简单,不需要调用任何API,能够保持与Velocity一致性.
jxls VS poi == velocity VS servlet
(当然,jxls内部其实是使用poi作为底层api)

实际应用技巧:
JXLS 项目里仅仅提供了与WebWork的集成,我针对Spring MVC扩展了一个JxlsExcelView ,类似于Spring的VelocityView,有了这个,同一个模型的数据能够直接提供给 Velocity或者Jxls解析,分别显示出html和excel,而不需要写任何代码.最近在数据分析系统里成功使用了.

 

下面是源码,如何使用我就不多说了,可以参考Spring官方文档中视图部分。

 

package excel.view;

import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jxls.transformer.XLSTransformer;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.LocalizedResourceHelper;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.view.AbstractView;

public class JxlsExcelView extends AbstractView {

	private static String content_type="application/vnd.ms-excel; charset=UTF-8"; 
	private static String extension=".xls";
	
	private String fileName;
	private String location;
	
	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}
	
	public JxlsExcelView() {
		setContentType(content_type);
	}
	
	protected void renderMergedOutputModel(Map map, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		
		HSSFWorkbook workbook;
		
		LocalizedResourceHelper helper=new LocalizedResourceHelper(getApplicationContext());
		Locale userLocale=RequestContextUtils.getLocale(request);
		Resource inputFile=helper.findLocalizedResource(location, extension, userLocale);
		
		XLSTransformer transformer=new XLSTransformer();
	        workbook=transformer.transformXLS(inputFile.getInputStream(), map);


		
		response.setContentType(getContentType());
		response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
		
		ServletOutputStream out=response.getOutputStream();
		workbook.write(out);
		out.flush();		
	}

}
 

后记:

使用时要注意内存,因为jxls不是基于流操作的。不能转换太大的excel,一般超过10M的xls可能造成OOM。


     当需要导出的数据量逐渐增长时,我们就会看到任务管理器里的内存消耗量“蹭蹭蹭”往上涨,直如牛市一发不可收,轻轻松松就“涨停”—— OutOfMemery了。这种情况可以理解:jxls使用poi进行excel操作,这是要先生成一个完整的Workbook对象后再保存到文件的。这 样内存里就需要存放所有的row和cell对象,而且在最后一条数据对象化前内存是始终得不到释放的。
根据经验,导出的数据(纯文本形式)大小如果为1K,需要消耗内存60K。也就是说比率是1:60。(这个比率目前是我大概估计的)。初步估算一下:如果导出的数据一行为250字节,4000行约为1M,导出excel时就需要60M内存。
因此,内存增长是一个问题,还有一个问题就是excel的2^16行数限制。
解决办法需要多管齐下:
1.多sheet进行分页。
2.多workbook进行分文件存储然后合并。
通过两次动作分解,可以将内存消耗维持在一个稳定的水平上。

具体原理不讲了,就发一段测试代码:。。。

 

【2007-7 bbs】

 

分享到:
评论
2 楼 tedeyang 2011-12-01  
anmijay 写道
你好,刚看到这个微博,不知道jxls是否支持自定义导出????

    * Using SQL queries directly in XLS templates
    * Simple property access notation
    * Full expression language support
    * Complex object graph export
    * Flexible collection export
    * Flow-Control Tags support
    * Dynamic grouping of data
    * Export of a single collection into multiple worksheets
    * Adjacent tables support!
    * Complex formulas support
    * Charts, Macros and many other Excel features in XLS template
    * Dynamic Outlines
    * Dynamic Columns Hiding
    * Dynamic Cell Style processing through custom Processors
    * JDBC ResultSet export
    * Merged Cells support
    * Multiple bean properties in a single cell
    * Reading XLS files

把excel作为视图层,excel本身是可以由你自定义的。这种方式是在excel里写java变量,然后直接输出。
1 楼 anmijay 2011-11-28  
你好,刚看到这个微博,不知道jxls是否支持自定义导出????

相关推荐

Global site tag (gtag.js) - Google Analytics