前台使用Ext JS,后台框架为SSH,使用Apache的POI组件来实现导出Excel功能。
Apache POI是Apache软件基金会的开放源码函数库,POI提供API给Java程序对Microsoft Office格式文档进行读写的功能。本项目的各管理模块中用到的导出Excel功能都是调用POI库在服务器端先生成Excel文件,然后提供给前端进行下载的。
首先,导入apache的POI库文件。初始化一个workbook,并创建新的sheet,然后逐行生成并插入row,即可生成一个Excel文件。最后将workbook写入ByteArrayInputStream流传输到前台。进行适当的配置之后,浏览器就能识别出Excel文件。
配置文件中,需指定相应Action的返回结果的类型为excel文件流,并且以附件的形式打开,还要指定文件的名字,例如:
<action name="expWarnHisAction" class="SearchWarning" method="searchForExport">
<result name="success" type="stream">
<param name="contentType">application/vnd.ms-excel</param>
<param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
<param name="inputName">bais</param>
</result>
</action>
配置好之后,前端用Javascript函数window.open()打开相应的Action,并附上查询条件作为请求参数,即可打开一个新的浏览器窗口进行导出。Action核心代码如下,需要考虑的一个问题是,Office的Excel文件(03版之前)中,每一个工作表最多能有65536行,所以如果超过65536行数据,需要进行特殊处理,创建多个工作表(sheet):
HSSFWorkbook workbook = new HSSFWorkbook();
//NearEast 2012-03-23 考虑单sheet中记录数不能超过65536;且认为总数不会超过int的表示范围
int total = warningService.getTotalWarnings(ab);
int s = 0;//每65535条记录新开一个sheet
int cnt = total/65535 + 1;
HSSFSheet[] sheet = new HSSFSheet[cnt];
HSSFRow row = null;
for(int i=0; i<cnt; i++){
sheet[i] = workbook.createSheet("sheet" + i);
row = sheet[i].createRow(0);
row.createCell(0).setCellValue("预警时间");
row.createCell(1).setCellValue("车牌号");
row.createCell(2).setCellValue("预警类型");
row.createCell(3).setCellValue("当前速度");
row.createCell(4).setCellValue("当时预警");
row.createCell(5).setCellValue("驾驶员");
row.createCell(6).setCellValue("所属单位");
}
for (int i = 0; i < warnings.size(); i++) {
row = sheet[i/65535].createRow(i%65535 + 1);
ab = (WarnerBean) warnings.get(i);
row.createCell(0).setCellValue(ab.getStartTime());
row.createCell(1).setCellValue(ab.getIdnumber());
row.createCell(2).setCellValue(ab.getWarnerTypeStr());
row.createCell(3).setCellValue(ab.getSpeed());
row.createCell(4).setCellValue(ab.getComparedValue());
row.createCell(5).setCellValue(ab.getDriver());
row.createCell(6).setCellValue(ab.getDepartment());
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
workbook.write(baos);
} catch (IOException e) {
e.printStackTrace();
}
byte[] ba = baos.toByteArray();
setBais(new ByteArrayInputStream(ba));
warnings = null;
辅助函数:
public String getDownloadFileName(){
String name = null;
try {
name = new String("导出历史预警.xls".getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
name = "warnings.xls";
e.printStackTrace();
}
return name;
}
Struts的配置文件中,可以指定上传文件的大小限制,此处限制为16兆:
<struts>
<constant name="struts.multipart.maxSize" value="16777216"/>
</struts>