Maybe sounds stupid but the first column of my csv is not the date field.
I can manually edit CSV to change columns order and then works like a charm but since the file is automacally generated I cannot do it frequentely.
Is there any way to set date column if not first?
Edit: here you have sample of my csv
Test server;Date/Time;Latency (ms);Dowload Speed (Kb/s);Upload Speed (Kb/s)
TVAlmansa S.L. (Almansa) [50.87 km];2015/07/07 11:00:31;67.94;57975;25226
Grupo TVHoradada (Pilar De La Horadada) [87.32 km];2015/07/07 12:00:32;46.11;58484;25433
Grupo TVHoradada (Pilar De La Horadada) [87.32 km];2015/07/07 13:00:31;43.75;55262;24106
TVAlmansa S.L. (Almansa) [50.87 km];2015/07/07 14:00:39;89.39;55266;12722
TVAlmansa S.L. (Almansa) [50.87 km];2015/07/07 15:00:35;69.24;56732;22550
1st step to solution
As #danvk says, it seems that dygraphs takes first column from csv file as date argument. There is no way to change this, I just can to load csv file in an array and then set columns I want to display.
Solution
Finally I've used some code based on this post to load and parse my csv file. This is the complete code
//AJAX query for CSV file
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status === 200 || // Normal http
req.status === 0) { // Chrome w/ --allow-file-access-from-files
var data = req.responseText;
drawGraph(data);
}
}
};
req.open('GET', 'bandwith_report.csv', true);
req.send(null);
//Graph draw function
var drawGraph = function(data) {
//data threatment (select columns)
var parsed_data = toArray(data);
var firstRow = parsed_data[0];
var data = parsed_data.slice(1); // Remove first element (labels)
//data display
graph = new Dygraph(
"graphdiv2", //div
data,
{
labels: firstRow
}
);
}
var toArray = function(data) {
//load lines
var lines = data.split("\n");
var arry = [];
//parse lines
for (var idx = 0; idx < lines.length; idx++) {
var line = lines[idx];
// Oftentimes there's a blank line at the end. Ignore it.
if (line.length == 0) {
continue;
}
var row = line.split(";");
// Special processing
// remove first field (including header)
row.splice(0,1);
// parse data (except header)
if (idx > 0) {
row[0] = new Date(row[0]); // Turn the string date into a Date.
// turn string into float
for (var rowIdx = 1; rowIdx < row.length; rowIdx++) {
// Turn "123" into 123.
row[rowIdx] = parseFloat(row[rowIdx]);
}
}
arry.push(row);
}
return arry;
}
No. dygraphs assumes that the first column is the independent (x) axis. If it's not, then you need to modify your data to make it so. Instead of doing this manually, you could do it in JavaScript.
Related
I am using a Google Apps Script that pulls the content from a feed in a sheet.
This is the code that I'm using:
function processXML(FeedURL,sheetsFileDestinationURL,rawPasteSheetName,OPT_childNamesArray,OPT_Namespace){
var OPT_childNamesArray = ["link"]; // get only item url from the feed
var GoogleSheetsFile = SpreadsheetApp.openByUrl(sheetsFileDestinationURL);
var GoogleSheetsPastePage = GoogleSheetsFile.getSheetByName(rawPasteSheetName);
if (OPT_childNamesArray){
GoogleSheetsPastePage.getDataRange().offset(1,0).clearContent(); // get all filled cells, omitting the header row, and clear content
}
else {
GoogleSheetsPastePage.getDataRange().offset(0,0).clearContent(); // get all filled cells, INCLUDING the header row, and clear content
}
// Generate 2d/md array / rows export based on requested columns and feed
var exportRows = []; // hold all the rows that are generated to be pasted into the sheet
var XMLFeedURL = FeedURL;
var feedContent = UrlFetchApp.fetch(XMLFeedURL).getContentText(); // get the full feed content
var feedItems = XmlService.parse(feedContent).getRootElement().getChild('channel').getChildren('item'); // get all items in the feed
for (var x=0; x<feedItems.length; x++){
// Iterate through items in the XML/RSS feed
var currentFeedItem = feedItems[x];
var singleItemArray = []; // use to hold all the values for this single item/row
// Parse for specific children (requires names and namespace)
if (OPT_childNamesArray){
for (var y=0; y<OPT_childNamesArray.length; y++){
// Iterate through requested children by name and fill rows
var currentChildName = OPT_childNamesArray[y];
if (OPT_Namespace){
if (currentFeedItem.getChild(OPT_childNamesArray[y],OPT_Namespace)){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y],OPT_Namespace));
}
else {
singleItemArray.push("null");
}
}
else {
if (currentFeedItem.getChild(OPT_childNamesArray[y])){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y]));
}
else {
singleItemArray.push("null");
}
}
}
exportRows.push(singleItemArray);
}
// Parse for ALL children, does not require knowing names or namespace
else if (!OPT_childNamesArray){
var allChildren = currentFeedItem.getChildren();
if (x == 0){
// if looking at first item, create a header row first with column headings
var headerRow = [];
for (var h=0; h<allChildren.length; h++){
headerRow.push(allChildren[h].getName());
}
exportRows.push(headerRow);
}
for (var c=0; c<allChildren.length; c++){
singleItemArray.push(allChildren[c].getText());
}
exportRows.push(singleItemArray);
}
}
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
else if (!OPT_childNamesArray){
var maxRangeLength = 0;
var currentRowIndex = 1;
for (var x = 0; x<exportRows.length; x++){
if (exportRows[x].length > maxRangeLength){
maxRangeLength = exportRows[x].length;
}
GoogleSheetsPastePage.getRange(currentRowIndex,1,1,exportRows[x].length).setValues([exportRows[x]]);
currentRowIndex++;
}
}
}
My problem is this:
When I run this code I get:
https://url/115-396/
https://url/115-396/
https://url/115-396/
I need to remove "115-396/".
So I tryed to add this code but didn't work:
...
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for (var k = 0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
var URL = exportRows[0].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValue(URL);
}
else if (!OPT_childNamesArray){
...
Edit after #Yuri reply:
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for ( k=0; k < exportRows[0].length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[0][k] = exportRows[0][k].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
result:
https://url/
https://url/115-396/
https://url/115-396/
Basically, the regex is applied only to the first url.
How I can make that the regex is applied to all the url's?
Any help?
Thanks
You are using a for to iterate thru the exportRow array, but later on, you're not using the k iterator inside the for.
Then, you are not accessing the exportRows array, only the first position:
var URL = exportRows[0].toString().replace(re, replacingItem);
Shouldn't be?
var URL = exportRows[k].toString().replace(re, replacingItem);
In that case, it won't work, because URL it's not an array, so by doing this you are only saving the last assignation produced on the for iterator on the URL, I believe you are trying to do the following:
for ( k=0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[k] = exportRows[k].toString().replace(re, replacingItem);
}
And you'll have exportRows as an array of the desired url's without the 115-396 extensions.
Now you can place this on the spreadsheet with setValue as you were doing, but setValue is for strings, integers, etc, and not for arrays. For arrays you have setValues()
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
But, then, the range of exportRows should match the range of your getRange selection, which I'm not sure it's happening.
Just to clarify it, exportRows.length is the length of the array, and exportRows[1] is the length of the string/url stored on the position 1 of the array.
Hope this helps, the question is not really clear neither the intentions, provide more info if still not working.
How to know the size of the range you're getting?
var myrange = GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length)
Logger.log(myrange.getNumRows());
Logger.log(myrange.getNumColumns());
You'll be able to know the range you have on getRange and make it match with the exportRows size.
Make sure to check the attached documentation, and in case you have more doubts please open a new question related to it.
I read a csv file using javascript code and i want to push it into a a 2D Array in order to do some processing
var dataArray = new Array;
function parseCSV(dataArray) {
//replace UNIX new lines
data = data.replace(/\r\n/g, "\n");
//replace MAC new lines
data = data.replace(/\r/g, "\n");
//split into rows
var rows = data.split("\n");
// loop through all rows
for (var i = 0; i < rows.length; i++) {
// this line helps to skip empty rows
if (rows[i]) {
// our columns are separated by comma
var column = rows[i].split(",");
var date=column[0];
var value = column[4];
// create object which contains all these items:
var dataObject = {
date: date,
T4: value
};
dataArray.push(dataObject);
}
}
}
}
As a test, i try to read a cell content and display on the web page to verify that i read the file.
<script type="text/javascript">
var x= dataArray[1][4];
document.write(x);
</script>
but it doesn't show anything.
Can anyone Help??
var dataArray = new Array;
var data = "Date,Description,Created By,Modified By,T4 Tag\n";
data += "20170424,This is record 1,user1,none,Just work please.\n";
data += "20170424,This is record 2,user2,none,I'm trying too.\n";
function parseCSV(dataArray) {
//replace UNIX new lines
data = data.replace(/\r\n/g, "\n");
//replace MAC new lines
data = data.replace(/\r/g, "\n");
//split into rows
var rows = data.split("\n");
// loop through all rows
for (var i = 0; i < rows.length; i++) {
// this line helps to skip empty rows
if (rows[i]) {
// our columns are separated by comma
var column = rows[i].split(",");
var date=column[0];
var value = column[4];
// create object which contains all these items:
var dataObject = {
date: date,
T4: value
};
dataArray.push(dataObject);
}
}
}
parseCSV(dataArray);
Lacking a file, I forced some CSV data into a string for processing.
Your question is not showing these two items:
how you are setting var data
how you are calling parseCSV(dataArray)
If these two things are present all should work - Here's the proof
As far as the html script portion:
your array addressing looks wrong - it seems like it should look like:
<script>
var x = dataArray[1].T4;
document.write(x);
</script>
Here's my reasoning:
I understand that you are passing the CSV data to this function for parsing it into your dataArray variable - correct?
If correct, this data will look something like I have added manually (I added this directly just to work with something).
The bigger item is not so much where the data is coming from, but that ultimately it gets parsed by this parseCSV function.
When this happens, you are building appending to the empty dataArray variable in the following way:
For the first pass this will look as follows:
[{"date" : "Date", "T4" : "T4 Tag"}]
For the second pass:
[{"date" : "Date", "T4" : "T4 Tag"}, {"date" : "20170424", "T4" : "Just work please."}]
For the third pass:
[{"date" : "Date", "T4" : "T4 Tag"}, {"date" : "20170424", "T4" : "Just work please."}, {"date" : "20170424", "T4" : "I\'m trying too."}]
So now when you are in your html section of code, you have no key of address [4].
Your code says:
var x = dataArray[1][4];
Consider the following to see what I mean:
var record = dataArray[1];
//{"date" : "20170424", "T4" : "Just work please."}
//There is no key 4 here only date & T4.
var date = record.date;//returns: "20170424"
var t4 = record.T4;//returns: "Just work please."
In Contrast if you had the following - your method would work
myObj = {"date" : "20170424", "4" : "This is a value for field 4", "T4" : "Just work please."}
myObj[4];//returns "This is a value for field 4";
hopefully this explains it clearly enough.
here is the load csv file function
function loadCSV(file) {
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari
var request = new XMLHttpRequest();
} else {
// code for IE6, IE5
var request = new ActiveXObject('Microsoft.XMLHTTP');
}
// load
request.open('GET', file, false);
request.send();
parseCSV(dataArray);
}
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];
// ...
}
I am importing a csv file using javascript. It imports the dataset in my program but I always get the error csv[i] not defined (line 57). I tried adding vai i = 0; just before that line but it still gives me the error. Any idea what I should add to get rid of this error?
//
// =============================================================
// CSV to coll - javascript code
// =============================================================
//
//
//
/***************************************************************
Notes:
This JS object is used to import the csv file and convert it for use within a coll.
Besides the original data, two spreads (between open and close and between high and low) are calculated
Furthermore, the minima and maxima of each column are sent out to allow contextualization of the values.
These minima and maxima can be used to set the range of the zmap object down the chain.
****************************************************************/
// =============================================================
// inlets and outlets
// =============================================================
outlets = 6;
// =============================================================
// Functions start here
// =============================================================
/***************************************************************
this function imports the csv file. The first line (the header row) is skipped and
the lines are converted to strings
****************************************************************/
function importfromfile(filename)
{
var f = new File(filename);
var csv = [];
var x = 0;
if (f.open) {
var str = f.readline(); //Skips first line.
while (f.position < f.eof) {
var str = f.readline();
csv.push(str);
}
f.close();
} else {
error("couldn't find the file ("+ filename +")\n");
}
/***************************************************************
1) the csv is read into the coll/cellblock
2) the spread between high-low and open-close is calculated and set out to the coll/cellblock as well
3) the maximum of each column is found and sent to outlet 1
****************************************************************/
var maxtimestamp=0;
var maxdatavalue=0;
for (var i=0; i<=csv.length; i++) {
var a = csv[i].split(",");
var timestamp = parseFloat(a[0]);
var datavalue = parseFloat(a[1]);
maxtimestamp=(timestamp>maxtimestamp)? timestamp : maxtimestamp; // open overwrites the max if it greater
maxdatavalue=(datavalue>maxdatavalue)? datavalue : maxdatavalue; // open overwrites the max if it greater
outlet(0, x++, timestamp, datavalue);
outlet(1, maxtimestamp, maxdatavalue);
outlet(4, csv.length);
}
// the minimum of each column is found and sent out to outlet 2
// a bang to outlet 3 makes sure that the coll is referred in the cellblock
var mintimestamp=Infinity;
var mindatavalue=0;
for (var i=0; i<=csv.length; i++) {
var a = csv[i].split(",");
var timestamp = parseFloat(a[0]);
var datavalue = parseFloat(a[1]);
mintimestamp=(timestamp<mintimestamp)? timestamp : mintimestamp; // open overwrites the min if it greater
datavalue=(datavalue<mindatavalue)? datavalue : mindatavalue; // open overwrites the min if it greater
outlet(2, mintimestamp, mindatavalue);
outlet(3, mintimestamp);
outlet(4, "bang");
}
}
This is the problem:
for (var i=0; i<=csv.length; i++) {
// -------------^
Array indexes are 0 through length - 1, not length. Remove the =. Accessing csv[i] when i is csv.length will give you undefined, which will cause an error on the first line of the loop body, where you try to call split on it.
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