I am having some problems with my JavaScript and amCharts graph.
What I am trying to achieve is to reload an amChart line graph with new data from a DIV element. In my final page this DIV element will be dynamically updated and hidden so will not been seen by the end user. The graph needs to be redrawn without reloading the page.
I have an JSFiddle page with an example of my attempts to reload the data.
http://jsfiddle.net/gnuoynomis/Se2UE/1/
I have tried to:
Make objects of the points and add them into a string creating a string of objects but this does not seem to load into the graph.
function LoadNewDataFromDIV_V1()
{
//This function attempts to use a string of objects to pass to the dataprovider setting
var ChartData = document.getElementById("NewData").innerHTML;
var CD = ChartData.split("},{"); //Split the string on the different day elements
var NewChartData = "";
for(i=0; i<CD.length; i++)
{
var D = CD[i];
D = D.replace("{",""); //Remove any additional { that may exist to help with the formating later
D = D.replace("}",""); //Remove any additional } that may exist to help with the formating later
D = "{" + D + "}"; //Add a { and } to reformat the line correctly from the splitting
if(NewChartData != "")
NewChartData += ",";
NewChartData += JSON.parse(D); //Add the parsed object to the data string
}
chart.dataProvider = NewChartData; //Update graph data
chart.validateData(); //Revalidate chart data
}
I have also tried adding the objects into an array and tried passing this but still no luck.
function LoadNewDataFromDIV_V2()
{
//This function attempts to use an array to store the data and pass this to the dataprovider setting
var ChartData = document.getElementById("NewData").innerHTML;
var CD = ChartData.split("},{"); //Split the string on the different day elements
var NewChartDataArray = [];
for(i=0; i<CD.length; i++)
{
var D = CD[i];
D = D.replace("{",""); //Remove any additional { that may exist to help with the formating later
D = D.replace("}",""); //Remove any additional } that may exist to help with the formating later
D = "{" + D + "}"; //Add a { and } to reformat the line correctly from the splitting
NewChartDataArray.push(D); //Push the data to the array
}
chart.dataProvider = NewChartDataArray; //Update graph data
chart.validateData(); //Revalidate chart data
}
My reset of the graph works perfectly if I add the entire string straight in manually and this is what I am trying to replicate with the other methods.
If anyone is able to point out what I am doing wrong then I would be most grateful. I am also open to any suggestions if you think that I could be doing this in a better way.
working fiddle
http://jsfiddle.net/Se2UE/2/
the core of my change is here
var NewChartDataArray = [];
for(i=0; i<CD.length; i++)
{
var D = CD[i];
D = D.replace("{","");
D = D.replace("}","");
D = "{" + D + "}";
NewChartDataArray.push(JSON.parse(D));
}
declare NewChartDataArray as array and not string then add an object to array.
You had an array of strings, your library expects an array of objects
refer this
Related
I am using google sheets quite a lot, but now I am trying to use google apps script to get and update dynamic data retrieved from formulas into a static table.
So, I have a sheet called 'dynamique', with formulas retrieving, filtering and sorting data from other spreadsheets.
I want to be able to work on this data, so I am trying to create a button which would copy all the values from the 'dynamique' sheet into another sheet called 'statique'. That is, I want a formula which would check if the values from the column C of the 'dynamique' sheet are in the column C of the 'statique' sheet. And if the values aren't there, I want the script to copy them. (columns A and B are empty)
I've managed to get my script to work for one column, but now, I want to copy the whole line.
For example, if the value in dynamique!C10 can't be found in statique!C:C, my script writes the value of dynamique!C10 in the first empty cell of the column statique!C:C. But I want it to write dynamique!C10:J10 into my destination sheet (say it's going to be maybe statique!C8:J8).
Here is my code, working for only one cell.
function dynamicToStatic() {
var dynSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("dynamique");
var staSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("statique");
var dynLength = dynSheet.getRange("C1:C").getValues().filter(String).length;//.getLastRow();
var staLength = staSheet.getRange("C1:C").getValues().filter(String).length;
var staRange = staSheet.getRange(6,3,staLength-1);
var staValues = staRange.getValues();
var rangeToCheck = dynSheet.getRange(6,3,dynLength-1,8);
var valuesToCheck = rangeToCheck.getValues();
var numRows = rangeToCheck.getNumRows();
var staNumRows = staRange.getNumRows();
for (i = 0; i<= numRows; i++) {
var row = valuesToCheck[i];
var index = ArrayLib.indexOf(staValues , -1 , row);
if (index == -1) {
//if (staValues.indexOf(row) != -1) {
staSheet.getRange(i+6,3,1,8).setValues(row);
}
}
var timestamp = new Date();
staSheet.getRange(4,3).setValue('List updated on the: '+timestamp);
}
Now I can't manage to retrieve the whole line of the array, so as to be able to copy it using range.setValues(). I always get error messages.
Any help would be more than appreciated...
function gettingFullRows() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const shsr=2;//data startrow
const vA=sh.getRange(shsr,1,sh.getLastRow()-shsr+1,sh.getLastColumn()).getValues();
let html='';
vA.forEach((r,i)=>{
html+=Utilities.formatString('<br />Row:%s is %s',i+shsr,r.join(','));
});
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), "Row");
}
So i did some re-writing to your code and made some comments in there. I hope this will make some things clear.
Array's are 0 indexed. So if the value is NOT found in the .indexOf then it would return -1. Also (for speed) i first push all the result to a array and then set the array in one "action" this saves a lot of time. The calls to and from a sheet takes the most time.
For the conversion to a 1d array i used spread operator
See this link for difference in const / var / let
The timestamp string i updated with the use of Template literals
If you have some questions, shoot! (also i did not test this ofcourse)
function dynamicToStatic() {
const dynSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("dynamique");
const staSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("statique");
const dynValues = dynSheet.getRange(1,3,dynSheet.getLastRow(),8).getValues();
//This is a 2d array
const staRaw = staSheet.getRange(6, 3, staSheet.getLastRow()).getValues();
//Convert to 1d array, for the indexoff later on, this way it is easier.
const staValues = [].concat(...staRaw);
//to store the output, as a 2d array, inside the if you see i push it in as array so you have the 2d array for the setValues.
const output = [];
for (let i = 0; i < dynValues.length; i++){
//i = the index of the array (row) inside the array of rows, the 0 would be the values of column C.
if (staValues.indexOf(dynValues[i][0]) >= 0){
output.push([dynValues[i]]);
}
}
//Start by the lastrow + 1, column C(3), ouput is a array of arrays(rows), then get the [0].lengt for the columns inside the row array.
staSheet.getRange(staSheet.getLastRow()+1, 3, output.length, output[0].lenght).setValues(output);
const timestamp = new Date();
staSheet.getRange(4,3).setValue(`List updated on the: ${timestamp}`);
}
new to javascript. I am trying to make a new series in Highcharts using one already graphed series multiplied by another already graphed series. How do I add the new series with its own y-axis? I am using some base code that I have not done myself.
ChartOptions.Series[index].data holds an array of arrays: so for example :[1563480488000, 12.144] would be timestamp and datavalue for every data point in the series.
So I would want something like this:
[1563480488000, 12.144] * [1563480488000, 1.0] = [1563480488000, 12.144]
that's 12.144*1.0, and the timestamp is kept.
dynamicChart is a new Highcharts.StockChart(chartOptions) its just away from the snippet I am working with.
I've tried the following code.
var voltSeries = chartOptions.series[0].data;
var ampSeries = chartOptions.series[1].data;
var wattSeries = [];
for(var i = 0; i <= voltSeries.length; i++){
var valu = chartOptions.series[1].data[i,1]*chartOptions.series[0].data[i,1];
wattSeries[i,1] = valu;
wattSeries[i,0] = valu;
}
eval('window.console && console.log(voltSeries)');
eval('window.console && console.log(wattSeries)');
dynamicChart.addSeries({
name: 'Watts',
data: wattSeries
});
dynamicChart.redraw();
the output of wattSeries is an Array of (2) [NaN, NaN] but It should be the timestamp and the multiplied value.
and It seems like I cannot graph it no matter what I do.
The problem is incorrectly getting values from the array. For nested arrays you should use several parentheses: array[x][x]
var dynamicChart = Highcharts.chart('container', chartOptions);
var voltSeries = chartOptions.series[0].data,
ampSeries = chartOptions.series[1].data,
wattSeries = [],
valu;
for (var i = 0; i < voltSeries.length; i++) {
valu = voltSeries[i][1] * ampSeries[i][1];
wattSeries.push([ampSeries[i][0], valu]);
}
dynamicChart.addSeries({
name: 'Watts',
data: wattSeries,
yAxis: 1
});
Live demo: http://jsfiddle.net/BlackLabel/vpzLou6r/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Chart#addSeries
I have looking into this issue for a while, but have yet to find a suitable answer (most involve switching to setChoiceValues() rather than addressing the "Cannot convert Array to Choice[]" issue with setChoices([])).
While attempting to generate form sections and questions via Google Script, I ran into the issue of not getting my answer selections to go to specific pages based on the user's answer. This appears to be the difference between setChoiceValues() and setChoices([]), with the latter allowing for page navigation as best as I can tell.
However, when attempting to put my array of new choices into setChoices([]), I get the error message "Cannot convert Array to Choice[]". My code works fine otherwise, but I need to use setChoices([]) (it seems) in order to get the page navigation that I want.
How can I loop values into an array or other container and be able to make them appear as a Choices[] object? How can I make something like this work? It seems like it should be much easier than it is, but I cannot see the solution.
Below is a segment of my code that is causing the issue:
//Form - globally accessible
var f = FormApp.openById(f_id);
//Date Iterator
var curr_date = 0;
//Time Iterator
var curr_time = 0;
//Array of Times
var Tchoices = [];
//Setting Time choices per date
while(curr_date < dates.length)
{
Tchoices = [];
curr_time = 0;
//dates is an array of objects with both d's (single date) and t's
// (array of times for that date)
var d = dates[curr_date].d;
var end_break = f.addPageBreakItem().setTitle("Times for " + d);
var f_time = f.addMultipleChoiceItem().setTitle(d);
while(curr_time < dates[curr_date].t.length)
{
end_break = end_break.setGoToPage(FormApp.PageNavigationType.SUBMIT);
Tchoices.push(f_time.createChoice(dates[curr_date].t[curr_time], end_break).getValue());
curr_time++;
}
f_time.setChoices([Tchoices]);
}
There was some minor issues with the building of your MultipleChoise object:
//Form - globally accessible
var f = FormApp.openById('someID');
//Date Iterator
var curr_date = 0;
//Time Iterator
var curr_time = 0;
//Array of Times
var Tchoices = [];
//Setting Time choices per date
while(curr_date < dates.length)
{
Tchoices = [];
curr_time = 0;
//dates is an array of objects with both d's (single date) and t's
// (array of times for that date)
var d = dates[curr_date].d;
var end_break = f.addPageBreakItem().setTitle("Times for " + d);
var f_time = f.addMultipleChoiceItem();
f.addMultipleChoiceItem().setTitle(d);
while(curr_time < dates[curr_date].t.length) //verify this while not sure what you have inside your dates array
{
end_break = end_break.setGoToPage(FormApp.PageNavigationType.SUBMIT);
Tchoices.push(f_time.createChoice(dates[curr_date].t[curr_time])); //You cannot add a pagebreak inside the elements of a choiseItem array
curr_time++;
}
Logger.log(Tchoices);
f_time.setChoices(Tchoices);
}
Check the values for dates[curr_date].t.length inside the Loop I'm not sure how you constructed the array.
You cannot add a pagebreak inside the elements of a choiseItem array
I'm working on an add-in for excel 2016 using the javascript API. I can successfully get the range into an array and get the values to show in console.log. I've also been able to get the values into a JSON array using JSON.stringify();
I need to manipulate the array to remove the empty values ("").
Can this be accomplished by using regular javascript array methods?
I'm thinking I can display the results back into a different worksheet using a similar approach like i did with var shWk
Here are some snippets of what I'm trying to do:
(function () {
"use strict";
// The initialize function must be run each time a new page is loaded
Office.initialize = function (reason) {
$(document).ready(function () {
app.initialize();
//document.getElementById("date").innerHTML = Date("MAR 30 2017");
$('#deleteTab').click(deleteTab);
$('#preview').click(preview);
$('#publish').click(publish);
});
};
function preview() {
Excel.run(function(ctx) {
//getting the colname from a date range in B2
var colName = ctx.workbook.worksheets.getItem('preview').getRange("B2");
colName.load('values');
return ctx.sync().then(function() {
//converting colname value to string for column name
var wkN = (colName.values).toString();
// displaying on the task pane
document.getElementById("tst").innerText = wkN;
// testing to confirm i got the correct colname
var shWk = ctx.workbook.worksheets.getItem('preview').getRange("B3");
shWk.values = colName.values;
//building the column connection by setting the table name located on a different worksheet
var tblName = 'PILOT_ZMRP1';
var tblWK = ctx.workbook.tables.getItem(tblName).columns.getItem(wkN);
//loading up tblWK
tblWK.load('values');
return ctx.sync().then(function(){
//this is where my question is:
var arry = tblWK.values;
for (var i=0; i < tblWK.length; i++){
if (tblWK.values !== ""){
arry.values[i][0]) = tblWK.values[i][0]
};
};
console.log(arry.length); //returns 185
console.log (arry.values);//returns undefined
tblWK.values = arry;
var tblWeek = tblWK.values;
console.log(tblWeek.length);//returns 185
console.log(tblWK.values);//returns [object Array] [Array[1],Array[2]
})
});
}).catch(function (error) {
console.log(error);
console.log("debug info: " + JSON.stringify(error.debugInfo));
});
}
What am I missing? Can you point me to some resources for javascript array handling in the specific context of office.js?
I want to thank everyone for the time spent looking at this question. This is my second question ever posted on Stack Overflow. I see that the question was not written as clear as it could've been. What i was trying to achieve was filtering out the values in a 1D array that had "". The data populating the array was from a column in a separate worksheet that had empty values (hence the "") and numeric values in it. the code below resolved my issue.
//using .filter()
var itm = tblWK.values;
function filt(itm){
return itm != "";
}
var arry = [];
var sht = [];
var j=0;
var s=0;
arry.values = tblWK.values.filter(filt);
//then to build the display range to show the values:
for (var i=0; i < itm.length-1; i++) {
if (tblWK.values[i][0]){
var arry; //tblWK.values.splice(i,0); -splice did not work, maybe my syntax was wrong?
console.log("this printed: "+tblWK.values[i][0]);
var cl = ('D'+i); //building the range for display
j++; //increasing the range
s=1;//setting the beignning range
var cll = cl.toString();//getRange() must be a string
console.log(cll);//testing the output
}
}
//using the variable from the for loop
var cl = ('D'+s+':D'+j);
var cll = cl.toString();
console.log(cll);//testing the build string
sht = ctx.workbook.worksheets.getItem('Preview').getRange(cll);
sht.values = arry.values; //displays on the preview tab
console.log (arry.values); //testing the output
The question was probably easier said by asking what vanilla javascript functions does office.js support. I found a lot help reading Building Office Add-ins using Office.js by Micheal Zlatkovsky and by reading the MDN documentation as well as the suggested answer posted here.
Regards,
J
I'm not sure what this check is trying to achieve: tblWK.values !== "". .values is a 2D array and won't ever be "".
For Excel, the value "" means that the cell is empty. In other words, if you want to clear a cell, you assign to "". null value assignment results in no-op.
You can just fetch the values form the array that contains null by using for each and can can push the null values into another array.
I'm trying to merge multiple arrays evenly/alternating in javascript/Google appScript. There are several arrays (5 or 6). I've tried 2 different methods, but neither worked. I don't work a lot with javascript honestly and I've managed to get the code to this point, but I can't get it merge properly; and most of them said merging two arrays to one (might be my problem).
I've seen plenty on php examples that were on how to do this and they are pretty straight forward in logic reading and I understand them better, but all javascript methods I've looked at and tried so far have failed to produce the results I want. I'm not sure if it's the way AppScript is formatting the arrays or they're just no made to handle more that 2.
My data looks similar to this at the moment:
var title = ["sometitle1","sometitle2","sometitle3"];
var link = ["somelink1","somelink2","somelink3"];
var date = ["somedate1","somedate2","somedate3"];
var data = ["somedata1","somedata2","somedata3"];
var all = [title,link,date,data];
var mix = [];
Note: all the variable data will/should be the same length since the data is being pulled from a spreadsheet.
My desired output is:
mix = ["sometitle1","somelink1","somedate1","somedata1","sometitle2","somelink2","somedate2","somedata2","sometitle3","somelink3","somedate3","somedata3"];
I tried using appscript to merge them with this: return ContentService.createTextOutput(title + link + data + date), but it didn't work out properly, it printed them in that order instead of merging the way I'd like them too.
Then I tried using a loop merge that I found here on sstackoverflow:
for (var i = 0; all.length !== 0; i++) {
var j = 0;
while (j < all.length) {
if (i >= all[j].length) {
all.splice(j, 1);
} else {
mix.push(all[j][i]);
j += 1;
}
}
}
But it splice merges every letter with a comma
mix = [s,o,m,e,t,i,t,l,e,1,s,o,m,e,t,i,t,l,e,2,s,o,m,e,t,i,t,l,e,3,s,o,m,e,l,i,n,k,1,...]
and doesn't alternate data either.
The code (2 version) I'm working on is: here with Output
&
Here with Output
(Also, dumb question, but do I use title[i] + \n OR title[i] + "\n" for adding new lines?)
Use a for loop and the push() method like this :
function test(){
var title = ["sometitle1","sometitle2","sometitle3"];
var link = ["somelink1","somelink2","somelink3"];
var date = ["somedate1","somedate2","somedate3"];
var data = ["somedata1","somedata2","somedata3"];
//var all = [title,link,date,data];
var mix = [];
for(var n=0;n<title.length;n++){
mix.push(title[n],link[n],date[n],data[n]);
}
Logger.log(JSON.stringify(mix));
}
And also : title[i] + "\n" for adding new lines
Edit following comments :
Your code should end like this :
...
for(var n=0;n<titles.length;n++){
mix.push(titles[n],links[n],descriptions[n],pubdates[n],authors[n]);
}
var mixString = mix.join('');// convert the array to a string without separator or choose the separator you want by changing the argument.
//Print data and set mimetype
return ContentService.createTextOutput(mixString)
.setMimeType(ContentService.MimeType.RSS);
}