Function in sheet has stopped working recently - google-apps-script

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.

Related

Using ReplaceWith to find & replace text in a google sheet

This may be a dumb question but I was unable to find an answer on stackoverflow, youtube, or the developers (google) site either for this issue.
I'm trying to use createTextFinder to find a certain word, and replace it with a new word. Ideally I'd like to replace the 2nd instance of the word instead of the first, however if that isn't possible that's OK. I'm also trying to ensure that my function can find these words dynamically instead of resting on defined ranges such as A1:D2 as an example.
So for our example below trying to change the 2nd instance of Apple to Pie.
What I find really bizarre, is that replaceWith doesn't seem to work, but replaceAllWith did work.
Problem:
Unable to have replaceWith work with the createTextFinder method. Receiving the error
"Exception: Service error: Spreadsheets"
Current Sheet:
Expected Outcome:
Troubleshooting I've tried:
Attempted to use startFrom and use a range prior to the 2nd instance of Apple but this didn't seem to work
Attempted to make another textfinder in the same function, however I don't think you're allowed to? I did this in order to do my prior attempt
changed replaceWith to replaceAllWith which worked, but then tried to have it find "Pie" in the same function and change the first instance back to "Apple" but this didn't work
Tried to use the findNext() feature as well, but this unfortunately did not work, and I'm unsure how to use this with the replaceWith method.
Common errors occuring during these attempts is the program stating I do not have a proper function or that the parameters don't match the method signature
Code:
function findText() {
const workSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1');//I have a few tabs and would like to call to them directly
const tf = workSheet.createTextFinder('Apple');
tf.matchEntireCell(true).matchCase(false);//finds text "Apple" exactly
tf.replaceWith('Pie');
}//end of function findText
Resources:
Google Developers on replaceWith
function replacesecondinstanceofword( word = "Apple",replacement = "Peach") {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet1');
const tf = sh.createTextFinder(word).matchEntireCell(true).findAll();
tf.forEach((f,i) => {
if(i == 1) {
sh.getRange(f.getRow(),f.getColumn()).setValue(replacement)
}
});
}
Learn More
Based on Cooper's solution:
function replace_second(word = "Apple", replacement = "Peach") {
try {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1')
.createTextFinder(word).matchEntireCell(true).findAll()[1]
.setValue(replacement);
} catch(e) {}
}
You need to call .findNext() at least once to replace the first matched cell.
function findText() {
const workSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
'Sheet1'
);
const tf = workSheet.createTextFinder('Apple');
tf.matchEntireCell(true).matchCase(true); //finds text "Apple" exactly
let match = -1;
while (++match < 2) tf.findNext();//for second match
tf.replaceWith('Pie');
}

Logger.getLog() is not working: Google Apps Scripts

I wanted to view my log from the sheet front end, I tried following workaround but it seems getLog() function is not working.
// log adding function
function addLogs()
{
Logger.log("Adding my test log");
}
// log display function
function viewLog()
{
var logs = Logger.getLog(); // issue is here
Browser.msgBox(logs); // gives empty
var htmlOutput = HtmlService
.createHtmlOutput(logs)
.setSandboxMode(HtmlService.SandboxMode.IFRAME).setHeight(500);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Sheet Log'); // gives empty
}
Try combining your functions together as a nested function. When you run the code, you have added to the log in one function, and called an empty log in the other.
You will either need to add to the log and call it in the same function or nest the functions together so that when you run the topmost function, it runs all processes.
Did you call the function addLogs() at all? It's not going to run on it's own and hence the log will be empty at the beginning. Correct behaviour.

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.

Google Apps Script Execution Order

Having trouble getting GAS to execute functions in the order I need. In this code:
function documentUpload(e) {
var app = UiApp.getActiveApplication();
app.getElementById('documentValue').setText('Uploaded');
app.getElementById('documentValueLabel').setStyleAttribute('color', 'black');
checkSubmit(e);
return app;
}
...it always runs checkSubmit before changing the text. Which is useless because one of the things that checkSubmit checks is whether documentValue has text.
I saw this post and tried adding LockService like so:
function documentUpload(e) {
var app = UiApp.getActiveApplication();
app.getElementById('documentValue').setText('Uploaded');
app.getElementById('documentValueLabel').setStyleAttribute('color', 'black');
var lock = LockService.getPrivateLock();
lock.waitLock(10000);
checkSubmit(e);
lock.releaseLock();
return app;
}
...but I'm not getting any different results. Same thing for Utilities.sleep().
Thanks in advance for any suggestions!
the UI is updated when you return app . That means that any function call from inside your function cannot see the changes you made to your UI from inside the same function.
You'll have to think differently, ie probably split your code in 2 functions to allow to return the app (in other words to update the UI) before calling the function that reads its content.
EDIT : when I look at your code it seems that the only thing you want to do before starting the download is to change a text value and a style attribute... if so you can use a clientHandler that will execute immediately (see this other recent post) maybe this can solve your problem... let us know if it does.

Google Script - Simple function not doing anything

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