Google Script - setValue - google-apps-script

I am trying to learn Google Script. I want to write a script that uses a For Loop to save the value of each cell, clear the cell, then paste that saved value back into it. The data is in cells C6 - C17. So far, I am able to get my For Loop to work clearing each cell one by one with a 1sec pause in between but I cant figure out how to use setValue to copy the value back into the cell. If I change the last line to source.setValue("test") then my script works, clearing each cell then replacing it with "test".
Here is my code:
function forceRefresh() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Fidelity Daily");
for (var i =6 ; i<=17;i++)
{
var source = sheet.getRange(i,3);
var values = source.getValues();
source.clear();
Utilities.sleep(1000);
source.setValue(values);
}
}

Values retrieved by getValues() is 2 dimensional array. In your script, values is [["value"]]. So for your script in your question, when you want to import values to a cell using setValue(), it is required to modify as follows.
From :
source.setValue(values);
To :
source.setValue(values[0][0]);
Note :
If you want to retrieve one value from one cell, you can use getValue(). In this case, value retrieved by getValue() can be used by source.setValue(value);.
References :
getValue()
getValues()
setValue()
I don't know whether this is an answer for you. If I misunderstand your question, I'm sorry.

I was able to solve my issue by adding the command SpreadsheetApp.flush() after the source.clear() command.

The answer for your second question.
Utilities.sleep only runs in the beginning of each function only one time. I hope this helps.
And unfortunately there is no such command like delay(); or something, in google script.

Related

Populate rows with the sheets names of an spreadsheet

I have an spreadsheet that contains multiple sheets with some recipes. I'm storing the sheets' titles in the first sheet manually, to reference the recipes titles on another spreadsheet, but this doesn't scale well, so I want to automate the process. I believe I can't do that with any of the built in functions, so I'm trying to build a custom function to do it.
I already know some coding, but my experience with google API is very limited. My current attempt is returning the following exception: "You do not have the permission to call set value". After google this error, I discovered that custom functions seemingly cannot set values to another cells, so I'm here to find an alternative to such a trivial behavior.
This is my current code:
function updateSheetTitles() {
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var cell = SpreadsheetApp.getActiveSpreadsheet().getCurrentCell();
var row = cell.getRow();
var column = cell.getColumn();
for (var i=0 ; i<sheets.length ; i++){
if(i<1) //For passing trought the first sheet
return;
cell.setValue(sheets[i].getSheetName);
var range = SpreadsheetApp.getActiveSheet().getRange(row+1, column, 1, 1);
cell = SpreadsheetApp.getActiveSheet().setCurrentCell(range);
}
}
And here's and image to illustrate what I want:
This is probably an easy task, but I failed to find a way to build this, so any ideas to accomplish that would be appreciated.
I believe your goal as follows.
You want to retrieve sheet names in the active Google Spreadsheet.
You want to put the sheet names to the active cell.
You want to achieve this using the custom function.
Modification points:
Unfortunately, setValue cannot be used in the custom function. I think that the reason of your issue is due to this.
In your script, at cell.setValue(sheets[i].getSheetName);, the method of getSheetName is not run. If you want to use this method, please add () like getSheetName().
SpreadsheetApp.getActiveSpreadsheet() can be declared one time.
In order to achieve your goal, I would like to propose a custom function for creating an array including the sheet names and returning the array.
When above points are reflected to the sample script, it becomes as follows.
Modified script:
Please copy and paste the following script to the script editor of Google Spreadsheet. And, please put the custom function of =updateSheetTitles() to a cell. By this, the sheet names are returned to the row direction.
function updateSheetTitles() {
return SpreadsheetApp.getActiveSpreadsheet().getSheets().map(e => [e.getSheetName()]);
}
From your replying, when you want to retrieve the sheet names except for 1st and 2nd sheet, you can also use the following script.
function updateSheetTitles() {
return SpreadsheetApp.getActiveSpreadsheet().getSheets().map(e => [e.getSheetName()]).slice(2);
}
References:
Custom Functions in Google Sheets
map()
getSheetName()

Google Sheets Script to find formulas and copy/paste them into notes

I like to copy/paste as values all of my older sheets to save resources, but I don't want to remove the formulas as I rely on them to re-create them in the future (some are quite complicated). I thought a good alternative would be to copy each formula into its cell's note before I paste as values only, so I thought I could write a script to do this, preferably throughout an entire worksheet. I confess I'm googling as I go here, but am I on the right track? Do I have the right variables to start working on the loop?
function CopyFormulaToNote() {
/* I dont' want to get just the active sheet but all of them
look into how to do that */
var ss=SpreadsheetApp.getActive().getActiveSheet();
var lr=ss.getLastRow();
var lc=ss.getLastColumn();
var range=ss.getRange(1,1,lr,lc);
/* Find the first formula in the entire spreadsheet
I doubt it will just find all formulas per se without specifying that a formula begins with =
although there is a getFormula function...
and if I do have to specify that I think what I have below says to look for = as the first character */
var search=range.createTextFinder().matchFormulaText("^[=]"); //search for formula ie first character =
var result=search.getCurrentMatch(); //I *think* this would get the 1st result
var cell=result.getCell(row, column); //get the cell range of the result
var note=cell.setNote(note); //create a cell note for that cell
/* and now create a loop to do it everywhere that includes */
result.CopyTo(note); //copy the result into the note
}
You want to retrieve the formulas from all cells in all sheets in the Google Spreadsheet.
You want to put the retrieved formulas to each cell as the note.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
I thought that in your case, the script can be simpler by getFormulas() and setNotes().
Sample script:
function myFunction() {
SpreadsheetApp
.getActiveSpreadsheet()
.getSheets()
.forEach(function(sheet) {
var range = sheet.getDataRange();
range.setNotes(range.getFormulas());
});
}
References:
forEach()
getFormulas()
setNotes(notes)
If I misunderstood your question and this was not the direction you want, I apologize.

Trigger a script when a formula changes a cell value

I'm using a Google script then sends out an email when a certain column in a Google sheet is changed. The information in the cell is either inputted manually, or completes using a formula based on information in other cells.
The script works fine when information is manually entered, but not when the formula runs. I've read up on it and realise that a formula calculation doesn't count as an edit, so how do I get the script to run?
It's currently set up to trigger from the spreadsheet when there's an edit.
Below is the part of my script that covers the column/cell in question.
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
if(sheet.getActiveRange().getColumn() == 12)
There's a lot more included in the script so I haven't copied everything onto here. Many thanks in advance.
There is no trigger that can run when a formula changes.
Try figure out, what conditions is your formula depends on:
if it is another cell, entered manually, then use those cell to trigger it's changes with onEdit
if the formula imports data from external source, use random or time functions, you'd better use onTime trigger.
if the formula uses importrange then go to the range you import and see the original range, return to step 1 → 2...

How to evaluate a spreadsheet formula within a custom function?

In a spreadsheet I can enter =SIN(45)+123 in a cell, and it will be evaluated.
How can I evaluate spreadsheet functions within a custom function, something like an "eval"
function that would work like this :
function myFunc() {
return Sheet.eval("=SIN(45)+123")
}
is it possible ?
Note that I don't care about the SIN function in particular, what I want is to have access to the complete arsenal of spreadsheet functions (PMT, QUERY, NPER, etc..)
Spreadsheet functions from Apps-Script
Not possible - This has been asked many times. Suggest you check the google-apps-script issue list to see if anything has changed. But last I checked, there is no way to do it, and they have no plan to add it. https://code.google.com/p/google-apps-script-issues/issues/list
Ethercalc - java script spreadsheet formulas
If you need to, you can always copy the code from "ethercalc" as it has a java script versions of the spreadsheet formulas.
https://github.com/audreyt/ethercalc
I know this is an old question, but it might help someone.
just assign the formula to a range, then grab the value.
//asign a formula to the range
var range = sheet.getRange("A1").setFormula("=SUM(D1:D100)");
//get the result
var result = range.getValue();
//clean up
range.setFormula("");
I got this working. Using set value will do the trick. Thus something like this:
function MyFun1(){
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange('A1').setValue(Myfun2())
}
function MyFun2(){
return "=SIN(45)+123"
}
Hope this helps!
I think you need to divide this issue up into two different concerns.
Do you want to grab data that is already on the spreadsheet, perform a calculation, and then print a result, or do you want to use the sin() function on calculations in code unrelated to the data in the spreadsheet?
If you are trying to do the latter, you should be able to reference spreadsheet functions by using Math.sin() in your Google Apps Script. For more information on using the sin() function in JavaScript, check this post out: http://www.w3schools.com/jsref/jsref_sin.asp
If you are trying to do the former, then what you should do is use a readRows() function (more information available here: http://gassnippets.blogspot.com/2012/11/create-your-first-google-apps-script.html) to load your spreadsheet data into a variable (or variables) in memory, perform your calculations, and print the final result out to the spreadsheet using a similar function.
Let me know if this helps.
I came across this question in an attempt to find a way to evaluate part of a function like it is possible in Excel.
Here is my dirty workaround - instead of outputting the result in an msgbox, you could simply store the value or displayvalue of the activecell in a variable and use it to your liking.
Notice however, that the function will temporarily overwrite whatever you have in your currently selected cell and it will need to recalculate the sheet before the result is available. Hence it's not a viable solution if you need to evaluate multiple cell values.
function evalPart() {
var ui = SpreadsheetApp.getUi();
myPart = Browser.inputBox("Enter formula part:", ui.ButtonSet.OK_CANCEL);
if (myPart != "cancel") {
myActiveCell = SpreadsheetApp.getActiveSpreadsheet().getActiveCell();
myBackup = myActiveCell.getFormula();
myActiveCell.setFormula(myPart);
Browser.msgBox("Result of \\n \\n" + myPart + " \\n \\n " + myActiveCell.getDisplayValue());
myActiveCell.setFormula(myBackup);
}
}
I don't know if it's possible with high-level functions. However, it's possible with some common and easy-to-understand functions like (sum, subtract etc).
Following is the code I used to set values after the calculation is done in scripting itself.
function MyFun1() {
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange('A1').setValue(MyFun2());
}
function MyFun2() {
var one = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Dashboard");
var two = one.getRange('A2').getValue();
var three = one.getRange('A3').getValue(); return two*three;
}
Don't forget to add a trigger "onEdit" on Myfun1() to automatically update the return value.

Is it possible to do ImportRange in Google Apps Script?

I have been playing around with Google Apps Script today and I am trying to code some custom spreadsheet functions. I have done some searching but cannot find an answer to my query.
I know that on a Google Spreadsheet you can use ImportRange in a cell on a spreadsheet like this:
=ImportRange(spreadsheet_key;sheet!range_of_cells)
My questions are is it possible to do something similar in a Google Apps Script and if so, how?
I want to import a range of cells from a sheet on another spreadsheet (not a sheet on the spreadsheet where the script will reside).
Yes, this is perfectly possible. You just need to call SpreadsheetApp.openById and then get the desired sheet and ranges normally.
Please take a look at the documentation : range.getValues() and range.setValues() are very basic GAS methods and are pretty well described.
Read the tutorial as well.
It seems Google, in their infinite wisdom, has altered the behavior of openById and similar functions. They are no longer allowed in the context of custom functions.
See https://code.google.com/p/google-apps-script-issues/issues/detail?id=5174 for more details.
They suggest using IMPORTRANGE as a workaround, but as previously mentioned, this needs to be called within a cell.
Our solution was to use IMPORTRANGE in the sheet, and pass the acquired data into our custom function, as the data set was small. I hope this information helps!
I needed to do this recently. This is what I came up with, simply hard-coding the spreadsheet key and range into ahab's myImportRange function
// to be used in the spreadsheet like so: = myScriptedImportRange( GoogleClock() )
// no need to include key or range because they are in the script here
//
// the third parameter - GoogleClock() - triggers an automatic update every minute.
// updated 2011-07-17 (ahab): better regex to strip sheetname of *outer* single quotes
// updated 2013-01-27 (ben) to hard-code key and range
function myScriptedImportRange( ) {
var key = "PUT YOUR DATA_SPREADSHEET_ID IN HERE"
var sheetrange = "PUT YOUR SHEET AND CELL RANGE IN HERE"
var shra = sheetrange.split("!") ;
if (shra.length==1) shra[1]=shra[0], shra[0]="";
var sheetstring = shra[0].replace( /^'(.*)'$/g , "$1") // was: replace( /'/g , "") ; updated 2011-07-17 (ahab)
var rangestring = shra[1]
var source = SpreadsheetApp.openById( key )
if ( sheetstring.length==0 ) sheet = source.getSheets()[0] ;
else sheet = source.getSheetByName( sheetstring ) ;
return sheet.getRange( rangestring ).getValues();
}
In my case I have a set of private sheets, an intermediate sheet that uses the regular myImportRange and VMERGE with some SQL to combine selections from the private sheets into the intermediate sheet, and then a public sheet that simply has one cell containing = myScriptedImportRange( GoogleClock() )
Note that there is a similar approach here: https://stackoverflow.com/a/11857014
Note also that the ImportRange function and related functions often have a problem of not displaying the imported data when the origin workbook(s) is/are not open. A simple way around this has been described in a comment here: https://stackoverflow.com/a/11786797