DevSecOps

27 fev, 2009

Exportar Datagrid para Excel

Publicidade

Abaixo mostrarei como realizar essa exportação.

Primeiramente precisamos construir nossa aplicação no Adobe Flex, para obter o resultado acima. Copie o código abaixo.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
		<![CDATA[
			[Bindable]
			private var dp:Array = [
				{ symbol: "ADBE", name: "Adobe Systems Inc.", price1: 49.95, price2: 49.95, price3: 49.95, price4: 49.95, price5: 49.95 },
				{ symbol: "MACR", name: "Macromedia Inc.", price1: 49.95, price2: 49.95, price3: 49.95, price4: 49.95, price5: 49.95 },
				{ symbol: "MSFT", name: "Microsoft Corp.", price1: 49.95, price2: 49.95, price3: 49.95, price4: 49.95, price5: 49.95 },
				{ symbol: "IBM", name: "IBM Corp.", price1: 49.95, price2: 49.95, price3: 49.95, price4: 49.95, price5: 49.95 },
				{ symbol: "ADBE", name: "Adobe Systems Inc.", price1: 49.95, price2: 49.95, price3: 49.95, price4: 49.95, price5: 49.95 },
				{ symbol: "MACR", name: "Macromedia Inc.", price1: 49.95, price2: 49.95, price3: 49.95, price4: 49.95, price5: 49.95 }
				];					
		]]>
	</mx:Script>	
	<mx:DataGrid id="dgDado" y="40" dataProvider="{dp}" horizontalCenter="0"/>
	<mx:Button y="10" label="Exportar para o Excel" horizontalCenter="0" id="btExportar"/>	
</mx:Application>

Agora vem o primeiro pulo do gato. Crie uma classe no Flex chamada DataGridExporter. Em meu exemplo salvei a classe no diretório br.com.igormusardo.datagrid.

Nesta classe, temos duas funções loadDGInExcel e convertDGToHTMLTable. Essas funções são responsáveis por receber uma Datagrid como parâmetro, ler o seu conteúdo, criar o código HTML que represente a DataGrid e finalmente passar o HTML gerado como parâmetro de uma página. No meu caso ASP.NET, mas pode ser feito em PHP ou JSP, informada na variável urlExcelExport para que a aplicação server-side gere o arquivo .XLS e forçe o download para o cliente. Para tanto copie o código abaixo.

package br.com.igormusardo.datagrid
{
    	import flash.errors.*;
    	import flash.events.*;
    	import flash.external.*;
    	import flash.net.URLRequest;
    	import flash.net.URLRequestMethod;
    	import flash.net.URLVariables;
    	import flash.net.navigateToURL;
 
	public class DataGridExporter
        {        	
	        //Aplicação servidor que gerará o excel
	        public var urlExcelExport:String = "ExcelExport.aspx";
 
 
	        // Converte a datagrid para uma tabela html
	        private function convertDGToHTMLTable(dg:*):String {
	        	var font:String = dg.getStyle('fontFamily');
	        	var size:String = (int(dg.getStyle('fontSize'))-2).toString(); //Reduz em 2, o tamanho da fonte.
	        	var str:String = '';
	        	var colors:String = '';
	        	var style:String = 'style="font-family:'+font+';font-size:'+size+'pt;"';				
	        	var hcolor:Array;
 
	        	if(dg.getStyle("headerColor") != undefined) {
	        		hcolor = [dg.getStyle("headerColor")];
	        	} else {
	        		hcolor = dg.getStyle("headerColors");
	        	}				
 
	        	str+= '<table width="'+dg.width+'"><thead><tr width="'+dg.width+'" style="background-color:#' +Number((hcolor[0])).toString(16)+'">';
 
	        	for(var i:int = 0;i<dg.columns.length;i++) {
	        		colors = dg.getStyle("themeColor");
 
	        		if(dg.columns[i].headerText != undefined && dg.columns[i].visible == true) {
	        			str+="<th "+style+">"+dg.columns[i].headerText+"</th>";
	        		} else if (dg.columns[i].visible == true) {
	        			str+= "<th "+style+">"+dg.columns[i].dataField+"</th>";
	        		}
	        	}
	        	str += "</tr></thead><tbody>";
	        	colors = dg.getStyle("alternatingRowColors");
 
	        	for(var j:int =0;j<dg.dataProvider.length;j++) {					
	        		str+="<tr width=\""+Math.ceil(dg.width)+"\">";
 
	        		for(var k:int=0; k < dg.columns.length; k++) {
	        			if(dg.dataProvider.getItemAt(j) != undefined && dg.dataProvider.getItemAt(j) != null && dg.columns[k].visible == true && dg.columns[k].dataField != "Melhor") {
	        				if(dg.columns[k].labelFunction != undefined && dg.columns[k].labelFunction != null && dg.columns[k].visible == true) {
	        					str += "<td nowrap=\"nowrap\" width=\""+Math.ceil(dg.columns[k].width)+"\" "+style+">"+dg.columns[k].labelFunction(dg.dataProvider[j],dg.columns[k])+"</td>";
	        				} else {
	        					str += "<td nowrap=\"nowrap\" width=\""+Math.ceil(dg.columns[k].width)+"\" "+style+">"+dg.dataProvider.getItemAt(j)[dg.columns[k].dataField]+"</td>";
	        				}
	        			}
	        		}
	        		str += "</tr>";
	        	}
	        	str+="</tbody></table>";
 
	        	return str;
	        }
 
		// Envia o HTML para a aplicação servidor
		public function loadDGInExcel(dg:*):void {
 
			var variables:URLVariables = new URLVariables(); 
			variables.htmltable	= convertDGToHTMLTable(dg);
 
			var u:URLRequest = new URLRequest(urlExcelExport);
			u.data = variables;
			u.method = URLRequestMethod.POST;
 
			navigateToURL(u,"_self");
	        }       
        }
}

Após criada a classe, é necessário atribiuir uma função que executará o loadDGInExcel. Inclua o código abaixo ao seu código fonte action script.

private function exportar():void
{
	var dgE:DataGridExporter = new DataGridExporter();
	dgE.loadDGInExcel(dgDado);
}

E por fim, atribua a função exportar() ao clique do botão, como o código abaixo.

<mx:Button y="10" label="Exportar para o Excel" horizontalCenter="0" id="btExportar" click="{exportar()}"/>

Pronto, no Adobe Flex, não é necessário fazer mais nenhuma alteração, agora o trabalho fica por conta da aplicação server-side. No Visual Studio, crie um novo arquivo chamado de ExcelExport.aspx, e inclua a tag ValidateRequest=”false” no cabeçalho do arquivo aspx, como abaixo.

<%@ Page Language="vb" ValidateRequest="false" AutoEventWireup="false" CodeBehind="ExcelExport.aspx.vb" Inherits="Flex.ExcelExport" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
 
    </div>
    </form>
</body>
</html>

A parte de codificação, receberá o parâmetro htmltable, vindo do Flex que renderizará com o ContentType “application/vnd.ms-excel” com o nome de ExportaExcel.xls tudo isso dentro da função Page Load.

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Response.Clear()
        Response.ContentType = "application/vnd.ms-excel"
        Response.AddHeader("content-disposition", "attachment;filename=ExportaExcel.xls")
        Response.Charset = ""
        EnableViewState = False
        Request.ContentEncoding = System.Text.Encoding.UTF8
        Response.Write(Request("htmltable"))
        Response.End()
    End Sub

Dessa forma, quando o Flex enviar o htmltable, o navegador exibirá a janela padrão de download, para o arquivo recém criado.

E pronto! Sua aplicação Adobe Flex já exporta os dados de uma Datagrid para o Excel.

Dúvidas e feedbacks são sempre muito bem-vindos.

Sucesso e divirta-se.