I'm trying to construct a highcharts barchart using data from multiple locally held json files and having a bit of trouble. For simplicity's sake I want to loop through all files, do a search for a particular string and use the count as the data for my graph. I've went about it like so:
options.series[0].name = 'Test';
options.series[0].data = [];
//Loop over the different local files and do a search count in each
var localfiles = new Array('localfile1.json', 'localfile2.json');
for (var i=0; i<locfiles.length; i++) {
//do a count here
$.getJSON(localfiles[i], function(data) {
var count = 0;
var index = 0;
var entry;
for (index = 0; index < data.length; ++index) {
entry = data[index];
if (entry.searchkey == "searchstring") {
count ++;
}
options.series[0].data.push(count);
});
});
var chart = new Highcharts.Chart(options);
I realise that I'm not passing the options array around correctly. But I'm not sure what way I should code this. Any advice?
Thanks in advance.
to get 2 bars you need to put the options.series[0].data.push(count); outside the second loop otherwise you gonna end up with lots of bars growing up
options.series[0].name = 'Test';
options.series[0].data = [];
//Loop over the different local files and do a search count in each
var localfiles = new Array('localfile1.json', 'localfile2.json');
for (var i=0; i<locfiles.length; i++) {
//do a count here
$.getJSON(localfiles[i], function(data) {
var count = 0;
var index = 0;
var entry;
for (index = 0; index < data.length; ++index) {
entry = data[index];
if (entry.searchkey == "searchstring") {
count ++;
}
});
options.series[0].data.push(count);
});
var chart = new Highcharts.Chart(options);
this way you'll get 1 bar for each json file
to answer your comment
you can use addSeries
var series1 = {
data: [],
name: ""
}
chart.addSeries(series1);
if you want to remove all previous series you can do that
while(chart.series.length > 0){
chart.series[0].remove(true);
}
Related
I have some data pulling from a sheet. I have created an array that is sorted by the 2nd column (SKU column) below is what is returned in the spreadsheet:
In this array would like to add a blank row when the SKU changes to make it easier to read. I wrote the following code:
function update(){
var mfgSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Order Info");
var purchaseLog = SpreadsheetApp.
openById("1KkR4jE1c00WuQpPrexW8f9BIq5vxl0fWaUGxbeYERsE").
getSheetByName("Order Details");
var orderSort = purchaseLog.getRange(3, 1, purchaseLog.getLastRow(), 15).getValues().
sort(function(r1,r2){
var a = r1[1];
var b = r2[1];
if(a>b){
return 1;
}else if (a<b){
return -1;}
return 0;
}).filter(function (item){if(item[1]!=""&&item[1]!="Purchase Order Link"){return true}})
.map(function(r){return [r[0],r[1],r[2],r[5],r[6],r[11],r[13],r[12],r[8]]});
var SKUs = orderSort.map(function(r){return r[1]})
var SKUList = [];
for (var i in SKUs) {
var SKU = SKUs[i];
var duplicate = false;
for (var j in SKUList) {
if (SKU === SKUList[j]) {
duplicate = true;
}
}
if (!duplicate) {
SKUList.push(SKU);
}
}
var finalArr = []
for(var i = 0; i <= SKUList.length-1; i++){
var element = orderSort.filter(function(item){if(item[1]===SKUList[i]){return true}});
finalArr.push(element);
finalArr.push([,,,,,,,,,]);
}
Logger.log(finalArr);
}
The code almost works, but I'm getting a weird 3d Array, and I'm afraid that my logic is very wrong. Photo of the log is also included. Anyone that could help me solve this problem, it would be greatly appreciated.
element is already a 2D array. By pushing it to another array, a 3D array is created. Use Array.concat instead:
finalArr = finalArr.concat(element);//instead of finalArr.push(element);
I'm fairly new to coding in Google Script, and with Javascript. Basically what I'm trying to do is make a script to update data on a table in a spreadsheet. I have the script to import the email as a CSV, but I'm struggling with transferring the data from the email to the table by matching up the dates. Essentially what I would like the script to do is emulate a vlookup and paste the values from the emails CSV file to the table.
I made a copy of the file as an example of what I'm trying to do. I'm trying to transfer the yellow section of columns A and B of the Data tab to the matching yellow section columns A and B. And if there is no data for the dates then I would like the empty dates to be 0.
https://docs.google.com/spreadsheets/d/1uK3sCUFvcW6lgk962jgTN-yZox-lF8-Z0wm7Zhh-i8I/edit?usp=sharing
Thanks!
This two functions will accomplish your objectives. createArray(hight, width, filling) is just a workaround to create an array of the exact size of the Destination table. moveDates() is the one that compares the timestamps of the Data table with the ones on Destination; and will write down the values of the row if they match, and a zero if they don't.
This second function will first declare a bunch of variables that will save ranges and values for both sheets. After that, it will read all the dates of both tables. Later, it will run through the Destination table searching for coincidences and saving them on the newData array. Finally, the code will write down the newData. I've tested this code on your spreadsheet and it works perfectly.
function createArray(hight, width, filling) {
var array = [];
for (var i = 0; i < hight; i++) {
array[i] = [];
for (var j = 0; j < width; j++) {
array[i][j] = filling;
}
}
return array;
}
function moveDates() {
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data');
var destinationSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
'Destination');
var dataRange = dataSheet.getRange(5, 1, 6, 3);
var destinationRange = destinationSheet.getRange(2, 1, 11, 3);
var newDataRange = destinationSheet.getRange(2, 2, 11, 2)
var data = dataRange.getValues();
var destination = destinationRange.getValues();
var dataDates = [];
var destinationDates = [];
var newData = createArray(11, 2, 0);
for (var i = 0; i < data.length; i++) {
dataDates.push(new Date(data[i][0]));
}
for (var i = 0; i < destination.length; i++) {
destinationDates.push(new Date(destination[i][0]));
}
for (var i = 0; i < destination.length; i++) {
for (var j = 0; j < data.length; j++) {
if (destinationDates[i].getTime() === dataDates[j].getTime()) {
newData[i][0] = data[j][1];
newData[i][1] = data[j][2];
}
}
}
newDataRange.setValues(newData);
}
If you need more information or clarifications I'll be happy to help you.
We have a workbook which contains two dashboards, the first contains one worksheet and the second contains four worksheets.
We're trying to pass filters in via the url (that part is ok) but we cannot get all the worksheets on the second dashboard to update.
The code loops through the dashboards, activating each in turn then calling a filterActiveSheet() method on each.
This method loops through each worksheet in turn, searches for a matching categorical filter with the same FieldName as the provided one and, when found, uses the applyFilterAsync() method to replace it with the provided one.
var options = {
< snip >
onFirstInteractive: function () {
workbook = viz.getWorkbook();
sheets = workbook.getPublishedSheetsInfo();
for(s = 0; s < sheets.length; s++)
{
viz.getWorkbook().activateSheetAsync(s)
.then(filterActiveSheet);
}
}
};
function filterActiveSheet(sheet) {
for (ws = 0; ws < sheet.getWorksheets().length; ws++) {
var worksheet = sheet.getWorksheets()[ws];
worksheet.getFiltersAsync()
.then(function(p) {
var f = filters.split(';');
for(y=0;y<f.length;y++){
var filter = f[y].split(':');
var filterType = $.grep(p, function(e){ return e.getFieldName() == filter[0]; });
if (filterType.length > 0) {
switch(filterType[0].getFilterType()) {
case tableau.FilterType.CATEGORICAL:
return worksheet.applyFilterAsync(filter[0], filter[1], tableau.FilterUpdateType.REPLACE);
break;
< snip >
}
}
}
});
}
}
var viz = new tableauSoftware.Viz(placeholderDiv, url, options);
The problem we're seeing is that only one worksheet on each dashboard is being updated. Stepping through the JS in Chrome I can see the call to applyFilterAsync() the expected number of times which does not seem to cause an error, it simply doesn't seem to want to update all the filters/worksheets, just one on each dashboard.
Thoughts? Suggestions? Syntax errors?
getPublishedSheetsInfo() returns a collection that is returning one worksheet and one dashboard the types of which can be determined by calling getSheetType(). You can't apply getFilterAsync() directly to a dashboard but have to iterate. Try something like:
if (sheet.getSheetType() === 'WORKSHEET') {
sheet.getFiltersAsync().then(function(filters) {
for (var x = 0; x < filters.length; x++) {
// do something
}
})
} else {
// either in a dashboard or story
var workSheetArray = sheet.getWorksheets();
for (var i = 0; i < workSheetArray.length; i++) {
workSheetArray[i].getFiltersAsync().then(function(filters) {
for (var x = 0; x < filters.length; x++) {
// do something
}
}
}
}
Below is the code that I use to load colors to the svg map that I have based on the winning party taken from a spreadsheet with an array. The problem that I am currently facing is that there is an error in the loop and it identified only the first nine paths and applied the color and left the rest. Can someone help me identify and fix these issues. I am still learning from my mistakes and help would be appreciated.
<![CDATA[
var resultData = [];
var uniqueparty= [];
var wincolor = [];
$.getJSON("https://spreadsheets.google.com/feeds/list/1IoNqeReOPKNFrYMlK2rnJVuMaLeAgnZneLbKYSQ7bs4/od6/public/values?alt=json", function(data) {
var len = data.feed.entry.length;
for (var i=0; i<len; i++) {
//first row "title" column
var current = data.feed.entry[i];
resultData[i]= [
current.gsx$constituency.$t, //0
current.gsx$winner2010.$t, //1
current.gsx$winningparty.$t, //2
current.gsx$candidatename1.$t, //3
current.gsx$party1.$t,//4
current.gsx$candidatename2.$t,//5
current.gsx$party2.$t,//6
current.gsx$candidatename3.$t,//7
current.gsx$party3.$t//8
];
//Moving Winning party names alone to an array
wincolor[i]=[current.gsx$winningparty.$t];
}
//Remove duplicates from the winning party array to another array
uniqueparty = wincolor.filter(function (el) {
if (this[el]) {
this[el] = 1;
return el;
}
return true;
}, {});
//uniqueparty.sort();
//Specify colors for the party
var colors = ["#FE9A2E", "#F2F5A9", "#81F781", "#F2F5A9", "#58ACFA", "#F3F781", "#F5A9F2", "#81F7F3", "#F5A9A9"];
//assign color using loop based on element ID
for(i=0; i<wincolor.length; i++){
for(j=0; j<uniqueparty.length; j++){
if(uniqueparty[j]==resultData[i][2]){
var paths = document.getElementById(resultData[i][0]);
paths.style.fill=colors[j];
break;
}
}
}
});
]]>
I have included the spreadsheet from which the data is retreived and also the svg map
https://docs.google.com/spreadsheets/d/1IoNqeReOPKNFrYMlK2rnJVuMaLeAgnZneLbKYSQ7bs4/pubhtml?gid=0&single=true
http://jsfiddle.net/diviseed/3ncos0uk/1/
(forgive me if I use slightly incorrect language - feel free to constructively correct as needed)
There are a couple posts about getting data from JSON data of siblings in the returned object, but I'm having trouble applying that information to my situation:
I have a bunch of objects that are getting returned as JSON from a REST call and for each object with a node of a certain key:value I need to extract the numeric value of a sibling node of a specific key. For example:
For the following list of objects, I need to add up the numbers in "file_size" for each object with matching "desc" and return that to matching input values on the page.
{"ResultSet":{
Result":[
{
"file_size":"722694",
"desc":"description1",
"format":"GIF"
},
{
"file_size":"19754932",
"desc":"description1",
"format":"JPEG"
},
{
"file_size":"778174",
"desc":"description2",
"format":"GIF"
},
{
"file_size":"244569996",
"desc":"description1",
"format":"PNG"
},
{
"file_size":"466918",
"desc":"description2",
"format":"TIFF"
}
]
}}
You can use the following function:
function findSum(description, array) {
var i = 0;
var sum = 0;
for(i = 0; i < array.length; i++) {
if(array[i]["desc"] == description && array[i].hasOwnProperty("file_size")) {
sum += parseInt(array[i]["file_size"], 10);
}
}
alert(sum);
}
And call it like this:
findSum("description1", ResultSet.Result);
To display an alert with the summation of all "description1" file sizes.
A working JSFiddle is here: http://jsfiddle.net/Q9n2U/.
In response to your updates and comments, here is some new code that creates some divs with the summations for all descriptions. I took out the hasOwnProperty code because you changed your data set, but note that if you have objects in the data array without the file_size property, you must use hasOwnProperty to check for it. You should be able to adjust this for your jQuery .each fairly easily.
var data = {};
var array = ResultSet.Result;
var i = 0;
var currentDesc, currentSize;
var sizeDiv;
var sumItem;
//Sum the sizes for each description
for(i = 0; i < array.length; i++) {
currentDesc = array[i]["desc"];
currentSize = parseInt(array[i]["file_size"], 10);
data[currentDesc] =
typeof data[currentDesc] === "undefined"
? currentSize
: data[currentDesc] + currentSize;
}
//Print the summations to divs on the page
for(sumItem in data) {
if(data.hasOwnProperty(sumItem)) {
sizeDiv = document.createElement("div");
sizeDiv.innerHTML = sumItem + ": " + data[sumItem].toString();
document.body.appendChild(sizeDiv);
}
}
A working JSFiddle is here: http://jsfiddle.net/DxCLu/.
That's an array embedded in an object, so
data.ResultSet.Result[2].file_size
would give you 778174
var sum = {}, result = ResultSet.Result
// Initialize Sum Storage
for(var i = 0; i < result.length; i++) {
sum[result[i].desc] = 0;
}
// Sum the matching file size
for(var i = 0; i < result.length; i++) {
sum[result[i].desc] += parseInt(result[i]["file_size"]
}
After executing above code, you will have a JSON named sum like this
sum = {
"description1": 20477629,
"description2": 1246092
};
An iterate like below should do the job,
var result = data.ResultSet.Result;
var stat = {};
for (var i = 0; i < result.length; i++) {
if (stat.hasOwnProperty(result[i].cat_desc)) {
if (result[i].hasOwnProperty('file_size')) {
stat[result[i].cat_desc] += parseInt(result[i].file_size, 10);
}
} else {
stat[result[i].cat_desc] = parseInt(result[i].file_size, 10);
}
}
DEMO: http://jsfiddle.net/HtrLu/1/