Highcharter and organization chart customisation - javascript

I am tring to make a WBS chart using highcharter R package.
I wish to be able to plot the differents tasks per actions in a straight way under the box whom they come from, rather than in wages. I struggle to find the appropriate option to control this. (even after checking this here https://api.highcharts.com/highcharts/plotOptions.organization)
See the code below and what does it returns. Which is almost what I expected, but not exactly. I found the way to control the column position, but this is not working for rows. Moreover the task order is mixed in a weird way for the tasks in column 8 which is not expected of course.
library(highcharter)
highchart() %>%
hc_chart(type = 'organization', inverted = TRUE) %>%
hc_title(text = 'WBS') %>%
hc_add_series(
name = 'WBS',
data = list(
#Liste action
list(from = 'T', to = 'A1'),
list(from = 'T', to = 'A2'),
list(from = 'T', to = 'A3'),
list(from = 'T', to = 'A4'),
#A1
list(from = 'A1', to = 'b1'),
list(from = 'b1', to = 'P'),
list(from = 'P', to = 'F1'),
list(from = 'F1', to = 'AqDo'),
list(from = 'AqDo', to = 'Ay1'),
list(from = 'Ay1', to = 'R1'),
list(from = 'R1', to = 'Ar1'),
#A2
list(from = 'A2', to = 'b2'),
list(from = 'b2', to = 'Cx'),
list(from = 'Cx', to = 'F2'),
list(from = 'F2', to = 'Pr'),
list(from = 'Pr', to = 'Ay2'),
list(from = 'Ay2', to = 'R2'),
list(from = 'R2', to = 'Ar2'),
#A3
list(from = 'A3', to = 'b3'),
list(from = 'b3', to = 'Cx'),
list(from = 'Cx', to = 'F3'),
list(from = 'F3', to = 'Pr'),
list(from = 'Pr', to = 'Ay4'),
list(from = 'Ay4', to = 'R3'),
list(from = 'R3', to = 'Ar3'),
#A4
list(from = 'A4', to = 'Ar4')
),
nodes = list(
#task list
list(id = 'T', name = "name", title = "title", color = '#081358', dataLabels = list(color = 'white'), column = 0),
list(id = 'A1', title = 'action1', color = '#2D2F51', dataLabels = list(color = 'white'), column = 1),
list(id = 'A2', title = 'action2', color = '#2D2F51', dataLabels = list(color = 'white'), column = 1),
list(id = 'A3', title = 'action3', color = '#2D2F51', dataLabels = list(color = 'white'), column = 1),
list(id = 'A4', title = 'action4', color = '#2D2F51', dataLabels = list(color = 'white'), column = 1),
#A1
list(id = 'b1', title = 'A1', color = '#9EC3E7', dataLabels = list(color = 'black'), column = 2),
list(id = 'P', title = 'A1', color = '#9EC3E7', dataLabels = list(color = 'black'), column = 3),
list(id = 'F1', title = 'A1', color = '#9EC3E7', dataLabels = list(color = 'black'), column = 4),
list(id = 'AqDo', title = 'A1', color = '#9EC3E7', dataLabels = list(color = 'black'), column = 5),
list(id = 'Ay1', title = 'A1', color = '#9EC3E7', dataLabels = list(color = 'black'), column = 6),
list(id = 'R1', title = 'A1', color = '#9EC3E7', dataLabels = list(color = 'black'), column = 7),
list(id = 'Ar1', title = 'A1', color = '#B94331', dataLabels = list(color = 'white'), column = 8),
#A2
list(id = 'b2', title = 'A2', color = '#2491A9', dataLabels = list(color = 'black'), column = 2),
list(id = 'Cx', title = 'A2 + A3', color = '#2BA8C4', dataLabels = list(color = 'black'), column = 3),
list(id = 'F2', title = 'A2', color = '#2491A9', dataLabels = list(color = 'black'), column = 4),
list(id = 'Pr', title = 'A2 + A3', color = '#2BA8C4', dataLabels = list(color = 'black'), column = 5),
list(id = 'Ay2', title = 'A2', color = '#2491A9', dataLabels = list(color = 'black'), column = 6),
list(id = 'R2', title = 'A2', color = '#2491A9', dataLabels = list(color = 'black'), column = 7),
list(id = 'Ar2', title = 'A2', color = '#B94331', dataLabels = list(color = 'white'), column = 8),
#A3
list(id = 'b3', title = 'A3', color = '#34D1F4', dataLabels = list(color = 'black'), column = 2),
list(id = 'F3', title = 'A3', color = '#34D1F4', dataLabels = list(color = 'black'), column = 4),
list(id = 'Ay4', title = 'A3', color = '#34D1F4', dataLabels = list(color = 'black'), column = 6),
list(id = 'R3', title = 'A3', color = '#34D1F4', dataLabels = list(color = 'black'), column = 7),
list(id = 'Ar3', title = 'A3', color = '#B94331', dataLabels = list(color = 'white'), column = 8),
#A4
list(id = 'Ar4', title = 'A4', color = '#B94331', dataLabels = list(color = 'white'), column = 8)
)
)
and see the plot below
Maybe the answer could be found by modifying the css, or html, or javaScript source code ? but this would not be logical as an R package has been created to use highchart from Rstudio.

Related

Remove white space in highchart area chart in R

I am trying to remove the white space to the left of and right of the area chart (created in R using highchart) which is shown in red in the image below.
My reproducible code:
library(highcharter)
type <- c("A", "B", "C", "D","A", "B", "C", "D","A", "B", "C", "D")
total <- c(3300, 6080, 2780, 14054, 3638, 6360, 2722, 14148, 2681, 4761, 2080, 10080)
year <- c(2018, 2018, 2018, 2018, 2019, 2019, 2019, 2019, 2020, 2020, 2020, 2020)
df <- data.frame(type, year, total)
highchart() %>%
hc_chart(type="area") %>%
hc_add_series(data = subset(df, type == "D"), name = "D", type = "area", hcaes(x = year, y = total)) %>%
hc_add_series(data = subset(df, type == "B"), name = "B", type = "area", hcaes(x = year, y = total)) %>%
hc_add_series(data = subset(df, type == "C"), name = "C", type = "area", hcaes(x = year, y = total)) %>%
hc_add_series(data = subset(df, type == "A"), name = "A", type = "area", hcaes(x = year, y = total)) %>%
hc_xAxis(title = "", categories = c("2018", "2019", "2020"))
I've looked around online but I don't know JavaScript so it's difficult to figure out.
I changed hc_xAxis to use tickPositions instead of categories.
hc_xAxis(title = "",
min = 2018, max = 2020,
tickPositions = c(2018, 2019, 2020))

Replace array values in string and make new string as per the values

I have one array which is range and on string which is test. Now I want to replace my range array values with {q1} and replace {w1} with it's values.
I added Expected output for my scenario
let range = [25, 50, 100, 125];
let w1 = 2
let test = '{w1} + {q1}'
Expected output
let string1 = 2 + 25;
let string2 = 2 + 50;
let string3 = 2 + 100;
let string4 = 2 + 125;
const range = [25, 50, 100, 125];
const w1 = 2;
const result = range.map(x=> w1.toString() + " + " + x.toString());
const range = [25, 50, 100, 125];
const w1 = 2;
const result = range.map((x) => w1.toString() + " + " + x.toString());
console.log("res", result);
You can simple achieve this using map and array destructuring assignment.
let range = [25, 50, 100, 125];
let w1 = 2;
const [string1, string2, string3, string4] = range.map(r => `${w1} + ${r}`);
console.log(string1);
console.log(string2);
console.log(string3);
console.log(string4);
You can replace string parts using String.prototype.replace() like this:
const range = [25, 50, 100, 125];
const w1 = 2;
range.map(value => '{w1} + {q1}'.replace('{w1}', w1).replace('{q1}', value));
// ['2 + 25', '2 + 50', '2 + 100', '2 + 125']
But it's a bad practise. Much better to use string interpolation via Template literals like this:
const range = [25, 50, 100, 125];
const w1 = 2;
range.map(value => `${w1} + ${value}`);
// ['2 + 25', '2 + 50', '2 + 100', '2 + 125']
A simple way of achieving this is by looping through the range array and pushing the desired strings to a new array.
var range = [25, 50, 100, 125], w1 = 2, strings = [];
for(index of range.keys()){
strings.push(`${w1} + ${range[index]}`);
console.log(`string${index+1}: ${strings[index]}`);
}

take 2 dimensional values of rows and columns of google sheet in a object

Hi I am trying to take values of 1st and 2nd row then add them to a object although I have coded it like below
function getTime(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var d = {}
var quantity = ss.getRange(2,4,2,24).getDisplayValues();
var fruit = ss.getRange(3,4,3,24).getValues();
var quantity = quantity[0].filter(item => item);
var fruit = fruit[0].filter(item => item);
for (let i = 0; i < quantity.length; i++) {
for (let j = 0; j < fruit.length; i++){
d[quantity[i]] = fruit[j]
}
}
But I do not like this approach (secondly, this for loop stuck) so I want to make more automated so for less errors in data
what I need is an object like this
{
"Apple": 23,
"Banana" 25,
"Apple": 30,
"Grapes": "No value",
"Apple": 31
}
Is it possible to code it somewhat like below approach
dic = {}
for quantity,fruit in zip(ss.getRange(2,4,2,24).getDisplayValues(), ss.getRange(3,4,3,24).getValues()):
dic[fruit] = key
the above approach is in python but for app script I need converted it into javascript.
Sheet image for reference
Based on your Python code I assume you're struggling to make this:
var d = {};
var fruit = ["Apple", "Banana", "Apple", "Grapes", "Apple"];
var quantity = [23, 25, 30, "No value", 31];
fruit.forEach((f,q) => d[f] = quantity[q]); // <-- the JS magic is here
console.log(d);
Update
If you need to sum all existed keys (fruits) here is the way:
var d = {};
var fruit = ["Apple", "Banana", "Apple", "Grapes", "Apple"];
var quantity = [23, 25, 30, "No value", 31];
fruit.forEach((f,q) => d[f] = d[f] ? d[f] + quantity[q] : quantity[q]);
console.log(d)
Which in direct translation to Python will look about like this:
d = {}
fruits = ["Apple", "Banana", "Apple", "Grapes", "Apple"]
quantity = [23, 25, 30, "No value", 31]
for f,q in zip(fruits,quantity):
try: d[f] += q
except: d[f] = q
print(d) # output: {'Apple': 84, 'Banana': 25, 'Grapes': 'No value'}
And probably you need to handle somehow the 'No value' values. They can be a source of errors in this simply implementation.
Just in case. Here's one of the ways to handle 'No value' values:
var s = ['No value', 'No value25', 25, '10', ''];
const get_num = s => s = (s == 'No value') ? s : +s.toString().replace(/\D+/g,'');
console.log(s.map(x => get_num(x))); // output: [ 'No value', 25, 25, 10, 0 ]

How to unpivot a table using Google Apps Script?

I have a table in a spreadsheet which I want to unpivot using google apps script: each one of the month rows of the original table have to become multiple rows in the new table. The problem is the code doesn't produce the expected result.
Insted of creating arrays that ends like this (each line of the table ends with one different month):
[[...,'April'],[...,'September'],[...,'December']]
It's producing this (each line ends with the last month value of that line in the original table):
[[...,'December'],[...,'December'],[...,'December']]
Can someone see the mistake?
function myFunction() {
var ay_datos = [
['State', 'Month1', 'Month2', 'Month3', 'Number of months', 'Month'],
['California', 'April', 'September', 'December', 3, ''],
['Texas', 'January', 'March', '', 2, ''],
];
var ay_new = [
['State', 'Month1', 'Month2', 'Month3', 'Number of months', 'Month'],
];
for (i = 1; i < ay_datos.length; i++) {
var num_months = ay_datos[i][4];
var ay_linea = ay_datos[i];
for (j = 0; j < num_months; j++) {
ay_linea[5] = ay_linea[1 + j];
ay_new.push(ay_linea);
}
}
}
You're pushing the same array each time in a loop. Any modifications done to the array will reflect on all references of the same array. Use slice to copy a array:
ay_linea[5] = ay_linea[1 + j];
ay_new.push(ay_linea.slice(0));
Live snippet:
function myFunction() {
const ay_datos = [
['State', 'Month1', 'Month2', 'Month3', 'Number of months', 'Month'],
['California', 'April', 'September', 'December', 3, ''],
['Texas', 'January', 'March', '', 2, ''],
];
const ay_new = [
['State', 'Month1', 'Month2', 'Month3', 'Number of months', 'Month'],
];
for (let i = 1; i < ay_datos.length; i++) {
const num_months = ay_datos[i][4];
const ay_linea = ay_datos[i];
for (let j = 0; j < num_months; j++) {
ay_linea[5] = ay_linea[1 + j];
ay_new.push(ay_linea.slice(0));
}
}
return ay_new;
}
console.log(myFunction());

Assign different color to each bar in a google chart

I am trying to assign different colors to each bar in a columnchart, but when I try every bar gets the same color.
Code:
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Something');
data.addColumn('number', 'Numbers');
data.addRows([
['A', 40],
['B', 17],
['C', 7]
]);
// Set chart options
var options = {'title':'Megafon 27/10 2011',
'width':1300,
'height':600,
'colors' : ['red', 'blue', 'green']
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
I know this is probably really easy, but right now I can't see it. Please help me.
Thank you
Lars
Change to:
...
// Create the data table.
var data = new google.visualization.DataTable();
var raw_data = [
['A', 40],
['B', 17],
['C', 7]
];
data.addColumn('string', 'Columns');
for (var i = 0; i < raw_data.length; ++i) {
data.addColumn('number', raw_data[i][0]);
}
data.addRows(1);
data.setValue(0, 0, 'row');
for (var i = 0; i < raw_data.length; ++i) {
data.setValue(0, i+1, raw_data[i][1]);
}
// Set chart options
...
=== UPDATE ===
A simplified version:
...
// Create the data table.
var data = new google.visualization.DataTable();
var raw_data = {
'A': 40
, 'B': 17
, 'C': 7
};
data.addRows(1);
var i = 0;
for (var index in raw_data) {
data.addColumn('number', index);
data.setValue(0, i++, raw_data[index]);
}
// Set chart options
...

Categories