It looks like the dataTableToCsv method stops when it encounters a "#"
Because this is a google defined method, what would be the best way to escape this sign or even better, correct this?
csvContent = csvColumns + google.visualization.dataTableToCsv(data);
Here's a test. Notice that in this example, it will stop at Column D second row.
google.charts.load('current', {
callback: drawBasic,
packages: ['table']
});
function drawBasic() {
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1w1vaFAPTE440jc2cpYGftXSaPwGxU_x7iQRSGK35oYc/edit#gid=0'
);
query.setQuery('SELECT *');
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
var options = {
title: 'test'
}
var chart = new google.visualization.Table(document.getElementById('chart_div'));
chart.draw(data, options)
$('#Export').on('click', function () {
var csvColumns;
var csvContent;
var downloadLink;
var fileName;
// build column headings
csvColumns = '';
for (var i = 0; i < data.getNumberOfColumns(); i++) {
csvColumns += data.getColumnLabel(i);
if (i < (data.getNumberOfColumns() - 1)) {
csvColumns += ',';
}
}
csvColumns += '\n';
// build data rows
csvContent = csvColumns + google.visualization.dataTableToCsv(data);
// download file
fileName = 'data.csv';
downloadLink = document.createElement('a');
downloadLink.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvContent);
downloadLink.download = fileName;
raiseEvent(downloadLink, 'click');
downloadLink = null;
function raiseEvent(element, eventType) {
var eventRaised;
if (document.createEvent) {
eventRaised = document.createEvent('MouseEvents');
eventRaised.initEvent(eventType, true, false);
element.dispatchEvent(eventRaised);
} else if (document.createEventObject) {
eventRaised = document.createEventObject();
element.fireEvent('on' + eventType, eventRaised);
}
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<button id="Export" title="Download to CSV">Download to CSV</Button>
<div id="chart_div"></div>
You want to download the values of Spreadsheet as a CSV file.
In your current issue, the CSV data is not completed. It's "it will stop at Column D second row".
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
It was found that when I saw csvContent of csvContent = csvColumns + google.visualization.dataTableToCsv(data);, the CSV data has the whole values from the Spreadsheet. So in this modification, csvContent is converted to a blob and it is downloaded.
Modified script:
When your script is modified, please modify as follows.
From:
downloadLink.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvContent);
To:
downloadLink.href = URL.createObjectURL(new Blob([csvContent], {type: "text/csv"}));
or
downloadLink.href = window.URL.createObjectURL(new Blob([csvContent], {type: "text/csv"}));
References:
Blob
URL.createObjectURL()
If I misunderstood your question and this was not the direction you want, I apologize.
I am using the code below to export nearly 3,000 JSON records to CSV format. It is working in Chrome and Opera but not in Safari, IE, or Firefox. I have an "out of browser memory" issue.
Why doesn't it work in those browsers?
How can I export many (e.g. 90,000) records in any browser?
function exportAll(JSONData, ReportTitle, ShowLabel) {
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '';
CSV += ReportTitle + '\r\n\n';
if (ShowLabel) {
var row = "";
for (var index in arrData[0]) {
row += index + ',';
}
row = row.slice(0, -1);
CSV += row + '\r\n';
}
for (var i = 0; i < arrData.length; i++) {
var row = "";
for (var index in arrData[i]) {
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
var csv = CSV;
blob = new Blob([csv], {
type: 'text/csv'
});
var csvUrl = window.webkitURL.createObjectURL(blob);
var filename = 'GraphsData.csv';
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
$('#lnkDwnldLnk')[0].click();
document.body.removeChild(link);
}
I Wrote a javascript function to export data into csv formate . Currently getting data in csv file but not in proper ways. I mean they are not in there respective columns. I have a table on page and want data inside that table to be exported to csv file.
function createCSV() {
alert('entered');
var csv = '';
$('table[id$="table"]').find('tr:has(th)').each(function() {
var listThValues = [];
$(this).find('th').each(function() {
listThValues.push($(this).find('div').html());
});
csv += listThValues.join() + '\r\n';
});
$('table[id$="table"]').find('tr:has(td)').each(function() {
var listThValues = [];
$(this).find('td').each(function() {
listThValues.push($(this).html());
});
csv += listThValues.join() + '\r\n';
});
//var filename = 'file.csv';
//var blobby = new Blob([csv], {type: 'text/plain'});
var csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);
$("#export").attr({
'download': 'test.csv'
,'href': csvData
,'target' : '_blank' //if you want it to open in a new window
});
I've been trying this for a while now, but I can't get my head around what's wrong. Maybe I've tried so many ways that I'm not even sure this piece of code is right anymore.
Basically I'm trying to use the track.scrobble method from the Last.fm API, sending a batch of tracks.
That's the code I have, and it's always returning Invalid method signature. Does anyone can give me some help here, please?
UPDATE
Based on mccannf answer, I've changed the code, but am still getting the error:
var apiUrl = "http://ws.audioscrobbler.com/2.0/";
var apiMethod = "track.scrobble";
var apiKey = "MY_API_KEY";
var apiSecret = "MY_API_SECRET";
var key = "MY_SESSION_KEY";
var apiSig = "";
var lastfmScrobble = function (data) {
var dataToScrobble = setTiming(data);
var albums = [];
var artists = [];;
var timestamps = [];
var tracks = [];
var dataToHash = "";
for (var i = 0; i < dataToScrobble.tracks.length; i++) {
albums["album["+ i.toString() + "]"] = dataToScrobble.album;
artists["artist[" + i.toString() + "]"] = dataToScrobble.artist;
timestamps["timestamp[" + i.toString() + "]"] = dataToScrobble.tracks[i].split("|")[1];
tracks["track[" + i.toString() + "]"] = dataToScrobble.tracks[i].split("|")[0];
}
dataToHash += albums.sort().join("");
dataToHash += "api_key" + apiKey;
dataToHash += artists.sort().join("");
dataToHash += "method" + apiMethod;
dataToHash += "sk" + key;
dataToHash += timestamps.sort().join("");
dataToHash += tracks.sort().join("");
dataToHash += apiSecret;
apiSig = $.md5(unescape(encodeURIComponent(dataToHash)));
var songsToScrobble = {};
$.extend(songsToScrobble,
albums.sort(),
{ api_key: apiKey },
{ api_sig: apiSig },
artists.sort(),
{ method: apiMethod },
{ sk: key },
timestamps.sort(),
tracks.sort());
$.ajax({
url: apiUrl,
type: "POST",
data: songsToScrobble,
success: function (data) {
console.log(data);
}
});
}
Now the object sent has the correct format (JSON). What can still be wrong?
I did a quick sample JS Fiddle of your code.
The dataToHash is like this:
album[0]Achtung Babyalbum[1]Achtung Babyapi_keyxxxBLAHxxxartist[0]U2artist[1]U2methodtrack.scrobbleskkkkFOOkkktimestamp[0]1379368800timestamp[1]1379369000track[0]Onetrack[1]The FlymmmySecrettt
The songsToScrobble variable in the code above looked like this:
{ "album": [
"album[0]Achtung Baby",
"album[1]Achtung Baby"
],
"api_key":"xxxBLAHxxx",
"api_sig":"8dbc147e533411a41ba9169f59e65b3a",
"artist":["artist[0]U2","artist[1]U2"],
"method": "track.scrobble",
"sk":"kkkFOOkkk"
"timestamp": [
"timestamp[0]1379368800",
"timestamp[1]1379369000"
],
"track": [
"track[0]One",
"track[1]The Fly"
]
}
I believe songsToScrobble should look like this:
{ "album[0]": "Achtung Baby",
"album[1]": "Achtung Baby",
"api_key":"xxxBLAHxxx",
"api_sig":"8dbc147e533411a41ba9169f59e65b3a",
"artist[0]": "U2",
"artist[1]": "U2",
"method": "track.scrobble",
"sk":"kkkFOOkkk"
"timestamp[0]": "1379368800",
"timestamp[1]": "1379369000",
"track[0]": "One",
"track[1]": "The Fly"
}
Only other minor point is to make sure dataToHash is UTF-8 encoded before you convert to MD5 hash.
Edit
This is how I created the data for the ajax call. NOTE: this is untested - I don't have a last.fm account.
var songsToScrobble = {};
function addDataToScrobble(parentElement, inputData) {
if ($.isArray(inputData)) {
$.each(inputData, function(index ,element) {
songsToScrobble[parentElement + "[" + index + "]"] = element;
dataToHash += parentElement + "[" + index + "]" + element;
});
} else {
songsToScrobble[parentElement] = inputData;
dataToHash += parentElement + inputData;
}
}
for (var i = 0; i < data.tracks.length; i++) {
albums.push(data.album);
artists.push(data.artist);
// The tracks are coming in the format: title|timestamp
timestamps.push(data.tracks[i].split("|")[1]);
tracks.push(data.tracks[i].split("|")[0]);
}
addDataToScrobble("album", albums);
addDataToScrobble("api_key", apiKey);
addDataToScrobble("artist", artists);
addDataToScrobble("method", apiMethod);
addDataToScrobble("sk", key);
addDataToScrobble("timestamp", timestamps);
addDataToScrobble("track", tracks);
apiSig = $.md5(unescape(encodeURIComponent(dataToHash+apiSecret)));
songsToScrobble["api_sig"] = apiSig;
$.ajax({
url: apiUrl,
type: "POST",
data: songsToScrobble,
success: function (data) {
console.log(data);
}
});
I am trying to export a file as .csv file so that when the user clicks on the download button, the browser would automatically download the file as .csv.
I also want to be able to set a name for the .csv file to be exported
I am using javascript to do this
The code is below:
function ConvertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = '';
for (var index in array[i]) {
if (line != '') line += ','
line += array[i][index];
}
str += line + '\r\n';
}
return str;
}
// Example
$(document).ready(function () {
// Create Object
var items = [
{ "name": "Item 1", "color": "Green", "size": "X-Large" },
{ "name": "Item 2", "color": "Green", "size": "X-Large" },
{ "name": "Item 3", "color": "Green", "size": "X-Large" }];
// Convert Object to JSON
var jsonObject = JSON.stringify(items);
// Display JSON
$('#json').text(jsonObject);
// Convert JSON to CSV & Display CSV
$('#csv').text(ConvertToCSV(jsonObject));
$("#download").click(function() {
alert("2");
var csv = ConvertToCSV(jsonObject);
window.open("data:text/csv;charset=utf-8," + escape(csv))
///////
});
});
I have written a solution in this thread: How to set a file name using window.open
This is the simple solution:
$("#download_1").click(function() {
var json_pre = '[{"Id":1,"UserName":"Sam Smith"},{"Id":2,"UserName":"Fred Frankly"},{"Id":1,"UserName":"Zachary Zupers"}]';
var json = $.parseJSON(json_pre);
var csv = JSON2CSV(json);
var downloadLink = document.createElement("a");
var blob = new Blob(["\ufeff", csv]);
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = "data.csv";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
JSON2CSV function:
function JSON2CSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
var line = '';
if ($("#labels").is(':checked')) {
var head = array[0];
if ($("#quote").is(':checked')) {
for (var index in array[0]) {
var value = index + "";
line += '"' + value.replace(/"/g, '""') + '",';
}
} else {
for (var index in array[0]) {
line += index + ',';
}
}
line = line.slice(0, -1);
str += line + '\r\n';
}
for (var i = 0; i < array.length; i++) {
var line = '';
if ($("#quote").is(':checked')) {
for (var index in array[i]) {
var value = array[i][index] + "";
line += '"' + value.replace(/"/g, '""') + '",';
}
} else {
for (var index in array[i]) {
line += array[i][index] + ',';
}
}
line = line.slice(0, -1);
str += line + '\r\n';
}
return str;
}
in modern browsers there is a new attribute in anchors.
download
http://caniuse.com/download
so instead of using
window.open("data:text/csv;charset=utf-8," + escape(csv))
create a download link:
download
another solution is to use php
EDIT
i don't use jQuery, but you need to edit your code to add the download link
with something like that in your function.
var csv=ConvertToCSV(jsonObject),
a=document.createElement('a');
a.textContent='download';
a.download="myFileName.csv";
a.href='data:text/csv;charset=utf-8,'+escape(csv);
document.body.appendChild(a);
Try these Examples:
Example 1:
JsonArray = [{
"AccountNumber": "1234",
"AccountName": "abc",
"port": "All",
"source": "sg-a78c04f8"
}, {
"Account Number": "1234",
"Account Name": "abc",
"port": 22,
"source": "0.0.0.0/0",
}]
JsonFields = ["Account Number","Account Name","port","source"]
function JsonToCSV(){
var csvStr = JsonFields.join(",") + "\n";
JsonArray.forEach(element => {
AccountNumber = element.AccountNumber;
AccountName = element.AccountName;
port = element.port
source = element.source
csvStr += AccountNumber + ',' + AccountName + ',' + port + ',' + source + "\n";
})
return csvStr;
}
You can download the csv file using the following code :
function downloadCSV(csvStr) {
var hiddenElement = document.createElement('a');
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvStr);
hiddenElement.target = '_blank';
hiddenElement.download = 'output.csv';
hiddenElement.click();
}
I just wanted to add some code here for people in the future since I was trying to export JSON to a CSV document and download it.
I use $.getJSON to pull json data from an external page, but if you have a basic array, you can just use that.
This uses Christian Landgren's code to create the csv data.
$(document).ready(function() {
var JSONData = $.getJSON("GetJsonData.php", function(data) {
var items = data;
const replacer = (key, value) => value === null ? '' : value; // specify how you want to handle null values here
const header = Object.keys(items[0]);
let csv = items.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','));
csv.unshift(header.join(','));
csv = csv.join('\r\n');
//Download the file as CSV
var downloadLink = document.createElement("a");
var blob = new Blob(["\ufeff", csv]);
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = "DataDump.csv"; //Name the file here
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
});
Edit: It's worth noting that JSON.stringify will escape quotes in quotes by adding \". If you view the CSV in excel, it doesn't like that as an escape character.
You can add .replace(/\\"/g, '""') to the end of JSON.stringify(row[fieldName], replacer) to display this properly in excel (this will replace \" with "" which is what excel prefers).
Full Line: JSON.stringify(row[fieldName], replacer).replace(/\\"/g, '""')
One-liner function for simple JSON with static titles
Assuming arr is JSON array, you can also replace the first string with comma separated titles end with \n
arr.reduce((acc, curr) => (`${acc}${Object.values(curr).join(",")}\n`), "")
Or with the window.open function mentioned before
window.open(`data:text/csv;charset=utf-8,${arr.reduce((acc, curr) => (`${acc}${Object.values(curr).join(",")}\n`), "")}`)
You should also consider escape the strings or replace the , to avoid extra cells
If your data comes from a SQL Database, all your lines should have the same structure, but if coming from a NoSQL Database you could have trouble using standard answers. I elaborated on above JSON2CSV for such a scenario.
Json data example
[ {"meal":2387,"food":"beaf"},
{"meal":2387,"food":"apple","peeled":"yes", "speed":"fast" },
{"meal":2387,"food":"pear", "speed":"slow", "peeled":"yes" } ]
Answer
"meal","food","peeled","speed"
"2387","beaf","",""
"2387","apple","yes","fast"
"2387","pear","yes","slow"
Code for headers and double quotes for simplicity.
function JSON2CSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
var line = '';
// get all distinct keys
let titles = [];
for (var i = 0; i < array.length; i++) {
let obj = array[i];
Object.entries(obj).forEach(([key,value])=>{
//console.log('key=', key, " val=", value );
if (titles.includes(key) ) {
// console.log (key , 'exists');
null;
}
else {
titles.push(key);
}
})
}
let htext = '"' + titles.join('","') + '"';
console.log('header:', htext);
// add to str
str += htext + '\r\n';
//
// lines
for (var i = 0; i < array.length; i++) {
var line = '';
// get values by header order
for (var j = 0; j < titles.length; j++) {
// match keys with current header
let obj = array[i];
let keyfound = 0;
// each key/value pair
Object.entries(obj).forEach(([key,value])=>{
if (key == titles[j]) {
// console.log('equal tit=', titles[j] , ' e key ', key ); // matched key with header
line += ',"' + value + '"';
keyfound = 1;
return false;
}
})
if (keyfound == 0) {
line += ',"' + '"'; // add null value for this key
} // end loop of header values
}
str += line.slice(1) + '\r\n';
}
return str;
}