Google Sheets, how to run function every x column? - google-apps-script

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

Related

Google Spreadsheets Add old number with new number

I am trying to add a number to an old number. For example A1 contains "5", and I write "10" into B1, then A1 should show "15".
When I type "10" in B1 again, then A1 should show "25", so A1 adds the previous number with the new number.
I dont want to do mental arithemtic every time.
Is this possible with Google Sheets?
I thought that in your situation when Google Apps Script is used, your goal might be able to be achieved. The sample script is as follows.
Sample script:
Please copy and paste the following script to the script editor of Google Spreadsheet, and save the script.
function onEdit(e) {
const range = e.range;
if (range.getA1Notation() != "B1") return;
const [a, b] = range.offset(0, -1, 1, 2).getValues()[0];
range.offset(0, -1).setValue(a + b);
}
Testing:
When you use this script, please put a number to the cell "B1". By this, the script is automatically run by firing the OnEdit trigger as follows. So when you directly run the script with the script editor, an error occurs because the event object is not declared. Please be careful this.
Note:
This is a simple sample script from your question. So when your actual situation is different from your question, please modify the above script.
Reference:
Simple Triggers

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()

Writing in a newly created Google spreadsheet using an external script

I have built a short script that takes inputs from a Google Form and creates a new spreadsheet. But when I try to set that values inside the sheet, nothing happens. Not sure if this is due to my code or to the lack of authorization given this is a newly created file. Here is my code:
var templates = DriveApp.getFilesByName('Template'); // get the files named Template (only one)
var template = templates.next(); // get the first files in the list
var newFile = template.makeCopy(name,newFolder); // Make a copy of the Template file and put it in NewFolder
var ss = SpreadsheetApp.open(newFile);
var sheet = ss.getSheets()[0];
sheet.getActiveRange('B1').setValue(name);
Thanks for your help
I think that in your script, an error occurs at getActiveRange('B1'). Because the method getActiveRange() of Class Sheet has not arguments. Ref I think that this is the reason of your issue. In this case, an error like The parameters (String) don't match the method signature for SpreadsheetApp.Sheet.getActiveRange. occurs. I thought that the reason of nothing happens might be that from your question, the script is run by the OnSubmit event trigger might be used. In this case, please modify as follows.
From:
sheet.getActiveRange('B1').setValue(name);
To:
sheet.getRange('B1').setValue(name);
When you modify like above and run again, the value of name is put to the cell "B2" on the 1st tab in the created Spreadsheet.
Note:
If you want to append the values when the script is run, please modify sheet.getActiveRange('B1').setValue(name); as follows.
sheet.appendRow([, name]); // In this case, the value is append to the column "B".
References:
getActiveRange()
getRange(a1Notation)

REF error when setting cell formula Google 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

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