« Pownce Invites! | Main | Happy Independence Day »

August 03, 2007

DataGridDataExporter: Export DataGrid data as CSV

A friend of mine, who is new to Adobe Flex, asked how can Datagrid-data be exported as CSV. I wrote a simple class, with one static-method, to do that. This is very basic implementation of CSV format.

Check out the example or download the code (with example).

DataGridDataExporter.as:

/**
	_________________________________________________________________________________________________________________

DataGridDataExporter is a util-class to export DataGrid's data into different format.
@class DataGridDataExporter (public)
@author Abdul Qabiz (mail at abdulqabiz dot com)
@version 0.01 (2/8/2007)
@availability 9.0+
@usage<code>DataGridDataExporter.<staticMethod> (dataGridReference)</code>
@example
<code>
var csvData:String = DataGridDataExporter.exportCSV (dg);
</code>

__________________________________________________________________________________________________________________

*/
package com.abdulqabiz.utils
{
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.collections.ArrayCollection;
import mx.collections.XMLListCollection;
import mx.collections.IList;
import mx.collections.IViewCursor;
import mx.collections.CursorBookmark;
public class DataGridDataExporter
{
public static function exportCSV(dg:DataGrid, csvSeparator:String="\t", lineSeparator:String="\n"):String
{
var data:String = "";
var columns:Array = dg.columns;
var columnCount:int = columns.length;
var column:DataGridColumn;
var header:String = "";
var headerGenerated:Boolean = false;
var dataProvider:Object = dg.dataProvider;
var rowCount:int = dataProvider.length;
var dp:Object = null;
var cursor:IViewCursor = dataProvider.createCursor ();
var j:int = 0;
//loop through rows
while (!cursor.afterLast)
{
var obj:Object = null;
obj = cursor.current;
//loop through all columns for the row
for(var k:int = 0; k < columnCount; k++)
{
column = columns[k];
//Exclude column data which is invisible (hidden)
if(!column.visible)
{
continue;
}
data += "\""+ column.itemToLabel(obj)+ "\"";
if(k < (columnCount -1))
{
data += csvSeparator;
}
//generate header of CSV, only if it's not genereted yet
if (!headerGenerated)
{
header += "\"" + column.headerText + "\"";
if (k < columnCount - 1)
{
header += csvSeparator;
}
}
}
headerGenerated = true;
if (j < (rowCount - 1))
{
data += lineSeparator;
}
j++;
cursor.moveNext ();
}
//set references to null:
dataProvider = null;
columns = null;
column = null;
return (header + "\r\n" + data);
}
}
}



DataGridCSVExportExample.mxml:-


<?xml version="1.0"?>
<!-- DataGrid control example. -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import com.abdulqabiz.utils.DataGridDataExporter;
private function exportCSV ():void
{
console.text = DataGridDataExporter.exportCSV (dg);
}
]]>

</mx:Script>
<mx:XMLList id="employees">
<employee>
<name>Christina Coenraets</name>
<phone>555-219-2270</phone>
<email>ccoenraets@fictitious.com</email>
<active>true</active>
</employee>
<employee>
<name>Joanne Wall</name>
<phone>555-219-2012</phone>
<email>jwall@fictitious.com</email>
<active>true</active>
</employee>
<employee>
<name>Maurice Smith</name>
<phone>555-219-2012</phone>
<email>maurice@fictitious.com</email>
<active>false</active>
</employee>
<employee>
<name>Mary Jones</name>
<phone>555-219-2000</phone>
<email>mjones@fictitious.com</email>
<active>true</active>
</employee>
</mx:XMLList>
<mx:Panel title="DataGrid Control Example" height="100%" width="100%"
paddingTop="10" paddingLeft="10" paddingRight="10">
<mx:Label width="100%" color="blue"
text="Select a row in the DataGrid control."/>
<mx:DataGrid id="dg" width="100%" height="100%" rowCount="5" dataProvider="{employees}">
<mx:columns>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="phone" headerText="Phone"/>
<mx:DataGridColumn dataField="email" headerText="Email"/>
</mx:columns>
</mx:DataGrid>
<mx:Button label="Export CSV" click="exportCSV ()"/>
<mx:TextArea id="console" width="100%" height="100%" />
</mx:Panel>
</mx:Application>


Technorati tags: , , , ,

Posted by Abdul Qabiz at August 3, 2007 04:10 PM

Comments

This can be quite handy .. one use I can think of off the top of my head is export as excel ... if you save csv content as a file with .xls extension and then open the file in excel .. excel will read it properly.

Thanks!

Posted by: Mrinal Wadhwa at August 4, 2007 06:25 AM

Instead of storing into textarea i want to store into csv file .

can you tel me how to do this ?

Thanks,
Megharaja S.H.

Posted by: Megharaja at September 7, 2007 03:38 PM

@Megharaja: If you are using AIR, you can save data in a file using File API. If your application runs in browser, you need to use FileReference API to send data to server-side-script, which would return (or just echo) the data back to client and client would be prompted to save the file...

Following is simple Flex code, you can write php or any other server-side support your own. I am posting here a Java-Servlet code, which i wrote to help someone else. Basically, server-side script takes data over HTTP/POST and returns the data with right MIME-TYPE...


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
		<![CDATA[
			import com.abdulqabiz.utils.DataGridDataExporter;
			import flash.net.FileReference;
			import flash.net.URLRequest;
			import flash.net.URLVariables;
			import flash.net.URLRequestMethod;
			private static const CSV_DOWNLOAD_END_POINT:String = "http://localhost/getcsv";
			private var downloadFileRef:FileReference = null;
			private function exportCSV ():void
			{
				var csvData:String = DataGridDataExporter.exportCSV (dg);
				console.text = csvData;
				if (csvData.length > 0)
				{
					downloadCSV (csvData);
				}
			}
		private function downloadCSV (csvData:String):void
		{
			if (!downloadFileRef)
			{
				downloadFileRef = new FileReference ();
			}
			var request:URLRequest = new URLRequest ();
			request.url = CSV_DOWNLOAD_END_POINT;
			request.method = URLRequestMethod.POST;
			request.data = new URLVariables ("csvdata=" + csvData);
			downloadFileRef.download (request, "file.csv");
		}
		]]>
	</mx:Script>
    <mx:XMLList id="employees">
        <employee>
            <name>Christina Coenraets</name>
            <phone>555-219-2270</phone>
         <email>ccoenraets@fictitious.com</email>
            <active>true</active>
        </employee>
        <employee>
            <name>Joanne Wall</name>
            <phone>555-219-2012</phone>
            <email>jwall@fictitious.com</email>
            <active>true</active>
        </employee>
        <employee>
            <name>Maurice Smith</name>
            <phone>555-219-2012</phone>            <email>maurice@fictitious.com</email>
            <active>false</active>
        </employee>
        <employee>
            <name>Mary Jones</name>
            <phone>555-219-2000</phone>            <email>mjones@fictitious.com</email>
            <active>true</active>
        </employee>
    </mx:XMLList>
    <mx:Panel title="DataGrid Control Example" height="100%" width="100%" 
        paddingTop="10" paddingLeft="10" paddingRight="10">
        <mx:Label width="100%" color="blue"
            text="Select a row in the DataGrid control."/>
        <mx:DataGrid id="dg" width="100%" height="100%" rowCount="5" dataProvider="{employees}">
            <mx:columns>
                <mx:DataGridColumn dataField="name" headerText="Name"/>
                <mx:DataGridColumn dataField="phone" headerText="Phone"/>
                <mx:DataGridColumn dataField="email" headerText="Email"/>
            </mx:columns>
        </mx:DataGrid>
    <mx:Button label="Export CSV" click="exportCSV ()"/>
    <mx:TextArea id="console" width="100%" height="100%" />
    </mx:Panel>
</mx:Application>


/**
 * 
 */
package com.abdulqabiz.util

import java.io.IOException;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* This servlet echos the data as CSV
*


*


*
* @author Abdul Qabiz
*/
public class GetCSV extends HttpServlet
{
/**
*
*/
private static final long serialVersionUID = 1L;

protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
doGet(req, res);
}

protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{

res.setHeader("Content-Type", "text/csv");
if (req.getParameter("csvdata") != null)
{
res.getOutputStream().print(req.getParameter("csvdata"));
}

}
}


Posted by: Abdul Qabiz at September 7, 2007 10:49 PM

Thank you so much for the code. I looked all over the place on the Internet and finally found this blog entry. It helped me tremendously. Thanks again.

Posted by: Jessica at October 12, 2007 03:00 AM

Thank you very much.But I also have some problems.What can I do then?
First,copy the data to clipboard. Then copy the data to EXCEL again.
This problems is Complex ,I think.
So I wish somebody can help me.

Posted by: Xinen at October 30, 2007 07:45 AM

if we will try to write this csv string in excel file and if any of the data fields contains "?" character..the approach fails...the data after the character ? is not written to the excel file.

Posted by: saurabh narula at December 8, 2007 07:34 PM

Thanks for the code .But to run the servlet you need to run LDS .Is there a way to acheive save operation without LDS

Posted by: Prasanth at January 4, 2008 04:22 PM

@Prasanth: That servlet is just for example, you can surely do the same using PHP/ASP or any server-side script...

It's probably lot simple in PHP, you have to just echo the content, received with GET/POST, to client and also set the HTTP headers in response...

This should work (just wrote not tested):-

savecsv.php:-

<?php
	header('Content-type: text/csv');
	$csvData = ($_POST['csvdata']) ? $_POST['csvdata'] : $_GET['csvdata'];
	echo  $csvData;
?>


You can send the data either via query-string (GET) or POST. I suggest, you use HTTP Post to send csvdata. I have not put the checks in there, you can always modify it to handle errors etc..

In above Flex code, change the value of constant "CSV_DOWNLOAD_END_POINT" to the URL of this php..

Hope that helps..

-abdul

Posted by: Abdul Qabiz at January 4, 2008 10:28 PM

its a good article. it helps me a lot.
i have some little problem while running this code.
iam using lcd services with java backend.
when i open the downloaded csv file, content of the single row comes in single cell(excel sheet box), its not differentiate the cell wise like in my file
'"Uyda ""assets/icons/phone_sound.png"" "" 4985623658"" ""Tue Jan 8 19:44:00 GMT 0530 2008"" ""0"" ""98.48898"" ""13.28463"" ""0"" ""123"""
'


but it must be differentiate by single cell, Could u please help me out in this

Posted by: uday at January 11, 2008 04:39 PM

Hey

Instead of copying data from the datagrid is it possible to convert the XML which is the input to CSV and download it ...

Posted by: Prasanth at January 15, 2008 11:32 AM

Hello,

How i can implement the same trick to send a dataProvider ( all datagrid information) to php? To use this information as $message to send email?

Can you help me?

Thks

Posted by: tugadot at April 25, 2008 06:28 AM

Hi Abdul,

Thanks a lot, it is what I was looking for export my reports to excel.

I have a lot of reports, In my reports I have labels showing the totals for the columns, and I needed to export the totals too.

Based in your code I created the function exportArrayCSV to send the totals as array, export to CSV and join to the datagrid exportCSV.

Could help somebody that have reports with totals.




public function exportArrayCSV (array:Array, csvSeparator:String="\t", lineSeparator:String="\n"):String
{
var data:String = "";
//loop through all columns for the row
for(var i:int = 0; i
{
data += "\""+ array[i] + "\"";
if(i {
data += csvSeparator;
}
}
return ("\r\n" + data);
}

//Sample how to join the datagrid exportCSV with the Totals exportCSV and assign to Clipboard.
private function exportCSV (dg:DataGrid):void
{
var strCSV : String;
var array : Array = new Array("Total","test");
strCSV = DataGridDataExporter.exportCSV(dg);
strCSV += exportArrayCSV(array);
System.setClipboard( strCSV )
}

Posted by: Paul Chavez at July 4, 2008 09:42 PM

public function exportArrayCSV (array:Array, csvSeparator:String="\t", lineSeparator:String="\n"):String
{
  var data:String = "";
  //loop through all columns for the row
  for(var i:int = 0; i 
  {
    data += "\""+ array[i] + "\"";
    if(i < (array.length -1))
    {
      data += csvSeparator;
    }
  }
  return ("\r\n" + data);
}

//Sample how to join the datagrid exportCSV with the Totals exportCSV and assign to Clipboard.
private function exportCSV (dg:DataGrid):void
{
var strCSV : String;
var array : Array = new Array("Total","test");
strCSV = DataGridDataExporter.exportCSV(dg);
strCSV += exportArrayCSV(array);
System.setClipboard( strCSV )
}

Posted by: Paul Chavez at July 4, 2008 09:57 PM

Why the client side csv data sending to server and then storing on client side. is there any direct approach without using server side script

Posted by: susan at July 8, 2008 04:05 PM

Hi!
I wanna know the Flex code to open a FILE OPEN dialog box when i click the Browse buttton designed in my Fornt end..

Posted by: sindhu at July 9, 2008 11:07 AM

Hai Abdul,

How can i export images (jpg,png) using Flex with java servlet?


Thanks.

Posted by: Muralidharan at July 9, 2008 06:12 PM

Hi
I have a xml file where im storing the book details like title,author etc.
In my application I have a option to add book details which should update the xml file.How can i get this done?

Thanx
Sheetal

Posted by: Sheetal at July 17, 2008 12:48 PM

Post a comment




Remember Me?


Please enter the security code you see here

(you may use HTML tags for style)