Google Script - Simple function not doing anything - google-apps-script

I made a function nearly identical to this and it worked great. This one tells me it is running but nothing actually happens in my inbox. I get no errors, either.
(This is my first day working with Google scripting so I'm sure it's a rookie mistake.)
function autoArchiveOldInboxItems() {
var search_term = "label:inbox older_than:30d";
while(GmailApp.search(search_term).length > 0){
var threads = GmailApp.search(search_term,0,100);
GmailApp.markThreadsRead(threads);
GmailApp.moveThreadsToArchive(threads);
}
}
I tried searching "in:inbox" as well as "label:inbox".

For some reason, this made it happy:
function kickOff(){
autoArchiveOldInboxItems();
}
function autoArchiveOldInboxItems() {
var search_term = "label:inbox older_than:30d";
while(GmailApp.search(search_term).length > 0){
var threads = GmailApp.search(search_term,0,100);
GmailApp.markThreadsRead(threads);
GmailApp.moveThreadsToArchive(threads);
}
}
Then, I call the kickoff function and it runs. Strangely, when I did it before, I was in the editor and chose to run that function and it kept doing nothing. Possible bug? Or maybe it's just me.
You should see my inbox now. :)

Related

Is there a way to call a custom function every couple of seconds in Google Apps Script?

I'm trying to make a silly but simple little program in google apps script and sheets where it picks a random dad joke to show you every couple of seconds. I tried using setInterval(), but I found out that it isn't included in google apps script. Any suggestions?
code:
function LOL() {
let messageList = ["Where do dads keep their jokes? In a dad-abase!","When does a joke become a dad joke? When it becomes a-parent!","Two men walk into a bar. You'd think the second one would've noticed!","Does your face hurt? 'Cause it's killing me!"]
function randInt() {
let listLength = messageList.length
let random = Math.floor(Math.random() * listLength);
return random
}
function showMessage() {
let int = randInt()
console.log(int)
return messageList[int]
}
return showMessage()
}
It would choose a random message from my list every minute to put in whatever cell has =LOL().
Here I found a solution by Tanaike that will update a custom function by using a TextFinder and combined it with Time driven trigger to automatically refresh it every minute.
Try this:
Code:
function LOL(){
let messageList = ["Where do dads keep their jokes? In a dad-abase!","When does a joke become a dad joke? When it becomes a-parent!","Two men walk into a bar. You'd think the second one would've noticed!","Does your face hurt? 'Cause it's killing me!"]
let listLength = messageList.length
let random = Math.floor(Math.random() * listLength);
return messageList[random];
}
function refresher() {
const sheet = SpreadsheetApp.getActiveSheet();
const formula = "=LOL";
sheet.createTextFinder("^\\" + formula).matchFormulaText(true).useRegularExpression(true).replaceAllWith("Loading");
sheet.createTextFinder("Loading").matchFormulaText(true).useRegularExpression(true).replaceAllWith(formula);
}
Installable Trigger Setup:
Output:
You can use the native Utilities.sleep from Serge's Answer, although I would recommend using a Trigger or async functions if you need to do anything else in the script.
Here's a quick example of implementation:
function myFunction() {
var delayInMilliseconds = 5000; //1 second
while (true){
Utilities.sleep(delayInMilliseconds)
showMessage()
}
}
You can manage Time-driven triggers manually, e.g. run a particular function everyHour(). See here

How can I bypass the invoked too many times error?

I am trying to use the following script to populate the zip codes for over 3000 cells:
function geo2zip(a) {
var response=Maps.newGeocoder()
.reverseGeocode(lat(a),long(a));
return response.results[0].formatted_address.split(',')
[2].trim().split(' ')[1];
}
function lat(pointa) {
var response = Maps.newGeocoder()
.geocode(pointa);
return response.results[0].geometry.location.lat
}
function long(pointa) {
var response = Maps.newGeocoder()
.geocode(pointa);
return response.results[0].geometry.location.lng
}
Obviously, after about 5 cells I am getting the error that the service has been invoked too many times
Simply, how do I pay (or add to the code) to be able to run the script for the cells I need?
I'm not sure about the delay. You'll have to play with it probably. And I'm also not sure if you'll be allowed to get 3000 operations in one day. But disregarding quotas for the moment, which I wouldn't recommend, you could do something like this.
It looks like this service is on a pay as you go basis so my guess is that it will cost you something. Read the links at the bottom about API use and Billing.
function loopGeocode(start) {
var start=start || 0;
var ss=SpreadsheetApp.getActive();
var sh1=ss.getSheetByName('Points');
var sh2=ss.getSheetByName('Locations');
var pt=sh1.getRange(1, 1,sh.getLastRow(),1).getValues();
for(var i=start;i<pt.length;i++) {
sh2.appendRow([i+1,pt[i][0],geo2zip(pt[i][0])])
Utilities.sleep(8000);//I have no idea what this delay should be
}
return i+1;
}
function geo2zip(a) {
var response=Maps.newGeocoder().reverseGeocode(lat(a),long(a));
return response.results[0].formatted_address.split(',')[2].trim().split(' ')[1];
}
function lat(pointa) {
var response = Maps.newGeocoder().geocode(pointa);
return response.results[0].geometry.location.lat
}
function long(pointa) {
var response = Maps.newGeocoder().geocode(pointa);
return response.results[0].geometry.location.lng
}
I'd run it off of a JavaScript timer and try running once every 6 minutes. I don't know if the withSuccessHandler() will wait that long so you might need to store the return value which tells the loop where to start counting every time. You could probably store in PropertiesService. It will take about 15 hours.
Geocoding API Use and Billing
Geocoding API Getting Started
Javascript Timer Example
After reading some of the links I would believe that 50 queries per second is acceptable so the solution may have nothing to do with adding time between samples. It's probably a matter of setting up a billing account and pay as you go.
Create, Modify, or Close Your Billing Account

Google apps script not throwing exception

I have been playing around google apps script for a while, and I stumbled across the "Your input contains more than the maximum of 50000 characters in a single cell" error. But when I tried to prevent my script from crashing because of it, using try-catch statement, it didn't work.
I checked in the Google apps script documentation site (https://developers.google.com/apps-script/), and found nothing.
Moreover, I tried to run that sample code:
function myFunction() {
try
{
var a = ""
for (i = 0; i< 50000; i++)
a += '111'
SpreadsheetApp.open(DriveApp.getFileById("FileID")).getActiveSheet().getRange(1,1).setValue(a)
}
catch (e)
{
Logger.log(e.message)
}
}
And it crashed, leaving no record in the log.
Any idea on how to prevent crashing? preferably with some code segment that will allow me to manipulate the input?
I will be grateful for any help.
EDIT
My script should handle big amounts of data, so running time is really important for me. Right now I'm using a solution that looks like
a.substring (0,50000)
But the thing that I really want to see is something that will be activated only when needed, so it will be faster...
To solve your issue of catching the "Your input contains more than the maximum of 50000 characters in a single cell" error use SpreadsheetApp.flush();
function myFunction() {
try
{
var a = ""
for (i = 0; i< 50000; i++)
a += '111'
SpreadsheetApp.open(DriveApp.getFileById("FileID")).getActiveSheet().getRange(1,1).setValue(a);
SpreadsheetApp.flush();
}
catch (e)
{
Logger.log(e.message)
}
}
Note: I am not answering the performance issue as I think that has been addressed in the previous answer.
How about something like:
var CELL_MAX_LEN = 50000; // Or whatever value you choose
function checkAndWriteCellValue(range, value) {
if (value.length > CELL_MAX_LEN) {
value = 'Too long!'; // Or something else, truncate value etc
}
range.setValue(value);
}
You could call it like this:
var range = spreadsheet.getActiveSheet().getRange(...); // Add the specifics of your range
checkAndWriteCellValue(range, value);

Function in sheet has stopped working recently

I have a function which up until recently was working fine.
function DynamicImportRange(sheet_url, sheet_name, sheet_range) {
var values = SpreadsheetApp.openByUrl(sheet_url).getSheetByName(sheet_name).getRange(sheet_range).getValues();
return values
};
I reference the function in a cell and am now getting the error: "You do not have permission to perform that action." I have authorized the function in the script editor and as I said before it was working fine for a long while up until recently. Any idea what the problem might be?
That is working for me as well. However, if it is not working for you, try doing something like this:
function DynamicImportRange(sheet_id, sheet_name, sheet_range) {
var values = SpreadsheetApp.openById(sheet_id).getSheetByName(sheet_name).getRange(sheet_range).getValues();
return values;
};
The only change I made was that instead of passing sheet_url I'm passing sheet_id and it seems to be working perfectly well.

error - "Method Range.getValue is heavily used by the script"

I posted this question previously but did not tag it properly (and hence why I likely did not get an answer) so I thought I would give it another shot as I haven't been able to find the answer in the meantime.
The below script is giving me the message in the title. I have another function which is using the same getValue method but it is running fine. What can I change in my script to avoid this issue?
function trashOldFiles() {
var ffile = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CtrlSht").getRange("B3:B3").getValue();
var files = DriveApp.getFilesByName(ffile);
while (files.hasNext()) {
var file = files.next();
var latestfile = DriveApp.getFileById(listLatestFile());
if(file.getId() ==! latestfile){
file.setTrashed(true);
}
}
};
Is it an error or an execution hint(the light bulb in the menu)?
are you using that method on other part of your code? probably in listLatestFile()?
I got the same execution hint by calling getRange().getValue() in listLatestFile() (using a loop)
and the hint always mentioned that the problem was when calling
var ffile = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CtrlSht").getRange("B3:B3").getValue();
in the function trashOldFiles() even when the actual problem was in other function.
Check if you are calling it in other place in your code, probably inside a loop.
OK, so Gerardo's comment about loops started to get me thinking again. I checked some other posts about how to re-use a variable and decided to put the listLatestFile() value in my spreadsheet -
var id = result[0][1];
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CtrlSht").getRange("B5:B5").setValue(id);
//Logger.log(id);
return id;
and then retrieved the latest file ID from the spreadsheet to use as a comparison value for the trashOldFiles() function which worked a treat.
function trashOldFiles() {
var tfile = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CtrlSht").getRange("B3:B3").getValue();
var tfiles = DriveApp.getFilesByName(tfile);
var lfile = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CtrlSht").getRange("B5:B5").getValue();
while (tfiles.hasNext()) {
var tfile = tfiles.next();
if(tfile.getId() !== lfile){
tfile.setTrashed(true);
}
}
};
Not sure if that approach was best practice but it did work for me. If anyone has suggestions for achieving this in a more elegant way, I'm all ears.