网上有extjs的grid直接导出为excel的控件,但是不满足需求,因为grid一般是分页的,而excel导出的时候肯定是全部数据
?
导 出excel这个过程的输入是 列配置信息(列头,字段名,宽度,顺序)
输出时excel文件
生成grid数据和导出 excel的数据要能重用
?
所以把列头信息作为参数传递到服务器端
params = Ext.apply({},this.findParentByType('form').getForm().getValues(),store.baseParams); var cm = grid.getColumnModel() ; for (var i = 0; i < cm.getColumnCount(); i++) { if (cm.getDataIndex(i)){ var fld = grid.store.recordType.prototype.fields.get(cm.getDataIndex(i)); var column_type = 'String'; switch(fld.type) { case "int": column_type="int"; break; case "float": column_type="float"; break; case "date": column_type="date"; break; }; params['columns['+i+'][hidden]']= cm.isHidden(i); params['columns['+i+'][column_width]'] = cm.getColumnWidth(i); params['columns['+i+'][column_header]']= cm.getColumnHeader(i); params['columns['+i+'][column_type]'] = column_type; params['columns['+i+'][data_index]'] = cm.getDataIndex(i); } } openPostWindow('/car_info/export_to_excel','_blank',params); //注意这行
?
{zh1}在新窗口打开链接不是用window.open,因为get方式传输数据量有限制,在ie中可能会报错,要用post方式
openPostWindow代码如下:
function openPostWindow(url,name,data){ var tempForm = document.createElement("form"); tempForm.id="tempForm1"; tempForm.method="post"; tempForm.action=url; tempForm.target=name; for(var p in data){ var hideInput = document.createElement("input"); hideInput.type="hidden"; hideInput.name= p; hideInput.value= data[p]; tempForm.appendChild(hideInput); } var request_forgery_protection_token_hideInput = document.createElement("input"); request_forgery_protection_token_hideInput.type="hidden"; request_forgery_protection_token_hideInput.name= "authenticity_token"; request_forgery_protection_token_hideInput.value= Ext.Ajax.extraParams.authenticity_token; tempForm.appendChild(request_forgery_protection_token_hideInput); if(tempForm.attachEvent){ tempForm.attachEvent("onsubmit",function(){openWindow(name);}); } else { tempForm.addEventListener("submit",function(){openWindow(name);},false); } document.body.appendChild(tempForm); if (tempForm.fireEvent) { tempForm.fireEvent('onsubmit'); tempForm.submit(); } else if (document.createEvent) { var ev = document.createEvent('HTMLEvents'); ev.initEvent('submit', false, true); tempForm.dispatchEvent(ev); } document.body.removeChild(tempForm); return false; }
?在firefox和ie中测试通过
?
?
服务器端代码如下
?
query_params = params query_params.delete(:limit) query_params.delete(:start) result = listdata(query_params) xls_report = StringIO.new book = Spreadsheet::Workbook.new sheet1 = book.create_worksheet :name => "WORKSHEET_NAME" sheet1.row(0).default_format = Spreadsheet::Format.new :color => :black, :weight => :bold, :size => 10 keys = params[:columns].keys.compact.collect{|key| key.to_i}.sort.collect{|key| key.to_s} sheet1.row(0).concat(keys.collect{|key| params[:columns][key][:column_header]}) row_num = 1 result[:rows].each do |row| sheet1.row(row_num).concat keys.collect{|key| row[params[:columns][key][:data_index]]} row_num = row_num + 1 end keys.each_with_index do |key,index| sheet1.column(index).width = params[:columns][key][:column_width].to_f/10 end book.write xls_report send_data(xls_report.string, :filename => 'FILENAME.xls', :type => 'application/vnd.ms-excel', :disposition => 'inline')
?首先删除limit和start两个参数,然后调用listdata这个取数据的方法(这个方法一般写在model中,这里为了简单写在controller中作为private方法),然后把数据写入到excel流中,{zh1}发送excel流
?
这样excel导出完成,excel和grid从同一来源取数据
并且如果在界面上调整了列的顺序或者宽度,导出的excel会随着变化
?
?