jQuery/JavaScript - Converting CSV to Array - javascript

I am trying to to convert a CSV file into a javascript array.
Here is my code:
var segments = {
'Segment_1':'inves_cast',
'Segment_2':'foreged_prod',
'Segment_3':'air_prod',
'Segment_5':'worldwide',
'Segment_6':'structurals'
};
var divisions = {
'Division_1':'structurals',
'Division_2':'airfoils',
'Division_3':'wyman',
'Division_4':'energy',
'Division_5':'fasteners',
'Division_6':'struc_comp',
'Division_7':'mech_hard',
'Division_8':'engine_prod',
'Division_9':'corp',
'Division_10':'aero',
'Division_11':'timet',
'Division_12':'',
'Division_13':'spec_metals',
};
var csv = $.get('/path/to/locations.csv');
console.log(csv);
var locationArray = transformLocationData(csv);
function transformLocationData(obj) {
var lineArray = [];
if(obj && obj.data) {
var text = (data.responseText);
lines = text.split('\n');
for(var line in lines) {
var lineTokens = line.split(',');
lineArray = [
lineTokens[0],
lineTokens[1],
lineTokens[3],
lineTokens[4],
lineTokens[5],
lineTokens[6],
lineTokens[11],
lineTokens[12],
lineTokens[13],
lineTokens[14],
lineTokens[15],
segments['Segment_' + lineTokens[8]],
divisions['Division_' + lineTokens[9]]
];
}
}
console.log(lineArray);
}
So what I am trying to do is us AJAX to get the csv file and then split the "responseText" first by line and Second loop through those lines and split it up by commas and then create an array based on those line numbers.
Here is a picture of the data I am getting back from the AJAX call:
With the last console log ( console.log(lineArray); ) it returns an empty array or really it just returns the data the is in var lineArray = []; which is empty if I populate it with data var lineArray = ["Lexus", "Audi", "BMW"]; It will return that array.
Here is a plunker with all the code: https://plnkr.co/edit/CoZGfr6S9R5LDqR1drzq
I know I am doing something wrong but cant seem to get it. I'm not familiar with doing this kind of thing so any help would be greatly appreciated.

You are replacing lineArray with a new array every time, and you're only logging the array at the end of the loop. Perhaps the CSV has an empty line at the end.
If you're wanting an array of arrays, do this instead:
var lineArray = [];
if(obj && obj.data) {
var text = (data.responseText);
lines = text.split('\n');
for(line in lines) {
var lineTokens = line.split(',');
lineArray.push([
lineTokens[0],
lineTokens[1],
lineTokens[3],
lineTokens[4],
lineTokens[5],
lineTokens[6],
lineTokens[11],
lineTokens[12],
lineTokens[13],
lineTokens[14],
lineTokens[15],
segments['Segment_' + lineTokens[8]],
divisions['Division_' + lineTokens[9]]
]);
}
}
console.log(lineArray);
Update:
In addition, you're not handling the results from the Ajax request properly. This line:
var csv = $.get('/path/to/locations.csv');
...does not return the CSV. Rather, it returns a Promise (sort of...). So you cannot parse csv like that. Rather, wait for the results. Change your code to:
$.get('/path/to/locations.csv').then(function (csv) {
var locationArray = transformLocationData(csv);
}, function (err) {
// Handle errors
});
As #vlaz alluded to, you'll also want to change your loop from for..in to a regular for loop:
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
// ...
}

Related

How to fix the Error : TypeError : Cannot read properly 'setValues' of undefined google app script. How to implement it to my the code?

I made files with table. On those table there is some datas that are changing according to each files. So I created a file where there is a table that sum all of the others tables that are in others files.
First i made my code that sum tables of two files :
function juneFunction() {
var sheet_origin1=SpreadsheetApp
.openById("ID1")
.getSheetByName("Calcul/Machine");
var sheet_origin2=SpreadsheetApp
.openById("ID2")
.getSheetByName("Calcul/Machine");
var sheet_destination=SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//define range as a string in A1 notation
var range1="BU4:CF71"
var values1=sheet_origin1.getRange(range1).getValues();
var values2=sheet_origin2.getRange(range1).getValues();
var destinationrange=sheet_destination.getRange("C3:N70");
//Here you sum the values of equivalent cells from different sheets
for(var i=0; i<values1.length;i++)
{
for(var j=0; j<values1[0].length;j++)
{
sum=values1[i][j]+values2[i][j];
destinationrange.getCell(i+1,j+1).setValue(sum);
}
}
}
This code is working perfectly.
But my goal is to sum 26 tables of 26 files.
So I tried to do it with 3 files, here is the code :
function juneFunction() {
var sheet_origin1=SpreadsheetApp
.openById("ID1")
.getSheetByName("Calcul/Machine");
var sheet_origin2=SpreadsheetApp
.openById("ID2")
.getSheetByName("Calcul/Machine");
var sheet_origin3=SpreadsheetApp
.openById("ID3")
.getSheetByName("Calcul/Machine");
var sheet_destination=SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//define range as a string in A1 notation
var range1="BU4:CF71"
var values1=sheet_origin1.getRange(range1).getValues();
var values2=sheet_origin2.getRange(range1).getValues();
var values3=sheet_origin3.getRange(range1).getValues();
var destinationrange=sheet_destination.getRange("C3:N70");
//Here you sum the values of equivalent cells from different sheets
for(var i=0; i<values1.length;i++)
{
for(var j=0; j<values1[0].length;j++)
{
for(var k=0; k<values1[0].length;k++){
sum=values1[i][j][k]+values2[i][j][k]+values3[i][j][k];
destinationrange.getCell[[i+1,j+1,k+1]].setValues(sum);
}
}
}
}
Here I have this error : TypeError : Cannot read properly 'setValues' of undefined. This error happen here :
destinationrange.getCell[[i+1,j+1,k+1]].setValues(sum);
I think that the error is coming from the .getCell but i dont know why ...
Range.getCell() takes two arguments: the row offset and the column offset. You are handing it just one argument: an array of three numbers.
You should not be using Range.getCell() in the first place. Instead, use Array.map() to get the sheets, Array.forEach() to iterate over them, and finally Range.setValues() to write all results in one go, like this:
function sumRangeAcrossManySpreadsheets() {
const spreadSheetIds = ['id1', 'id2', 'id3',];
const sheetName = 'Calcul/Machine';
const rangeA1 = 'BU4:CF71';
const targetRange = SpreadsheetApp.getActiveSheet().getRange('C3');
const sheets = spreadSheetIds.map(id => SpreadsheetApp.openById(id).getSheetByName(sheetName));
const result = [];
sheets.forEach((sheet, sheetIndex) => {
if (!sheet) {
throw new Error(`There is no sheet ${sheetName} in spreadsheet ID '${spreadSheetIds[sheetIndex]}'.`);
}
const values = sheet.getRange(rangeA1).getValues();
values.forEach((row, rowIndex) => row.forEach((value, columnIndex) => {
if (!result[rowIndex]) {
result[rowIndex] = new Array(row.length).fill(0);
}
result[rowIndex][columnIndex] += Number(value) || 0;
}));
});
targetRange.offset(0, 0, result.length, result[0].length).setValues(result);
}

Are js array indexes set if not defined

I am working on a script in which i need some data based on a lot of timestamps.
Below is just an example
var timestampData1 = [1555486016,1555486017,1555486018...];
var timestampData2 = [1555486016,1555486017,1555486018...];
var data = [];
data[1] = [];
$.each(timestampData1,function(index,value) {
data[1][value] = 1;
});
data[2] = [];
$.each(timestampData2,function(index,value) {
data[2][value] = 1;
});
console.log(data);
The example above will output the following in the console
However if i examine the data in the console, i see a lot of empty sets counting from 0 up to the very last timestamp
So my question is:
Will javascript set all of these indexes, or is it simply an indication in the console?
If not, i guess that it is very bad for performance, doing it like above ?
Yes your assumption is correct. If you use objects which have key/value pairs whis won't be a problem, however you will you array methods like push and filter.
Example:
var timestampData1 = [1555486016,1555486017,1555486018...];
var timestampData2 = [1555486016,1555486017,1555486018...];
var data = [];
//Make data[1] an object not array
data[1] = {};
$.each(timestampData1,function(index,value) {
data[1][value] = 1;
});
//Make data[1] an object not array
data[2] = {};
$.each(timestampData2,function(index,value) {
data[2][value] = 1;
});
console.log(data);
Output:

How to change JSON into string

i got a words array in JSON form like:
var words = [];
words.push({word:"I",x:50,y:50});
and i want it to store into a txt file which user can download from the website.
...
var data = JSON.stringify(words);
var file = new Blob([data],{type:'plain/text'});
...
however the output file is like this:
{"word":"Peaceful","x":40,"y":65,"lyric":"lyric"}
but i want it only print out the word "peaceful", i tried to use
var data = JSON.stringify(words.word);
but the output shows undefined.
words is an array, so you have to index it to access the object that you pushed onto it:
var data = JSON.stringify(words[0].word);
If I understand you correctly.
var myWords = [];
(for var i = 0; i < words.length; i++) {
var word = words[i].word;
myWords.push(word);
}
myWords.join(' '); // or myWords.join('\n');

Load csv data to an array

I have a csv file containing entries as follows:
a,10
b,20
c,30
d,40
In JavaScript, I want to assign this csv file to a variable lets say x as follow:
x = [
['a',10],
['b',20],
['c',30],
['d',40]
]
Can someone tell me how i can do this.
If your CSV is really that simple, you just need two splits and a loop:
var rows = "a,10\nb,20\nc,30\nd,40".split('\n');
var x = [];
for(var i=0; i<rows.length; i++) {
x.push(rows.split(','));
}
A shorter version:
var x = "a,10\nb,20\nc,30\nd,40".split('\n').map(function(val) {
return val.split(',');
});

Javascript 2D array issue - all elements are a copy of the final entry

I'm creating a javascript 2D array from an XML file which I then manipulate and filter as necessary before displaying on the page.
As I loop through the XML records, I manipulate the data a little, build a normal array from it (rowRecord) and then add this array to the 2D array (dataSet). Thing is, I end up with a nice 2D array, but all the records are duplicates of the very last record I'm adding.
Using some alerts I've found that as I add the first record, all is well. I then add the second record and I get a dataSet with 2 records, both of which are record 2. Adding the third results in a dataSet of 3 records, each of them a copy of the third record. This carries on for all 1300 records, resulting in 1300 identical records, all of which are the last record from the XML.
Here is the code:
var rowRecord = new Array();
var dataSet = new Array(rowRecord);
function getAjaxTridionInfo() {
var xmlFilename = 'filename.xml';
// make ajax call here, create xml object
xmlData = new Ajax.Request(xmlFilename,{
method:'get',
onSuccess: function(transport) {
var dataObj = transport.responseXML;
var vRoot = dataObj.getElementsByTagName('Items')[0];
for (var i=0; i<vRoot.childNodes.length; i++) {
if (vRoot.childNodes[i].nodeType == 1) {
var tridItem = vRoot.childNodes[i];
rowRecord[0] = tridItem.childNodes[0].firstChild.nodeValue.substring(26);
rowRecord[1] = tridItem.childNodes[1].firstChild.nodeValue;
rowRecord[2] = tridItem.childNodes[2].firstChild.nodeValue;
rowRecord[3] = rowRecord[1]+"/"+rowRecord[2];
rowRecord[4] = false;
rowRecord[5] = "n/a";
rowRecord[6] = "n/a";
rowRecord[7] = false;
rowRecord[8] = "n/a";
rowRecord[9] = "n/a";
//do some other processing here to determine rowRecord[4] - [9]
dataSet.push(rowRecord);
rowCount += 1;
}
}
//call next function here
},
onException: function(transport, exception) {
throw(exception);
alert('There has been a problem performing the Ajax call');
}
}
);
}
Any help or suggestions would be appreciated.
You should create rowRecord in the function, not outside, so as to make a new array for every row record.
// NO NEED TO DECLARE ROWRECORD HERE...
var dataSet = new Array(); // <- why would we add anything initially?
function getAjaxTridionInfo() {
// ...
if (vRoot.childNodes[i].nodeType == 1) {
var tridItem = vRoot.childNodes[i];
// IMPORTANT TO MAKE A NEW ARRAY HERE
var rowRecord = new Array();
rowRecord[0] = tridItem.childNodes[0].firstChild.nodeValue.substring(26);
rowRecord[1] = tridItem.childNodes[1].firstChild.nodeValue;
rowRecord[2] = tridItem.childNodes[2].firstChild.nodeValue;
rowRecord[3] = rowRecord[1]+"/"+rowRecord[2];
rowRecord[4] = false;
rowRecord[5] = "n/a";
rowRecord[6] = "n/a";
rowRecord[7] = false;
rowRecord[8] = "n/a";
rowRecord[9] = "n/a";
//do some other processing here to determine rowRecord[4] - [9]
dataSet.push(rowRecord); // <- PUSHES THE NEW ARRAY
rowCount += 1;
}
// ...
}
Move:-
var rowRecord = new Array();
to just before:-
rowRecord[0] = tridItem.childNodes[0].firstChild.nodeValue.substring(26);
Otherwise you keep re-using the same instance of an array object, overwriting its content on every iteration. All entries in the outer array point to this same single instance of the array.
Change:
var dataSet = new Array(rowRecord);
to:
var dataSet = [];
UPDATE: And move the dataSet declaration as per #AnthonyWJones

Categories