Download/Save CSV file - PapaParse
Asked Answered
D

2

11

PROBLEM:
Downloaded CSV file is blank (unparse() method to conver array/JSON to CSV).

DETAIL:
Papaparse is working fine when parse CSV file to JavaScript array. But when I feed that array data or JSON data to unparse() method, its not working.

Angular JS method:

$scope.downloadCSV = function(){
    var csv = Papa.unparse($scope.final_array);
    console.log($scope.final_array);
    console.log(csv);
    var csvData = new Blob([csv], {type: 'text/csv;charset=utf-8;'});
    var csvURL =  null;
    if (navigator.msSaveBlob) {
        csvURL = navigator.msSaveBlob(csvData, 'download.csv');
    } else {
        csvURL = window.URL.createObjectURL(csvData);
    }
    var tempLink = document.createElement('a');
    tempLink.href = csvURL;
    tempLink.setAttribute('download', 'download.csv');
    tempLink.click();
}

$scope.final_array contains data as:

enter image description here

On above code, console.log(csv); displays blank on the console.

In short: var csv = Papa.unparse($scope.final_array); is not working.

UPDATE
The posted array help me to generate following table and the button "Save Generated CSV" is not working and the code posted is for the this action button. enter image description here

Distraint answered 8/9, 2018 at 23:41 Comment(2)
How can I copy that array from the console ??Distraint
Also would be great to add tempLink.remove() at the end of the function to prevent them building up on the page.Joke
S
8

You are trying to unparse an array of arrays which is just plain data without the column names.

To use the column names you might want to use the array of objects version. Rewrite your final_array as:

$scope.final_array = [
    { question1: "A", question2: "A", question3: "mike" },
    { question1: "A B", question2: "B", question3: "dan" },
];

Alternatively you can separate your column names and the data in a single object as follows:

$scope.final_object = {
    fields: [ "question1", "question2", "question3" ],
    data: [
        [ "A", "A", "mike" ],
        [ "A B", "B", "dan", ],
    ],
};

If you need to convert $scope.final_array maybe the following snippet will help you:

function convertFinal(arrOfArr) {
    return arrOfArr.map(function(arr) {
        var obj = {};
        for(var key in arr) {
            if(arr.hasOwnProperty(key)) {
                obj[key] = arr[key];
            }
        }
        return obj;
    });
}

var csv = Papa.unparse(convertFinal($scope.final_array));
Semifinal answered 11/9, 2018 at 20:42 Comment(3)
Thanks, it worked but if you see my array, there is $$hashKey:object:47 which is last element of each array set. these all also being populated on the CSV file. How to ignore that key/column title ($$hashKey)Distraint
You didn't post your raw data, only screenshots of websites and interpreter outputs - I literally have no idea of how you got your array and can only speculate. You'll have to provide a minimal reproducible example (with emphasis on complete).Semifinal
I got filtered that out and perfect now. Thanks again.Distraint
I
13

Your mistake: if we view your console screenshot we will see that you have some mishmash in your array code from arrays and objects. In your code you have some like this:

var array =
[
    [question1: "A", question2: "A"],
    [question1: "A B", question2: "B"]
];

But it is incorrect and must to be some like this:

var array =
[
    {question1: "A", question2: "A"},
    {question1: "A B", question2: "B"}
];

You have to correct it.

Working example

See this Codepen demo because StackOverflow snippets are in sandbox and because of this do not work.

var array =
[
    {
        question1: "А",
        question2: "А",
        question3: "mike",
        question1_A: "TRUE",
        question1_B: "FALSE",
        question1_C: "FALSE",
        question1_D: "FALSE"
    },
    {
        question1: "A В",
        question2: "В",
        question3: "dan",
        question1_A: "TRUE",
        question1_B: "TRUE",
        question1_C: "FALSE",
        question1_D: "FALSE"
    },
    {
        question1: "B C D",
        question2: "А В С",
        question3: "tango",
        question1_A: "FALSE",
        question1_B: "TRUE",
        question1_C: "TRUE",
        question1_D: "TRUE"
    },
    {
        question1: "A D",
        question2: "С",
        question3: "charlie",
        question1_A: "TRUE",
        question1_B: "FALSE",
        question1_C: "FALSE",
        question1_D: "TRUE"
    },
    {
        question1: "В",
        question2: "А",
        question3: "bob",
        question1_A: "FALSE",
        question1_B: "TRUE",
        question1_C: "FALSE",
        question1_D: "FALSE"
    },
    {
        question1: "C D",
        question2: "А",
        question3: "john",
        question1_A: "FALSE",
        question1_B: "FALSE",
        question1_C: "FALSE",
        question1_D: "FALSE"
    }
];


function downloadCSV()
{
    var csv = Papa.unparse(array);

    var csvData = new Blob([csv], {type: 'text/csv;charset=utf-8;'});
    var csvURL =  null;
    if (navigator.msSaveBlob)
    {
        csvURL = navigator.msSaveBlob(csvData, 'download.csv');
    }
    else
    {
        csvURL = window.URL.createObjectURL(csvData);
    }

    var tempLink = document.createElement('a');
    tempLink.href = csvURL;
    tempLink.setAttribute('download', 'download.csv');
    tempLink.click();
}
<script src="https://www.papaparse.com/resources/js/papaparse.js"></script>
<input type="button" value="download CSV" onclick="downloadCSV()">

For further information see the documentation from Papa's unparse function.

Incident answered 12/9, 2018 at 8:9 Comment(10)
how can i make my array object as yours array?Distraint
@webDev, I would like to answer your question, but I do not know how it is possible that your have some corrupt object like this because in normal JS you will get an error with this object. But may be it is because you use Angular JS (I am not an experte in Angular JS). Try to print your array in the console with console.log(JSON.stringify(array, null, '\t'));Incident
Thanks for the answer, I tried the first answer posted because @BeyelerStudios posted first. That solved my problem. But the idea/answer of yours is correct too that's why +1. ThanksDistraint
Hey actually I don't have any idea on JS arrays, but i did some array manipulations based on how we do using other programming language. I am create each array as new_data[h] = 'FALSE'; and pushing that array to a blank final array as $scope.final_array.push(new_data); Thats how I got that kinda array. Thanks once again.Distraint
and yea see the conversion process posted by @BeyelerStudios above, you might get the idea how that kind of array had been generated by my code.Distraint
I will share a jsfiddle with you later to show how you can get what looks like an array of arrays like that.Drumm
@KirkLarkin, but do you know it just now or not? Because a few hours ago you wrote that this is impossible. And if you know it then share it with us on codepen.io please.Incident
To clear things up here - the comment I made about being impossible was the first code snippet from your answer here. The syntax you used isn't valid as you can't declare an array with named properties like that. The CodePen I've linked shows how you can achieve a similar result, but actually the array itself is empty.Drumm
@KirkLarkin, but one thing which I would like to know: how did you get this idea to build it on this way? It is your own idea or did you found it somewhere, or may be did you asked it by somebody?Incident
I just thought about it for a while and tried it out in the console. I was aware that properties could be added to arrays but didn’t really think about it until I started messing around with it. :)Drumm
S
8

You are trying to unparse an array of arrays which is just plain data without the column names.

To use the column names you might want to use the array of objects version. Rewrite your final_array as:

$scope.final_array = [
    { question1: "A", question2: "A", question3: "mike" },
    { question1: "A B", question2: "B", question3: "dan" },
];

Alternatively you can separate your column names and the data in a single object as follows:

$scope.final_object = {
    fields: [ "question1", "question2", "question3" ],
    data: [
        [ "A", "A", "mike" ],
        [ "A B", "B", "dan", ],
    ],
};

If you need to convert $scope.final_array maybe the following snippet will help you:

function convertFinal(arrOfArr) {
    return arrOfArr.map(function(arr) {
        var obj = {};
        for(var key in arr) {
            if(arr.hasOwnProperty(key)) {
                obj[key] = arr[key];
            }
        }
        return obj;
    });
}

var csv = Papa.unparse(convertFinal($scope.final_array));
Semifinal answered 11/9, 2018 at 20:42 Comment(3)
Thanks, it worked but if you see my array, there is $$hashKey:object:47 which is last element of each array set. these all also being populated on the CSV file. How to ignore that key/column title ($$hashKey)Distraint
You didn't post your raw data, only screenshots of websites and interpreter outputs - I literally have no idea of how you got your array and can only speculate. You'll have to provide a minimal reproducible example (with emphasis on complete).Semifinal
I got filtered that out and perfect now. Thanks again.Distraint

© 2022 - 2024 — McMap. All rights reserved.