renaming sheets with "full sheet" charts on them causes spreadsheet to reload - google-apps-script

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.

Related

Find Replace google spread sheet app script

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

Google Sheets – Find and Replace multiple Code

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 Appscripts: Is it possible for Docs, Presentation App to r/w from/to spreadsheet?

Regarding Google Appscripts. If creating apps with Appscrips for Google Docs, Google Presentation, and other Drive applications, is it possible to program such apps to create, read and write to Google Spreadsheets on the same Google account?
If possible, I would appreciate a link to a description of the method.
Thanks
This function will read row 12 and column1 of a spreadsheet Sheet1 and append it to the document that contains it. It also changes the value of row 13 column1 of Sheet1;
function getRow12Column1(){
var doc=DocumentApp.getActiveDocument();
var body=doc.getBody();
var ss=SpreadsheetApp.openById('id');
var sh=ss.getSheetByName('Sheet1');
var rg=sh.getDataRange();
var vA=rg.getValues();
body.appendParagraph(vA[11][0]);
vA[12][0]+=1;
rg.setValues(vA);
}

How do you make a google script run on whichever google sheet is open?

I made an app to insert data into a google spreadsheet. Usually you set the url of the google spreadsheet that the script is going to perform the actions specified in it.
function doGet(e){
var ss = SpreadsheetApp.openByUrl("your google spread sheet url");
var sheet = ss.getSheetByName("Sheet1");
Instead of setting a permanent url, i wanted the google script to perform the actions on a google spreadsheet that is open at that moment. This way if i create a new google spreadsheet, i don't have to change the url in the script
to add data since the app script will run on whichever spreadsheet is open.
Initially i tried this but it didn't work
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
When i used getActiveSpreadSheet and deployed it as a web app(testing the code) it gave me this error:
TypeError: Cannot call method "getSheetByName" of null. (line 4, file "Code")
Edited.
I tried this but wont work.
function doGet(e){
var newUrl = e.parameter.newurl
var ss = SpreadsheetApp.openByUrl([newurl]);
var sheet = ss.getSheetByName("Sheet1");

Access to spreadsheet in deployed web app

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