1.客户端导出Excel
1.1 网上找了些资料,目前的jar包有应用于桌面系统的as3xls,AirExcel,在web应用中无法导入相关类包。
1.2 使用js调用客户端的Excel 对象。在网上找的一段代码:
// ACTION SCRIPT FOR YOUR FLEX APP
function doCopy(dg)
{
var font = dg.getStyle('fontFamily');
var size = dg.getStyle('fontSize');
var hcolor ;
if(dg.getStyle("headerColor") != undefined) hcolor = [dg.getStyle("headerColor")];
else hcolor = dg.getStyle("headerColors");
var str:String = '<html><body><table width="'+dg.width+'"><thead><tr width="'+ dg.width+'" style="background-color:#' +Number((hcolor[0])).toString(16)+'">';
for(var i=0;i<dg.__columns.length;i++)
{
var colors = dg.getStyle("themeColor");
var style = 'style="font-family:'+font+';font-size:'+size+'pt;"';
if(dg.__columns[i].headerText != undefined)
{
str+="<th "+style+">"+dg.__columns[i].headerText+"</th>";
}
else
{
str+= "<th "+style+">"+dg.__columns[i].columnName+"</th>";
}
}
str += "</tr></thead><tbody>";
var colors = dg.getStyle("alternatingRowColors");
for(var j=0;j<dg.length;j++)
{
str+="<tr width=\""+Math.ceil(dg.width)+"\" style='background-color:#" +Number((colors[j%colors.length])).toString(16)+"'>";
var style = 'style="font-family:'+font+';font-size:'+size+'pt;"';
for(var i=0;i<dg.__columns.length;i++)
{
if(dg.getItemAt(j) != undefined && dg.getItemAt(j) != null)
if(dg.__columns[i].labelFunction != undefined)
str += "<td width=\""+Math.ceil(dg.__columns[i].width)+"\" "+style+">"+dg.__columns[i].labelFunction(dg.getItemAt(j),dg.__columns[i].columnName)+"</td>";
else
str += "<td width=\""+Math.ceil(dg.__columns[i].width)+"\" "+style+">"+dg.getItemAt(j)[dg.__columns[i].columnName]+"</td>";
}
str += "</tr>";
}
str+="</tbody></table></body></html>";
System.setClipboard(str);
}
function handleOnKeyUp()
{
if(Key.isDown(Key.CONTROL) &&Key.getCode() ==67)
{
mx.managers.CursorManager.setBusyCursor();
doCopy(grid); // exchange 'grid' with the id of your datagrid you want copied
mx.managers.CursorManager.removeBusyCursor();
}
}
// only register interest if you want ctrl-c to process a copy of a datagrid. // it's also ctrl + c (on key up, not down)
var obj:Object;
function registerKeyInterest()
{
if(obj == undefined)
{
obj = new Object();
obj.onKeyUp = mx.utils.Delegate.create(this,handleOnKeyUp);
}
Key.addListener(obj);
}
function removeKeyInterest()
{
Key.removeListener(obj);
}
function copyAndOpen(grid)
{
doCopy(grid);
getUrl("javascript:openExcel();");
}
// JAVASCRIPT for your HTML PAGE
<SCRIPT Language="JavaScript1.2">
var excel = null;
function openExcel()
{
try
{
if(excel == null)
{
excel = new ActiveXObject("Excel.Application");
}
var workbook = excel.Workbooks.Add();
workbook.Activate();
var worksheet = workbook.Worksheets("Sheet1");
worksheet.Activate();
worksheet.Paste();
excel.visible=true;
}catch(exception)
{
window.alert("Now you may Paste into an Excel SpreadSheet");
}
}
</SCRIPT>
2. 服务器端导入Excel
2.1 jar包:poi,jxl等。
2.2 使用poi3.7实现的例子。
2.2.1 poi3.7的下载
2.2.2 客户端as:
var variables:URLVariables = new URLVariables();//封装request传输参数
variables.data = 要导出的数据(需要组装成String)
var request:URLRequest = new URLRequest(url); //封装http访问请求
request.method = URLRequestMethod.POST;
request.data = variables;
navigateToURL(request,"_self");//返回结果导航到当前窗口的当前帧
2.2.3 Spring配置:
<!-- 控制器映射 -->
<bean id="outputExcel_urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/outputExcel/*.htm">outputExcelController</prop>
</props>
</property>
</bean>
<!-- 静态控制器 -->
<bean id="outputExcelStaticController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" >
<property name="prefix" value=""/>
</bean>
<bean id="outputExcelController" class="com.test.OutputExcelController">
<property name="methodNameResolver">
<ref bean="outputExcelControllerResolver" />
</property>
</bean>
<!-- 方法名解析器 -->
<bean id="outputExcelControllerResolver"
class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<!-- 配置Excel输出URL页面响应 -->
<prop key="/outputExcel/outputExcel.htm">doMainDispatch</prop>
</props>
</property>
</bean>
2.2.4 后台Controller,主要完成三个工作一是解析收到的字符串核心是String.split(String regEx),注意为了兼顾正则表达式,有些特殊字符如“$”,“*”,“^”等是不能用于regEx的,最后通过实验,选择了“##”,“:”,“&”作为三级特殊分割字符;二是按照workbook->sheet->row->cell文档结构生成excel文件;最后通过设置HttpServletResponse:: resp.setContentType("application/vnd.ms-excel")直接将生成excel文件写到HttpServletResponse输出流中提供用户下载。参考代码如下:
public void doMainDispatch(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
logger.info("OutputExcelController:doMainDispatch收到导出Excel请求");
resp.reset();
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/vnd.ms-excel");
String fileName = req.getParameter("fileName");
resp.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
String[] tokens = {req.getParameter("layerSplitToken"),req.getParameter("headBodySplitToken"),req.getParameter("dataSplitToken")};
String head = req.getParameter("head");
String data = req.getParameter("data");
HSSFWorkbook wb = this.generateMultiSheetsExcel(head, data,tokens);//generateExcel(head,data,sheetName);
wb.write(resp.getOutputStream());
resp.getOutputStream().flush();
resp.getOutputStream().close();
req.getInputStream().close();
}
/*
* @Function:generateMultiSheetsExcel--创建多Sheet的一个Excel文件,其中给个Sheet对应一个图层;
* @Param:head--每张Sheet名称、列名;
* @Param:data--每张Sheet的数据;
* @Param:tokens--分割从请求处获得的head,data字符串所用的特殊字符串
* @Return:HSSFWorkbook--生成的Excel工作簿;
*/
private HSSFWorkbook generateMultiSheetsExcel(String head, String data, String[] tokens) {
int rowNum=0,colNum=0,totalRowNum = 0;
HSSFWorkbook hssfworkbook = new HSSFWorkbook ();
HSSFSheet hssfsheet = null;
HSSFRow hssfrow = null;
HSSFCell hssfcell = null;
//step1:按”;“分割,获得每张表的head 和 data
String strLayerSplitToken = "#";
String strHeadDataSplitToken = ":";
String strDataSplitToken = "&";
if(2 < tokens.length) {
strLayerSplitToken = tokens[0];
strHeadDataSplitToken = tokens[1];
strDataSplitToken = tokens[2];
}else if(1< tokens.length && tokens.length <= 2) {
strLayerSplitToken = tokens[0];
strHeadDataSplitToken = tokens[1];
}else if(0 < tokens.length){
strLayerSplitToken = tokens[0];
}
String[] sheetsArr = head.split(strLayerSplitToken), sheetsDataArr = data.split(strLayerSplitToken);
String[] curSheetArr = null, curSheetDataArr = null;
String[] headArr = null, dataArr = null;
if(sheetsArr.length == sheetsDataArr.length) {
for(int ii= 0; ii < sheetsArr.length; ++ii) {
//step2:分割图层名与图层字段两部分,获得每张表中表名和字段部分
curSheetArr = sheetsArr[ii].split(strHeadDataSplitToken);
curSheetDataArr = sheetsDataArr[ii].split(strHeadDataSplitToken);
//step2.1:建当前sheet;
hssfsheet = hssfworkbook.createSheet(curSheetArr[0]);
//step3:分割图层各字段,为Excel下的每张Sheet中的Cell赋值
if(0 < curSheetArr.length && curSheetArr.length == curSheetDataArr.length) {
headArr = curSheetArr[1].split(strDataSplitToken);
dataArr = curSheetDataArr[1].split(strDataSplitToken);
//step3.1:写入当前Sheet数据;
totalRowNum = dataArr.length/headArr.length;
for(rowNum=0; rowNum<totalRowNum; rowNum++)
{
hssfrow = hssfsheet.createRow (rowNum);
if(0 == rowNum) {
for(colNum=0; colNum < headArr.length; ++colNum) {
hssfcell = hssfrow.createCell ((int) (colNum+1));
hssfcell.setCellValue(headArr[colNum]);
}
} else {
hssfcell = hssfrow.createCell ((int) 0); //第一列为序号列
hssfcell.setCellValue(rowNum);
for(colNum=0; colNum < headArr.length; ++colNum) {
hssfcell = hssfrow.createCell ((int) (colNum+1));
hssfcell.setCellValue(dataArr[(rowNum-1)*headArr.length + colNum]);//注意在Excel中第n行为dataArr中的第n-1行数据
}
}
}
} else {
logger.error("OutputExcelController:generateMultiSheetsExcel创建Excel失败--head与data两次字段数计算不等");
}
}
} else {
logger.error("OutputExcelController:generateMultiSheetsExcel创建Excel失败--haad与data两次图层数计算不等");
}
return hssfworkbook;
}
3. 一些参考资料
比较完整的基于poi代码:
http://pufan53.iteye.com/blog/903468
poi操作Excel:
http://www.codeweblog.com/read-and-write-excel-poi/
比较完整的基于jxls代码:
http://java.csecs.com/posts/list/2246.html