Trouble with Datagrid export CSV

6809
14
Jump to solution
02-06-2014 12:54 PM
Chang-HengYang
New Contributor III
Hi Everyone,

I found the post related to Datagrid to .csv file useful. I followed the instructions to have these codes in my web application and .ashx file. I could draw a box to select the features. However, it failed to export the file and a error message was shown in Chrome Web Console after clicking the button (Save to CSV),          Uncaught TypeError: Cannot read property 'structure' of undefined.

The web application is in jsbin

In addition, I have my web application file and MyWebHandler.ashx at the same folder

Please let me know how I fix this problem.

Many thanks,
Hank

The below code is the MyWebHandler.ashx file
public void ProcessRequest(HttpContext context)     {         context.Response.ContentType = "text/plain";         System.Collections.Specialized.NameValueCollection parameters = context.Request.Form;         string moduleName = parameters["module"];         string requestFeedback = "";         switch (moduleName)         {              case "ExportToExcel":                 EgisWeb.ExportHelper objExportCSVHelper = new EgisWeb.ExportHelper();                 objExportCSVHelper.CSV2Excel(parameters["csvdata"].ToString(), HttpContext.Current, parameters["title"].ToString());                 break;                      }         if (moduleName != "ExportToExcel")              context.Response.Write(requestFeedback);       }    public void CSV2Excel(string strCSV, HttpContext current, string strTitle)         {             current.Response.Clear();             strCSV = removeUniCodeSequenceCharacters(strCSV);             strCSV = System.Text.RegularExpressions.Regex.Unescape(strCSV);             current.Response.AddHeader("content-disposition", "attachment;filename=" + strTitle +"_"+DateTime.Now.ToString("ddmmyyyyHHMMSS") + ".csv");             current.Response.Charset = "";             current.Response.ContentType = "application/octet-stream";             current.Response.Write(strCSV);             current.Response.End();          }   private string removeUniCodeSequenceCharacters(string strWithEscapeSequence)         {             string strUse = "";             strUse = strWithEscapeSequence.Replace("%20", " ");             strUse = strUse.Replace("%2C", ",");             strUse = strUse.Replace("%27", "'");             strUse = strUse.Replace("%22", "\"");             strUse = strUse.Replace("%3F", "?");             strUse = strUse.Replace("%0A", "\n");             strUse = strUse.Replace("%28", "(");             strUse = strUse.Replace("%29", ")");             strUse = strUse.Replace("%26", "&");             strUse = strUse.Replace("%23", "#");             strUse = strUse.Replace("%3A", ":");             strUse = strUse.Replace("%21", "!");             strUse = strUse.Replace("%2D", "-");             strUse = strUse.Replace("%3B", ";");             strUse = strUse.Replace("%2A", "*");             strUse = strUse.Replace("%2B", "+");             strUse = strUse.Replace("%2E", ".");             strUse = strUse.Replace("%3C", "<");             strUse = strUse.Replace("%3D", "=");             strUse = strUse.Replace("%3E", ">");             strUse = strUse.Replace("%40", "@");             return strUse;         }
0 Kudos
1 Solution

Accepted Solutions
BrianLord1
Occasional Contributor
Hank,

I have implemented an "Export to CSV" tool in a couple of my javascript apps.  So once the datagrid is populated with my selected records I click on a button to export and save the csv file.  Here is how I have done it, although there is probably a better way since I am still learning...

I have a web handler file that I have called csv.ashx located in a folder I called "webservices" located in the project folder (i have included a screenshot of my folder structure).
<%@ WebHandler Language="C#" Class="csv" %>  using System; using System.Web;  public class csv : IHttpHandler {          public void ProcessRequest (HttpContext context) {         String content = "no data";         String filename = "MyFile";         if (context.Request["report"] != null)         {             try             {                 content = context.Request["report"].ToString();             }             catch             {             }         }         if (context.Request["filename"] != null)          {             try             {                 filename = context.Request["filename"].ToString() + "_" + DateTime.Now.ToString("MMMd_HH.mm");             }             catch             {             }         }          context.Response.ContentType = "text/csv";         context.Response.AddHeader("Content-disposition", "attachment;filename=" + filename + ".csv");         context.Response.Write(content);     }       public bool IsReusable {         get {             return false;         }     }  }


Now within the main html doc (although this should probably be moved to a separate javascript file) I have the following functions.

This is the function called when the user clicks the button and it basically takes everything in the datagrid and into a csv text string.
function exportCSVData() {                 var gridData = dijit.byId("gridCorners");                 var csvdatafield = dojo.byId("csvdata");                 dijit.byId('btnExport').setAttribute('checked', false);                                  var csvText = "";                 var fields = gridData.structure[0].cells[0];                 if (fields != null && fields.length > 0) {                     for (var ifldCnt = 0; ifldCnt < fields.length; ifldCnt++) {                         if (ifldCnt == 0) {                             csvText = fields[ifldCnt].name;                         } else {                             csvText += "," + fields[ifldCnt].name;                         }                     }                     csvText += "\n";                     var fieldValue = "";                      for (var i = 0; i < gridData.rowCount; i++) {                         var featureAttribute = gridData.store._arrayOfAllItems;                         var columnVal;                         for (var ifldCnt = 0; ifldCnt < fields.length - 1; ifldCnt++) {                             fieldValue = "";                              columnVal = featureAttribute[fields[ifldCnt].field][0];                             if (columnVal != null && columnVal != "") {                                 fieldValue = columnVal;                             }                             if (isNaN(fieldValue)) {                                 if (fieldValue.indexOf('\'') != -1 || fieldValue.indexOf('\"') != -1 || fieldValue.indexOf(',') != -1) {                                     if (fieldValue.indexOf('\"') != -1) {                                         fieldValue = fieldValue.replace("\"", "\"\"");                                     }                                     fieldValue = "\"" + fieldValue + "\"";                                 }                             }                             if (ifldCnt == 0) {                                 csvText += fieldValue;                             } else {                                 csvText += "," + fieldValue;                             }                         }                         csvText += "\n";                     }                     getCSV(csvText)                 }             }


And this is what actually submits the form to the webhandler.  There is also included code to prompt the user to name the file and if the do not they get an alert.
function getCSV(csvText) {                 //Get the stored CSV                 var url = "webservices/csv.ashx";                  var data = csvText;                  var f = dojo.byId("downloadform");                 f.action = url;                 dojo.byId("reportinput").value = data;                 userChoice = prompt("Choose a File Name (the date and time will be added to end of filename):");                 if (userChoice != null && userChoice != 'undefined' && userChoice != '') {                     dojo.byId("filename").value = userChoice;                     f.submit();                 } else if (userChoice == 'undefined') {                     alert("You must type in a filename!");                 } else if (userChoice == '') {                     alert("You must type in a filename!");                 } else if (userChoice == null) {                     alert("The CSV Export was Canceled");                 }             }


And here is the html for the hidden download form.
[HTML]<form method="post" action="" style="height: 0px; width: 0px; display: none;" class="dlform"
            id="downloadform" target="_blank">
                <input type="hidden" name="report" class="ri" id="reportinput" value="" />
                <input type="hidden" name="filename" class="fn" id="filename" value="" />
                <input type="hidden" name="s" class="s" id="s" value="" />
                <input type="hidden" name="numberofcolumns" class="rit" id="numberofcolumns" value="pdf" />
        </form>[/HTML]

I hope this helps.  As I mentioned above, there might be a better way to accomplish this.  This app has been up and running for a while now and I haven't had any users inform me of issues with exporting so it does work reliably.

Thanks,
Mark

View solution in original post

0 Kudos
14 Replies
BrianLord1
Occasional Contributor
Hank,

I have implemented an "Export to CSV" tool in a couple of my javascript apps.  So once the datagrid is populated with my selected records I click on a button to export and save the csv file.  Here is how I have done it, although there is probably a better way since I am still learning...

I have a web handler file that I have called csv.ashx located in a folder I called "webservices" located in the project folder (i have included a screenshot of my folder structure).
<%@ WebHandler Language="C#" Class="csv" %>  using System; using System.Web;  public class csv : IHttpHandler {          public void ProcessRequest (HttpContext context) {         String content = "no data";         String filename = "MyFile";         if (context.Request["report"] != null)         {             try             {                 content = context.Request["report"].ToString();             }             catch             {             }         }         if (context.Request["filename"] != null)          {             try             {                 filename = context.Request["filename"].ToString() + "_" + DateTime.Now.ToString("MMMd_HH.mm");             }             catch             {             }         }          context.Response.ContentType = "text/csv";         context.Response.AddHeader("Content-disposition", "attachment;filename=" + filename + ".csv");         context.Response.Write(content);     }       public bool IsReusable {         get {             return false;         }     }  }


Now within the main html doc (although this should probably be moved to a separate javascript file) I have the following functions.

This is the function called when the user clicks the button and it basically takes everything in the datagrid and into a csv text string.
function exportCSVData() {                 var gridData = dijit.byId("gridCorners");                 var csvdatafield = dojo.byId("csvdata");                 dijit.byId('btnExport').setAttribute('checked', false);                                  var csvText = "";                 var fields = gridData.structure[0].cells[0];                 if (fields != null && fields.length > 0) {                     for (var ifldCnt = 0; ifldCnt < fields.length; ifldCnt++) {                         if (ifldCnt == 0) {                             csvText = fields[ifldCnt].name;                         } else {                             csvText += "," + fields[ifldCnt].name;                         }                     }                     csvText += "\n";                     var fieldValue = "";                      for (var i = 0; i < gridData.rowCount; i++) {                         var featureAttribute = gridData.store._arrayOfAllItems;                         var columnVal;                         for (var ifldCnt = 0; ifldCnt < fields.length - 1; ifldCnt++) {                             fieldValue = "";                              columnVal = featureAttribute[fields[ifldCnt].field][0];                             if (columnVal != null && columnVal != "") {                                 fieldValue = columnVal;                             }                             if (isNaN(fieldValue)) {                                 if (fieldValue.indexOf('\'') != -1 || fieldValue.indexOf('\"') != -1 || fieldValue.indexOf(',') != -1) {                                     if (fieldValue.indexOf('\"') != -1) {                                         fieldValue = fieldValue.replace("\"", "\"\"");                                     }                                     fieldValue = "\"" + fieldValue + "\"";                                 }                             }                             if (ifldCnt == 0) {                                 csvText += fieldValue;                             } else {                                 csvText += "," + fieldValue;                             }                         }                         csvText += "\n";                     }                     getCSV(csvText)                 }             }


And this is what actually submits the form to the webhandler.  There is also included code to prompt the user to name the file and if the do not they get an alert.
function getCSV(csvText) {                 //Get the stored CSV                 var url = "webservices/csv.ashx";                  var data = csvText;                  var f = dojo.byId("downloadform");                 f.action = url;                 dojo.byId("reportinput").value = data;                 userChoice = prompt("Choose a File Name (the date and time will be added to end of filename):");                 if (userChoice != null && userChoice != 'undefined' && userChoice != '') {                     dojo.byId("filename").value = userChoice;                     f.submit();                 } else if (userChoice == 'undefined') {                     alert("You must type in a filename!");                 } else if (userChoice == '') {                     alert("You must type in a filename!");                 } else if (userChoice == null) {                     alert("The CSV Export was Canceled");                 }             }


And here is the html for the hidden download form.
[HTML]<form method="post" action="" style="height: 0px; width: 0px; display: none;" class="dlform"
            id="downloadform" target="_blank">
                <input type="hidden" name="report" class="ri" id="reportinput" value="" />
                <input type="hidden" name="filename" class="fn" id="filename" value="" />
                <input type="hidden" name="s" class="s" id="s" value="" />
                <input type="hidden" name="numberofcolumns" class="rit" id="numberofcolumns" value="pdf" />
        </form>[/HTML]

I hope this helps.  As I mentioned above, there might be a better way to accomplish this.  This app has been up and running for a while now and I haven't had any users inform me of issues with exporting so it does work reliably.

Thanks,
Mark
0 Kudos
Chang-HengYang
New Contributor III
Hi Mark,

Thank you for your time in advance. Almost 99% done, I clicked the button and this popout info showed that I need to name this zipped file(Error.jpg). After clicking the button, I just saw the content of the .ashx file(error.jpg). It looks like my internet server does no support ASP.Net. My coworker told me that I am using the Linux sever. I wonder if your internet server is windows server.

Thanks,
Hank
0 Kudos
BrianLord1
Occasional Contributor
Yes, our web server is windows. 

I am not really sure what what you would need to change to get it tow work on a Linux server.  That is an area I do not know much.  I would say, assuming the rest of my code worked you should have a properly formatted csv text string.  Now all you need to do is find a web handler that will work on a Linux server.

A quick search on stackoverflow found this thread that might be of some use to you.
http://stackoverflow.com/questions/1116175/running-asp-net-on-a-linux-based-server

Good Luck.

Mark
0 Kudos
Chang-HengYang
New Contributor III
Hi Mark,

Again thank you for the help. My server manager may not want to have a windows server in my department. Therefore, I will go for the other method"dojox.grid.EnhancedGrid". However, you post related to CSV export would be very helpful for these JS API developers. I will let you know when I successfully have the export to CSV function in  dojox.grid.EnhancedGrid.

Keep in touch,

Hank
0 Kudos
MayJeff
Occasional Contributor

Do you able to complete your task?  Thanks.

0 Kudos
Chang-HengYang
New Contributor III

Hi May,

I used another route to finish this work. However, I am not sure if my modified application fits your requirement. Basically, I have a table to display all the data and the filter window could provide users filter data by conditions users set. The post here is for users to drag a box and download the data in CSV/Excel format. However, there is a problem with the web server. I can not pass the website link. 

0 Kudos
MayJeff
Occasional Contributor

Thanks Yang.  I also got the same problem with the web.config file.  I try to use EnhancedGrid and posted a thread here: Can't get export datagrid to csv

Which method do you use?  Can you show me how do you do it?  Thanks.

0 Kudos
Chang-HengYang
New Contributor III

Hi May,

I am wondering if you would like a similar web application like the website (Gridx Export ). If yes, I could show you the workflow. However, if you prefer the user could drag the box and download the data in csv/excel format on your web map, I am still working on it.

Please let me know your opinions.

Hank

0 Kudos
MayJeff
Occasional Contributor

Actually I just need to export the search results to csv just like JSFiddle I modified:

Edit fiddle - JSFiddle

I don't need to drag a box on a map to get the data to export to csv format.  If you could, would be greatly appreciate.

Thanks.

0 Kudos