I'm using postman to test the following, later it will be automated but that's not the issue.
I'm requesting data from an XML based API and need to use the same data to send to a different API in XML format.
I've already figured out that I need to convert the XML to a JSON format in order to save it in a var. Which works.
However, the issue that I have is that this process creates extra characters in my data, in the form of: [{"$":
When I then continue to convert it back to XML (using the full function below), it doesn't work and I end up with an XML code with all over it. Which isn't accepted in the last post to the XML Api.
I want to achieve to remove all occurences of and in the XML var. But I think that I will need to get rid of the in the first step. [{"$":
I've already found a function (.replace) which removes it, but only the first occurence
Function JSON2XML
function json2xml(o, tab) {
var toXml = function(v, name, ind) {
var xml = "";
if (v instanceof Array) {
for (var i=0, n=v.length; i<n; i++)
xml += ind + toXml(v[i], name, ind+"\t") + "\n";
}
else if (typeof(v) == "object") {
var hasChild = false;
xml += ind + "<" + name;
for (var m in v) {
if (m.charAt(0) == "#")
xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
else
hasChild = true;
}
xml += hasChild ? ">" : "/>";
if (hasChild) {
for (var m in v) {
if (m == "#text")
xml += v[m];
else if (m == "#cdata")
xml += "<![CDATA[" + v[m] + "]]>";
else if (m.charAt(0) != "#")
xml += toXml(v[m], m, ind+"\t");
}
xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "</" + name + ">";
}
}
else {
xml += ind + "<" + name + ">" + v.toString() + "</" + name + ">";
}
return xml;
}, xml="";
for (var m in o)
xml += toXml(o[m], m, "");
return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
}
// Get the JSON from environment and parse it
let targetJSON = JSON.parse(pm.environment.get('firstTarget'));
// Convert it to XML String
let xmlString = json2xml(targetJSON);
// You can check the console if your string is correct
console.log(xmlString);
// Store the XML string as a variable and use this variable in your request body
pm.environment.set('targetXML', xmlString);
let resp = xml2Json(pm.response.text()),
targetData = resp.eExact.Accounts;
console.log({ targetData });
pm.environment.set('firstTarget', JSON.stringify(targetData));
This is the code which creates the [{"$":
I have a function that converts a HTML table into an Excel document. However upon the opening of the file, I receive the following message from Excel:
The file format and extension of 'something.xls' don't match. Etc etc...
Below is the function I am for the export, it is a slightly edited version of #SamPopes answer from this thread. The obj parameter is a table element I created using document.createElement('table');.
Is there any way to prevent this message upon opening the file?
function export(obj) {
var tab_text="<table border='2px'><tr>";
var textRange; var j=0;
tab = obj; //Table
for(j = 0 ; j < tab.rows.length ; j++){
tab_text=tab_text+tab.rows[j].innerHTML+"</tr>";
//tab_text=tab_text+"</tr>";
}
tab_text=tab_text+"</table>";
tab_text= tab_text.replace(/<A[^>]*>|<\/A>/g, "");//remove if you want links in your table
tab_text= tab_text.replace(/<img[^>]*>/gi,""); // remove if you want images in your table
tab_text= tab_text.replace(/<input[^>]*>|<\/input>/gi, ""); // removes input params
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // If Internet Explorer
{
txtArea1.document.open("txt/html","replace");
txtArea1.document.write(tab_text);
txtArea1.document.close();
txtArea1.focus();
sa=txtArea1.document.execCommand("SaveAs",true,"export.xls");
} else { //other browser not tested on IE 11
sa = window.open('data:application/vnd.ms-excel,' + encodeURIComponent(tab_text));
return (sa);
}
}
As I said in my comment above, here is the code for creating a CSV file. This works to avoid the error message you are receiving, but will eliminate any chance you have for formatting your data (As far as I know). Here is my code, which uses one process for IE and a second for all other browsers:
function exportTotalDataFile(){
var dataText = "";
var rowText = "";
'allData is generated through an AJAX call that creates a JSON'
'this loop creates the header row'
for (var index in allData[0]) {
rowText += index + ',';
}
'takes the trailing comma out, adds new row'
rowText = rowText.slice(0, -1);
dataText += rowText + '\r\n';
'Produces the data rows'
for (var i = 0; i < allData.length; i++) {
var rowText = "";
for (var index in allData[i]) {
rowText += '"' + allData[i][index] + '",';
}
rowText.slice(0, rowText.length - 1);
dataText += rowText + '\r\n';
}
var fileName = "Losses Report";
'Internet Explorer logic'
var isIE = false || !!document.documentMode;
if (isIE){
var IEwindow = window.open();
IEwindow.document.write('sep=,\r\n' + dataText);
IEwindow.document.close();
IEwindow.document.execCommand('SaveAs', true, fileName + ".csv");
IEwindow.close();
}
'All the other browsers'
else {
var uri = 'data:text/csv;charset=utf-8,' + escape(dataText);
var link = document.createElement("a");
link.href = uri;
link.style = "visibility:hidden";
link.download = fileName + ".csv";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
Sorry that this method is limited in the formatting department, but I hope this helps
I am using handsontable plugin for generate the data as excel format. This is done.
I need to export that data as excel and download.
Is there feature available in handsontable?
If not, How can i achieve this? Here, Handsontable data is different in table format
There isn't a feature yet, it's coming in the Pro version next month. In the meantime, there's this stack answer with a solution you could implement. You want to parse the data object from handsontable and then export that string to csv the normal JS way.
And here is the fiddle in case you don't want to follow the link, with the relevant code:
function parseRow(infoArray, index, csvContent) {
var sizeData = _.size(hot1.getData());
if (index < sizeData - 1) {
dataString = "";
_.each(infoArray, function(col, i) {
dataString += _.contains(col, ",") ? "\"" + col + "\"" : col;
dataString += i < _.size(infoArray) - 1 ? "," : "";
})
csvContent += index < sizeData - 2 ? dataString + "\n" : dataString;
}
return csvContent;
}
/**
* Export to CSV button
*/
var exportCsv = $("#export-csv")[0];
if (exportCsv) {
Handsontable.Dom.addEvent(exportCsv, "mouseup", function(e) {
exportCsv.blur(); // jquery ui hackfix
var csvContent = "data:text/csv;charset=utf-8,";
csvContent = parseRow(colHeaders, 0, csvContent); // comment this out to remove column headers
_.each(hot1.getData(), function(infoArray, index) {
csvContent = parseRow(infoArray, index, csvContent);
});
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", $("h1").text() + ".csv");
link.click();
})
}
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 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;
}