locked
How to Save HTML Table Data in .csv file using FileSavePicker()

    Question

  • I have data in my Html Table I want to save it in .csv file using FileSavePicker() I have tried the following code but it is not working.

    function SaveFile()
        {
            
            var MyFileSavePicker = new Windows.Storage.Pickers.FileSavePicker();
            MyFileSavePicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.documentsLibrary;
            
            MyFileSavePicker.fileTypeChoices.insert("",[".csv"]);
            
            MyFileSavePicker.pickSaveFileAsync().then(function (file) {
                if (file) {
                    Windows.Storage.CachedFileManager.deferUpdates(file);
                    var table = document.getElementById("OutputTable");
                    var fixCSVField = function (value) {
                        var fixedValue = value;
                        var addQuotes = (value.indexOf(',') !== -1) || (value.indexOf('\r') !== -1) || (value.indexOf('\n') !== -1);
                        var replaceDoubleQuotes = (value.indexOf('"') !== -1);
    
                        if (replaceDoubleQuotes) {
                            fixedValue = fixedValue.replace(/"/g, '""');
                        }
                        if (addQuotes || replaceDoubleQuotes) {
                            fixedValue = '"' + fixedValue + '"';
                        }
                        return fixedValue;
                    };
    
                    var tableToCSV = function (table) {
                        var data = "";
                        for (var i = 0, row; row = table.rows[i]; i++) {
                            for (var j = 0, col; col = row.cells[j]; j++) {
                                data = data + (j ? ',' : '') + fixCSVField(col.innerHTML);
                            }
                            data = data + "\r\n";
                        }
                        return data;
                    };
                    var uri = { csv: 'data:application/csv;base64,' };
                    var base64 = function (s) {
                        return window.btoa(unescape(encodeURIComponent(s)));
                    };
                    var hrefvalue = uri.csv + base64(tableToCSV);
                    file = hrefvalue;
                    // write to file
                    Windows.Storage.FileIO.writeTextAsync(file, file.name).done(function () {
                        // Let Windows know that we're finished changing the file so the other app can update the remote version of the file.
                        // Completing updates may require Windows to ask for user input.
                        Windows.Storage.CachedFileManager.completeUpdatesAsync(file).done(function (updateStatus) {
                            if (updateStatus === Windows.Storage.Provider.FileUpdateStatus.complete) {
                                WinJS.log && WinJS.log("File " + file.name + " was saved.", "sample", "status");
                            } else {
                                WinJS.log && WinJS.log("File " + file.name + " couldn't be saved.", "sample", "status");
                            }
                        });
                    });
                } else {
                    WinJS.log && WinJS.log("Operation cancelled.", "sample", "status");
                }
            });
    
        }


    samEE


    Tuesday, July 15, 2014 5:05 AM

Answers

  • Do this:
       var Result = tableToCSV(table);
                // write to file
                Windows.Storage.FileIO.writeTextAsync(file,Result).done(function () {


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, July 17, 2014 3:23 PM
    Moderator

All replies

  • Which part is failing? Please analyze this and let us know what exactly the problem is.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Tuesday, July 15, 2014 7:04 PM
    Moderator
  • I have debugged the code by putting break points, and the control is not entering in

    MyFileSavePicker.pickSaveFileAsync().then(function (file) {

    if(file){


    What should I do now?


    samEE



    Wednesday, July 16, 2014 7:11 AM
  • I see the problem at this line of code:

     Windows.Storage.FileIO.writeTextAsync(file, file.name).done(function () {

    Notice that the exception is: Type mismatch.

    The expected signature for writeTextAsync is:
    public static IAsyncAction WriteTextAsync(
      IStorageFile file,
      string contents
    )

    You're passing in these parameters:
    Name/Value/Type
    file/"data:application/csv;base64,ZnVuY3Rpb24gKHRhYmxlKSB7DQogICAgICAgICAgICAgICAgdmFyIGRhdGEgPSAiIjsNCiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgcm93OyByb3cgPSB0YWJsZS5yb3dzW2ldOyBpKyspIHsNCiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDAsIGNvbDsgY29sID0gcm93LmNlbGxzW2pdOyBqKyspIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhICsgKGogPyAnLCcgOiAnJykgKyBmaXhDU1ZGaWVsZChjb2wuaW5uZXJIVE1MKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSArICJcclxuIjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgcmV0dXJuIGRhdGE7DQogICAgICAgICAgICB9"/String
    file.name/undefined/Undefined

    Do you see the problem now?


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Wednesday, July 16, 2014 3:02 PM
    Moderator
  • Matt,

    Sir can you please Explain it that what should be

    file.name
    I have changed it with

     Windows.Storage.FileIO.writeTextAsync(file, hrefvalue).done(function () {

    as all the data after conversion is assigning to this variable but it still not works, garbage data is stored in the file.

    and where should I put the signature u Suggested as it's JavaScript where can I put
    public static


    samEE


    Thursday, July 17, 2014 3:55 AM
  • I have two questions for you:

    1) What's the purpose in doing this?  This content is not CSV when it's done.

    var uri = { csv: 'data:application/csv;base64,' };
    var base64 = function (s) {
      return window.btoa(unescape(encodeURIComponent(s)));
    };
    var hrefvalue = uri.csv + base64(tableToCSV);


    2) Why are you changing the value of file in this line?  You picked the file to save and now you're discarding it:

    file = hrefvalue;

    In my opinion, the function should be:

    Windows.Storage.FileIO.writeTextAsync(file, tableToCSV).done(function () {


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.


    Thursday, July 17, 2014 11:57 AM
    Moderator
  • Matt,

    Sir

    1) Those lines of code are used in Browser to Download .csv but I think it was a mistake to use it in the app as I am using File Save Picker for that purpose.(Am I Right?). Thank you for that.

    2) The reason to discard that piece of code is that I didn't know that a variable can be directly passed to

    Windows.Storage.FileIO.writeTextAsync(file, varname).done(function () {

    for writing in the file .

    And I have used

    Windows.Storage.FileIO.writeTextAsync(file, tableToCSV).done(function () {

    the whole body of the function i.e.

    function (table) {  
                      var data = "";                    
    for (var i = 0, row; row = table.rows[i]; i++) {
                            for (var j = 0, col; col =row.cells[j]; j++) 
    {                
                data = data + (j ? ',' : '') + fixCSVField
    (col.innerHTML);                        
    }                  
          data = data
    + "\r\n";                    }                    
    return data;                };
    is stored in the .csv file


    samEE



    Thursday, July 17, 2014 1:31 PM
  • Do this:
       var Result = tableToCSV(table);
                // write to file
                Windows.Storage.FileIO.writeTextAsync(file,Result).done(function () {


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, July 17, 2014 3:23 PM
    Moderator
  • Thnkx a lot sir it worked

    There is just a little problem left as I am using the following code to generate my table

    function (CSVText) {
                            if (!CSVText) return;
                            var CSVLines = CSVText.split("\r\n");
                            for (var i = 0; i < CSVLines.length - 1; i++) {
                                OutputTableRows += "<tr>";
                                var CSVValues = CSVLines[i].split(",");
                                for (var j = 0; j < CSVValues.length ; j++) {
                                    if ((j == CSVValues.length - 1) && i > 0) {
                                        tableRow = '<td style="width:200px;border-bottom:groove;"><input type="text" value="VALUE"/></td>';
                                        tableRow = tableRow.replace('VALUE', CSVValues[j]); 
                                        OutputTableRows += tableRow;
                                    }
                                    else {
                                        OutputTableRows += '<td style="width:200px; border-bottom:groove;">'  + CSVValues[j]  + "</td>";
                                    }
                                }
                                OutputTableRows += "</tr>";
                            }
                            document.getElementById("OutputTable").innerHTML = OutputTableRows;
                        }

    u helped me with the above code at the following link

    http://social.msdn.microsoft.com/Forums/en-US/159112e3-beb2-44ce-a4e1-f921795d1b9e/import-data-form-csv-file-to-html-table?forum=winappswithhtml5

    The Problem is that the data that is stored contains the

    <input type="text" value="VALUE"/></td>';

    Instead of text. As show below


    samEE

    Thursday, July 17, 2014 4:49 PM
  • It's doing exactly what it's told to do.  What value do you want?

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, July 17, 2014 5:33 PM
    Moderator
  • I don't want it

    <input type="text" value="VALUE"/></td>';

    to be in the output .csv file.

    There should the value that is entered by the user. What changes should I made ?


    samEE

    Thursday, July 17, 2014 7:06 PM
  • Matt,

    I have also tried this

    var x = document.createElement("Input");
    tableRow = '<td style="width:200px;border-bottom:groove;">' + document.body.appendChild(x); + '</td>';

    But it is also not working . Some suggestions Plz?


    samEE

    Saturday, July 19, 2014 6:38 AM
  • Use javascript to retrieve the value of that control before putting it in the csv file.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Monday, July 28, 2014 3:11 PM
    Moderator
  • Matt,

    Sorry, I can't understand what you are trying to say please elaborate ?


    samEE

    Monday, July 28, 2014 7:41 PM