REF error when setting cell formula Google Script - google-apps-script

I have created a custom function called =matchlist using apps script. That function is working with no problem. I also created another function called refreshTBA which clears the content of a certain cell (A2) and replaces it with the formula =matchlist(Setup!$b$2)​. When I run this function while I have the sheet open, there is no problem. However, any time I navigate away from the page and open it back up, the function in the cell is =matchlist(#REF).
Here is the code for the refreshTBA function:
function refreshTBA() {
var ss = SpreadsheetApp.getActive().getSheetByName("MatchImport")
var cell = ss.getRange("A2")
cell.clearContent()
cell.setFormula('=matchlist(Setup!$b$2)')
var cell = ss.getRange("A300")
cell.clearContent()
cell.setValue('Refreshed')
}

I solved this thanks to help on the Google Product Forum.
When putting a formula using the setFormula paramter, there is no need to include the equal sign. If I use setValue then I should

Related

Google Sheets, how to run function every x column?

I have a script in google sheets with the following function:
// Function to get current active sheet-name.
function getsheetName(dummy) {
return SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
}
Currently this function runs with this code in sheets:
=getsheetname(3:55)
The reference targets my entire sheet.
So whenever I make a change to a cell in my sheet the function runs again. This causes a huge amount of loading everytime i type anything in a new cell. Can i somehow reference the function to only run when i make changes to every x column instead of every cell?
I tried changing the formula but it would just stop updating completely, tried combining strings and using the MOD operator but I couldn't figure it out (keep in mind i am very new at this so probably missing something in my tinkering).
Appreciate any help!
I believe your goal is as follows.
You want to refresh the custom function of =getsheetname() when the columns "J", "T",,, (every 10 columns).
In this case, how about the following sample script? In order to refresh the function on Google Spreadsheet, I used this method. Ref
Sample script:
In this sample, in order to refresh your custom function, the simple trigger of onEdit is used. Please copy and paste the following script to the script editor of Spreadsheet. And, please save the script. When you use this script, please edit the columns "J", "T" and so on. By this, the script is run.
function onEdit(e) {
if (e.range.columnStart % 10 != 0) return;
const functionName = "=getsheetName";
const temp = "=temp";
const sheet = e.source.getActiveSheet();
sheet.createTextFinder(functionName).matchFormulaText(true).replaceAllWith(temp);
sheet.createTextFinder(temp).matchFormulaText(true).replaceAllWith(functionName);
}
In this case, 3:55 of =getsheetname(3:55) is not required to be used. You can use just =getsheetname().
If you changed the function name of your custom function, please modify const functionName = "=getsheetName";.
Reference:
Simple Triggers

Using Apps Script to return to certain cell and make it editable-ready in Google Sheet

I'm quite new to Apps Script. I hope someone could help me please.
I wanted to create an Apps Script in Google Sheet where the script will return to cell C4 and make it editable-ready. My script is as below:-
function EditC4() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('C4').activate();
}
Problem with this script is that just made C4 active but it is un-editable. Pressing F2 when the C4 is being made 'active' does not work as well. I'm calling the EditC4 function from another function.
I prefer not to use "Browser.msgBox" to make it edit-ready. Could someone please help? I search everywhere but could not find the answer.
Explanation:
The activate() method is used mainly by macros to register some cells or ranges as active and then use getActiveRange() or getActiveCell() to get these ranges back.
In your case, you want to "highlight" or "mark" a particular cell so it can be edited directly with the keyboard.
In this case you want to use activateAsCurrentCell() .
Also it is a better practice to get the range object from the sheet object and not directly from the spreadsheet object.
Solution:
function EditC4() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange('C4').activateAsCurrentCell();
}
Illustration:

Prevent a function in Google App Scripts from updating on a cell edit

I am trying to sort a list of 32 names in column A randomly to column B, I found this formula to do this:
=sort('Sheet1'!A2:A33,arrayFormula(randbetween(sign(row('Sheet1'!A2:A33)),100)),true)
This works great, but I then want to be able to use the new/random list in column B to use in other formulas. The problem is that any time you update any cell (even on another sheet) the list re-randomizes, preventing me from using any of the cells from the random list.
So I tried to take the formula out of the cell it was in and putting the formula in a menu option, thinking it would prevent the sheet/cell from updating with this Apps Script:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Custom Menu')
.addItem('Menu1', 'menuOption')
.addToUi();
}
function menuOption() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("B2");
cell.setFormula("=sort('Sheet1'!A2:A32,arrayFormula(randbetween(sign(row('Sheet1'!A2:A33)),100)),true)");
}
But it still re-randomizes the list in column B whenever a cell is edited. Is it possible to call a formula or App Script function only once, when ran?
Thanks,
Formulas inside cells update with every edit, for the problem you are having you must be calling it within a cell somewhere on the spreadsheet.
You need to remove this call and only run it via the scripts interface or the menu button.
or
If you don't mind wasting google server resources set a boolean value in a cell somewhere on your spreadsheet and check the value before you run the sorting aspect of the script.

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...

Custom function throws a "You do not have the permission required to setValue" error

I am trying to set some value to a cell in a Google Spreadsheet:
function exampleFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range1 = sheet.getRange("A1");
var value1 = range1.getValue();
value1+=1;
range1.setValue(2);
return value1;
}
If I am trying to affect a cell with this function, this error appears:
You do not have the permission required to setValue. (line 10, file "ddd")
Do you know how I could make that possible? I actually want the affected cell to take the value of the cell A1 and increase the value of A1 by 1.
from the documentation :
Custom functions return values, but they cannot set values outside the cells they are in. In most circumstances, a custom function in cell A1 cannot modify cell A5. However, if a custom function returns a double array, the results overflow the cell containing the function and fill the cells below and to the right of the cell containing the custom function. You can test this with a custom function containing return [[1,2],[3,4]];.
reference : Custom Functions in Spreadsheets
It looks that you are using the above function as a custom function, in other words, it is called by cell formula on the Google Sheets UI, in the following way:
=exampleFunction()
Custom functions in Google Sheets have limitations like they can't be used to call Google Apps Script services that require permissions. The workaround is to use another mean to call the function:
Run it from the Google Apps Script Editor
Use a custom menu
Use a trigger
Also they could be called from dialogs and sidebars, Google Apps Script Web apps and by using the Google Apps Script execution API
It's just a little different than what we programmers think.
You can use setFormula in a Macro but not in a custom function.
Just create a simple macro from Tools > Macros > Record Macro, and then open the Script editor and change the Macro's code to your code...
Here is my Macro's code:
function SetFormula() {
var spreadsheet = SpreadsheetApp.getActive();
var formulaValue = spreadsheet.getRange('formulaText').getValue().toString();
spreadsheet.getRange('total').setFormula(formulaValue);
return formulaValue;
};
Then, to run your macro automatically (you can run that manually from Tools > Macros > YOUR-MACRO-NAME), just create a trigger as follows:
Open the Script Editor:
Then go to Triggers from the left side panel and tap on Add Trigger button:
Finally, create the trigger, select your Macro from the list (mine is SetFormula), select the Event Source as From SpreadSheet, the Event Type to On Edit, and save it.
That's it!
I named my ranges as FormulaText and total to be more flexible.
you can do that from here:
Custom functions do have permission limitations as noted above. They can run with a custom menu or you can insert an image and assign a custom script to it to use it like a button.
Using a Trigger is another way to accomplish something like this example, which makes it automatic.
A simple trigger in an App Script such as onSelectionChange(e) works without running into the permissions issue of putting a custom function into a cell. This trigger is newer than what was available in the original post. In the simple example below, cell A1 will turn white with an even integer and red with anything else. Granted, the speed at which the triggers fire may vary. It's not always as instantaneous as one might expect.
function onSelectionChange(e) {
const sheet = SpreadsheetApp.getActive()
var value1 = sheet.getRange("A1").getValue()
if(value1 % 2 == 0) {
sheet.getRange("A1").setBackground("#FFFFFF") //white
} else {
sheet.getRange("A1").setBackground("#FF0000") //red
}
}