I have this very small issue and I was hoping someone could help me solve it.
This is the code.
function textFinder() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var range = sheet.getActiveRange();
var textFinder = range.createTextFinder('=');
var firstOccurrence = textFinder.findNext();
var numOccurrencesReplaced = firstOccurrence.replaceWith("=");
}
When the code runs I get
Error
TypeError: Cannot read property 'replaceWith' of null
textFinder # findReplace.gs:11
I am trying to find the = in a function that is in A1 B1 D1
I believe your goal is as follows.
You want to refresh all functions in a sheet using Google Apps Script.
In the case of refreshing the functions on Google Spreadsheet using TextFinder, I thought that these samples are useful. Ref1 Ref2 Ref3 But, in this case, I'm worried that in order to refresh all functions in a sheet, it might be a bit difficult. So, in this answer, I would like to propose a sample script for refreshing all functions in a sheet using Google Apps Script.
Sample script:
function myFunction() {
const sheet = SpreadsheetApp.getActiveSheet();
const refresh = (a, b) => sheet.createTextFinder(a).matchFormulaText(true).useRegularExpression(true).replaceAllWith(b);
refresh("^=(.+)$", "==$1");
refresh("^==(.+)$", "=$1");
}
If you want to refresh all functions in all sheets of a Google Spreadsheet, please modify SpreadsheetApp.getActiveSheet(); to SpreadsheetApp.getActiveSpreadsheet();.
References:
Class TextFinder
Related threads
Custom function won't refresh as inputs are changed
Google Sheets Function to Actively Check Cell
Refresh data retrieved by a custom function in Google Sheet
Related
in my script , I am attempting the execute my code on a specific tab.
Here is my code snippet
function sendalert() {
var sheet = SpreadsheetApp.getActiveSheet();
My google sheet has 6 tabs, but I would like my script to run always on the tab named "Operator". How do I enforce this?
I believe your goal as follows.
You want to run the script for the sheet with the sheet name of Operator in the active Spreadsheet.
For this, how about this answer?
Modification points:
In order to access to the specific sheet using the sheet name, you can use getSheetByName(name).
When getActiveSheet() is used, the opened sheet in the browser is used. If the browser is not opened, the sheet of 1st tab is used.
Modified script:
When your script is modified, please modify as follows.
function sendalert() {
var sheetName = "Operator";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetName);
// do something.
}
References:
getActiveSpreadsheet()
getSheetByName(name)
Maybe someone can help me with my Problem.
First some background: I have copied some WhatsApp chats to Google Sheets. I use Latex to generate a book containing the chats. Google Sheet is able to display all Emojis from WhatsApp, Latex, of course, isn't. So I downloaded the Emojis as png files and defined Latex commands to include those emojis as graphic.
For Example: Too display the regular smiling emoji I type \grin. I have a list with hundreds of emojis in one row and the corresponding command in the next row.
Until now I used search and replace -> replace all in the same sheet for every single type of emoji. But as this takes hours I wondered if there is any way to make this more effective.
Here is a spreadsheet with a small example: Google Sheet
Thanks in advance!
You want to replace the Emojis to the defined Latex commands.
For example, you want to replace as follows.
From 03.01.19, 00:29 - me: Hi 😊 to 03.01.19, 00:29 - me: Hi \nettnett.
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.
Flow:
The flow of this sample script is as follows. This sample script uses your shared Spreadsheet.
Retrieve data from the sheet of Codes for Smileys.
Create the request body for the findReplace request of batchUpdate method of Sheets API.
Run the method of batchUpdate.
Sample script:
This script used Sheets API. So, before you run the script, please enable Sheets API at Advanced Google services.
function myFunction() {
var dataSheet = "Codes for Smileys";
var sourceSheet = "unedited Chats with Smileys";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName(dataSheet).getDataRange().getValues();
data.shift();
var sheetId = ss.getSheetByName(sourceSheet).getSheetId();
var requests = data.map(function(row) {return {findReplace: {sheetId: sheetId, find: row[0], replacement: row[1]}}});
Sheets.Spreadsheets.batchUpdate({requests: requests}, ss.getId());
}
This sample script uses your shared Spreadsheet. So in this case, the data sheet is Codes for Smileys. And the source sheet for converting is unedited Chats with Smileys.
Note:
If you change the sheet name, also please modify above script. Please be careful this.
When you run the script for the first time, the authorization screen is opened. So please authorize the scopes for using the script.
References:
Advanced Google services
spreadsheets.batchUpdate
FindReplaceRequest
Added:
You want to put the converted values to the sheet of Chat with Latex Code.
The sample script for achieving above is as follows.
Sample script:
function myFunction2() {
var dataSheet = "Codes for Smileys";
var sourceSheet = "unedited Chats with Smileys";
var destinationSheet = "Chats with LaTeX Codes";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(dataSheet);
var data = ss.getSheetByName(dataSheet).getDataRange().getValues();
data.shift();
var srcSheet = ss.getSheetByName(sourceSheet);
var tempSheet = srcSheet.copyTo(ss);
var sheetId = tempSheet.getSheetId();
var requests = data.map(function(row) {return {findReplace: {sheetId: sheetId, find: row[0], replacement: row[1]}}});
Sheets.Spreadsheets.batchUpdate({requests: requests}, ss.getId());
var tempValues = tempSheet.getDataRange().getValues();
var destSheet = ss.getSheetByName(destinationSheet);
destSheet.getRange(destSheet.getLastRow() + 1, 1, tempValues.length, tempValues[0].length).setValues(tempValues);
ss.deleteSheet(tempSheet);
}
In this sample script, the following flow is run.
Copy the source sheet unedited Chats with Smileys as a temporal sheet.
Create request body for the batchUpdate method to the temporal sheet.
Run the batchUpdate.
Copy the converted values from the temporal sheet to the destination sheet Chats with LaTeX Codes.
In this case, the converted values are put to the last row of the sheet.
Delete the temporal sheet.
Google sheets allows charts to be moved to their own sheet. Google scripts appears to be unable to rename these sheets though, without crashing the spreadsheet and forcing it to reload.
To see what I mean try this:
1) create new spreadsheet and put some data in it.
2) create any type of chart w/ the data.
3) edit the chart and select "Move To Own Sheet..."
4) create a script w/ the following code:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
sheets[1].setName('bob');
}
5) run the script and the spreadsheet crashes with the message: "Unable to Load File"
6) reload the spreadsheet and notice that the sheet did get renamed.
Why does the spreadsheet crash? Is it possible to rename the sheet w/o crashing?
Unfortunately, I couldn't find the clear reason of the crash. But I think that there is a workaround for avoiding the crash. So how about this workaround? In this workaround, it uses Sheets API. In order to use Sheets API, please enable Sheets API at Advanced Google Services and API console. About the how to enable them, please check here.
The sample script using Sheets API is as follows.
Sample script :
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var id = ss.getId();
var sheetId = ss.getSheets()[1].getSheetId();
var resource = {"requests":[{"updateSheetProperties":{"properties":{"sheetId":sheetId,"title":"bob"},"fields":"title"}}]};
Sheets.Spreadsheets.batchUpdate(resource, id);
}
If this was not what you want, I'm sorry.
Is there a way on to run a script whenever the user switches between sheets in a Google Sheets Spreadsheet?
More or less like onOpen, but instead of running when the document is opened, it should fire every time the user switches to another sheet.
Here is my work-around for onSheetChange:
function saveActiveSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var actsheet = ss.getActiveSheet();
// The onSelectionChange() function executes in a separate thread
// which does not use any script global variables, so use the
// PropertiesService to maintain the user global state.
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('ACTIVE_SHEET', actsheet.getSheetName());
}
function onSheetChange(e) {
// Do anything needed after a new sheet/tab selection
}
function onSelectionChange(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Get current sheet name and compare to previously saved sheet
var currentactsheet = ss.getActiveSheet();
var currentactsheetname = currentactsheet.getSheetName();
var userProperties = PropertiesService.getUserProperties();
var actsheetname = userProperties.getProperty('ACTIVE_SHEET');
if (currentactsheetname !== actsheetname) { // New sheet selected
saveActiveSheet();
onSheetChange(e); // Call custom sheet change trigger
}
// Do anything needed when a different range is selected on the same sheet
else {
var range = e.range;
}
}
function onOpen(e) {
saveActiveSheet();
}
UPDATE: On April 2020 Google added onSelectionChange(e) which could be used to check if the user switched between sheets aka tabs.
At this time there isn't a trigger related to switch for one sheet to another. To learn about the available triggers in Google Apps Script, please checkout Triggers and events - Google Apps Script Guides
As a workaround you could a custom menu to and SpreadsheetApp.setActivesheet to switch between sheets by using a script instead of using tabs and including in that script a call to the function to be run when switching from one sheet to another.
I have created a "Feature request" to implement "onSheetChange" trigger at google issue tracker. You can star it, so google now you want this:
https://issuetracker.google.com/issues/72140210
And here is related question with possible workaround: How to capture change tab event in Google Spreadsheet?
you can use
sheet1.showSheet();
sheet2.hideSheet();
I am trying to access a Google spreadsheet via a Google script, that is published as a web app.
How I created the script:
from the spreadsheet, Tools/Script editor..., Spreadsheet project
and it asked for access to the spreadsheets in GDrive, so overall I assume it is attached to the spreadsheet.
The script:
function doGet() {
var ss = SpreadsheetApp.getActive();
// alternative, doesn't work either
// var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/abcdef/edit");
var sheets = ss.getSheets();
var text = ... loop over sheets and do some stuff to get the data ...
return ContentService.createTextOutput(text);
}
The error message when calling the web app:
TypeError: Cannot call method "getSheets" of null.
The function works (minus the ContentService.createTextOutput of course) when run in the editor.
You can't use the getActive() method unless the script is bound to a spreadsheet (ie script was created within the spreadsheet).
In your example with openByUrl() I would check your URL and the permissions to that sheet. Here is working example of what you were trying to do.
function doGet(){
var ss= SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1XLOVvEo2nzLARwRhsiWUrFMtF0LnofC1PQoWIeLmwgQ/edit#gid=0');
return ContentService.createTextOutput(ss.getSheets()[0].getName()).setMimeType(ContentService.MimeType.TEXT);
}