Rename sheet once copied to another Spreadsheet - remove "Copy of"? - google-apps-script

Hopefully relatively simple, but can't seem to find an answer.
I have a function that copies (archives) the current sheet to another spreadsheet, but then it's called "Copy of [sheet name]" in the destination spreadsheet.
Hoping I can get rid of the Copy of part, but setName() hasn't seemed to work.
Everything in the below code works until the last two lines.
function archiveCurrentSheet() {
SpreadsheetApp.getUi()
var areyousure = Browser.msgBox('Are you sure you want to archive this sheet?', Browser.Buttons.OK_CANCEL);
if (areyousure == "cancel" ) {
}
else {
var source = SpreadsheetApp.getActiveSpreadsheet();
var currentSheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var sheet = source.getActiveSheet();
var destination = SpreadsheetApp.openById("ID");
sheet.copyTo(destination);
var sheetRename = SpreadsheetApp.openById("ID").getSheets();
sheetRename.setName(currentSheetName);
}
}
It gives error: "TypeError: Cannot find function setName in object Sheet,Sheet,Sheet,Sheet,Sheet,Sheet,Sheet,Sheet."
Thanks!
p.s. bonus: would be how do I delete the current

The sheet.copyTo(destination) method returns the new sheet so you can do something like this.
sheet.copyTo(destination).setName(currentSheetName);

Related

Google Scripts - Can't Find Destination Sheet After Form Creation

My script creates a Google Form programmatically and sets the destination to the current Spreadsheet:
var sheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
var form = FormApp.create(acctName).setTitle(acctName).setDestination(FormApp.DestinationType.SPREADSHEET, sheetId);
// several form items added here
Next, I'd like to rename the destination Sheet and make a few formatting edits. When I do, however, the sheet doesn't seem to exist. For example, getSheets() does not contain the new Sheet! (And yes, ideally I'd like to open the sheet by ID; see function below which also doesn't work.)
var sheets = SpreadsheetApp.openById(form.getDestinationId()).getSheets();
SpreadsheetApp.setActiveSheet(sheets[0]);
The above code opens what I would consider index 1, not index 0, because the sheet isn't indexed. I even tried creating a few second delay (hoping that it was just a matter of time to allow the sync to happen between the client and server) but without any success.
I have also tried something like the following, as suggested elsewhere here on Stack Overflow, but the destination Sheet doesn't come up in getSheets() even when called through a separate function:
function getFormDestinationSheetId(form) {
var destinationId = form.getDestinationId();
if(destinationId) {
var spreadsheet = SpreadsheetApp.openById(destinationId);
spreadsheet.getSheets().forEach(
function(sheet) {
var sheetFormUrl = sheet.getFormUrl();
if(sheetFormUrl) {
var sheetForm = FormApp.openByUrl(sheetFormUrl);
if(sheetForm.getId() == form.getId()) {
return sheet.getSheetId();
}
}
}
);
}
return null;
}
I haven't been able to find anyone have a similar problem on the webs. Any advice would be appreciated. Thanks!
Welcome to Stack!
I assume your script is bound to a sheet? Depending on how you're calling the script you may not see the new sheets because of browser caching.
function myFunction() {
var sheet = SpreadsheetApp.getActive();
var sheetId = sheet.getId();
var form = FormApp.create('acctName').setTitle('acctName').setDestination(FormApp.DestinationType.SPREADSHEET, sheetId);
var ssSheets = sheet.getSheets();
var respSheet = ssSheets[0]
respSheet.getRange('A1').setBackground('RED');
respSheet.getRange('C1').setFormula('=COUNTA($C$2:$C)');
respSheet.setColumnWidth(2, 100);
SpreadsheetApp.flush();
}

How come this function isn't returning anything in Google Sheets?

I'm trying to be able to access information on the active sheet, but I can't even seem to "connect" with the sheet to begin with. I'm just wondering why this small function isn't returning anything.
I've played around with different ways to call the sheet (e.g. getActive(), getActiveSheet(), getSheetByName(), etc.), and changing the name of the sheet itself.
function CLICK (){
var sheetName = SpreadsheetApp.getActiveSheet();
return sheetName;
}
I just want it to return the sheet name so I know it's accessing the sheet properly.
For your var please try:
sheetName = SpreadsheetApp.getActiveSheet().getName();
Hi there are some different options you can choose depending on what you want to do. I would suggest to read https://developers.google.com/apps-script/guides/sheets. Here are the examples I have for you.
function myFunction() {
/* To work on the first sheet sheet of the Spreadsheet, use getName(); to get the name of the spreadsheet*/
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
/* To get the name of the active sheet*/
var sheet2 = SpreadsheetApp.getActiveSheet().getName();
/* To add values on the active cell (current selected cell)*/
var sheet3 = SpreadsheetApp.getActiveRange().setValue(sheet2);
/*To work on the sheet with a specific Name*/
var sheet4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
console.log(sheet2);
console.log(sheet4);
/*The difference between getSheets()[0] and getSheetByName("name") is that getSheets()[0]
will always work with the first sheet even if you change position and getSheetByName() will
always work with the sheet you named even if you change position, the position is 0 based*/
}
Here is another function to get name, url and id of the srpeadsheet.
function getDetails(){
var getName = SpreadsheetApp.getActiveSpreadsheet().getName();
var getUrl = SpreadsheetApp.getActiveSpreadsheet().getUrl();
var getId = SpreadsheetApp.getActiveSpreadsheet().getId();
console.log(getName);
console.log(getUrl);
console.log(getId);
}
Remember that if you are using a script editor that is attached to the Spreadsheet for sure you will be working on that spreadsheet. Now if you created a new script directly from script.google.com then you will need to first open the spreadsheet by using an Id or a url to open that specific spreadsheet.
I hope this helps.

How to set function clearContent() for single cell?

I just wondered why clearContent() function does not work very well in new google spreadsheet!
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("A:L");
var cell = ss.getActiveSelection();
var row = cell.getRow();
var column = cell.getColumn();
var range2 = sheet.getRange(row,column);
var response = Browser.msgBox('Did you confirm it?', Browser.Buttons.YES_NO);
if(response == 'yes'){Browser.msgBox('Thank you!', Browser.Buttons.OK)}
else{range2.clearContent()}
}
When I used old google spreadsheet, it worked.
But I'm using new google spreadsheet. It doesn't work.
getRange('A1:A2').clearContent(); is works.
But getRange(1,2).clearContent(); not work, even though it did work in old google spreadsheet!
Please do not tell me use old google spreadsheet.
Tell me how!!
I don't even see a .getActiveSelection() method in the ss class.
Don't see what you're doing with var range either.
We can just use the passed ss object e to get the range, then clear it when needed.
function onEdit(e) {
var range = e.range;
var response = Browser.msgBox('Did you confirm it?', Browser.Buttons.YES_NO);
if ( response == 'yes' ) {
Browser.msgBox('Thank you!', Browser.Buttons.OK);
}
else {
range.clearContent();
}
}
Thank you for your kind answer.
But I found what the problem is.
In the new google spreadsheet function clearContent() doesn't wotk because of 'data validation'!
So I set remove data validation function and clearcontent, finally, set same data validation in active cell.
It works!
Remove data validation.
Clearcontent.
Set data validation.
If anyone has same problem, try it.

Google Script: Issue deleting Specific Sheet in google spreadsheet

Situation:
I have a spreadsheet with 20 sheet.
I have other script that copy sheets from other spreadsheet every days to this spreadsheet-
I need to delete every days some specific sheet from a particular spreadsheet.
Problem:
When the script ends to clear the sheets, the spreadsheet hangs and I have to exit and re-enter to the spreadsheet.
I'll appreciate if anyone can help to tunning this script to work without hangging the spreadsheet.
Script:
function shellDeleteSheets(){
var sheets = ['Sheet1','Sheet2','Sheet3','Sheet4','Sheet5'];
for (var s in sheets){
deleteSheetName(sheets[s]);
}
}
function deleteSheetName(stname) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName(stname);
if(!sh) {
return;
}
ss.setActiveSheet(sh);
ss.deleteActiveSheet();
Utilities.sleep(400);
SpreadsheetApp.flush();
}
Try this version I use without issue
function DeleteSheets(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ['sheet1','sheet2','sheet3'];
var numberOfSheets = ss.getSheets().length;
for(var s = numberOfSheets-1; s>0 ; s--){ // in my case I never delete the first sheet
SpreadsheetApp.setActiveSheet(ss.getSheets()[s]);
var shName = SpreadsheetApp.getActiveSheet().getName();
if(sheets.indexOf(shName)>-1){
var delSheet = ss.deleteActiveSheet();
Utilities.sleep(500);
}
}
SpreadsheetApp.setActiveSheet(ss.getSheets()[0]);// send me back to first sheet
}
You could of course use the array of names as an argument for the function or - that's what I do in some cases - give the names of the sheet I need to keep, in this case the if condition is just different .
the sleep can be 400 mS, not sure it makes any difference, I use 500 because at some time I found it more reliable... and I (try to) never change a working solution ;-)
EDIT following your comment :
to make active the sheet called 'Updated' just change the last line of the code like this :
SpreadsheetApp.setActiveSheet(ss.getSheetByName('Updated'));
please note also that I moved this line in the original code, outside of the loop, sorry for this small error ^^

spreadsheet script running with trigger and manually

This should be simple but I'm stuck on this script...
It has a function (createnewsheet) that runs manually AND on a time trigger so I had to choose openById() to access the spreadsheet but when I'm looking at the sheet and run the function manually I want to set the newly created sheet active and that's what is causing me trouble.
When I run the function (createnewsheet) from the script editor everything is fine but when I call it from the spreadsheet menu I get this error message : Specified sheet must be part of the spreadsheet because of the last line of code. AFAIK I'm not addressing a sheet outside my spreadsheet... Any idea what I'm doing wrong in this context ?
Here is a simplified code that shows the problem, a shared copy is available here
var ss = SpreadsheetApp.openById('0AnqSFd3iikE3dGVtYk5hWUZVUFNZMzAteE9DOUZwaVE');
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('master')
var logsheet = ss.getSheetByName('logger')
var FUS1=new Date().toString().substr(25,6)+":00";
function onOpen() {
var menuEntries = [ {name: "Manual test", functionName: "createnewsheet"},
];
sheet.addMenu("Utilities",menuEntries);
SpreadsheetApp.setActiveSheet(logsheet);// this is working fine
}
function createnewsheet(){
var sheetName = "Control on "+ Utilities.formatDate(new Date(), FUS1, "MMM-dd-yy")
try{
var newsheet = ss.insertSheet(sheetName,2);// creates the new sheet in 3rd position
}catch(error){
FUS1=new Date().toString().substr(25,6)+":00";
var newsheet = ss.insertSheet(sheetName+' - '+Utilities.formatDate(new Date(), FUS1, "HH:mm:ss"),2);// creates the new sheet with a different name if already there
}
newsheet.getRange(1,1).setValue(sheetName);
SpreadsheetApp.setActiveSheet(ss.getSheets()[2]);// should make 3 rd sheet active but works only when run from script editor
// SpreadsheetApp.setActiveSheet(newsheet);// should have same result but works only when run from script editor
}
I found a practical workaround to solve my use case : I use a different function from the menu (in wich I setActive() the sheet I want) and call the main function from this one.
When called from the trigger there is no use to set any active sheet so I removed this part from the main function.
It goes like this :
function manualTest(){ // from the ss menu
createnewsheet();
var sheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(sheet.getSheets()[2]);// this works from the menu when ss is open
}
function createnewsheet(){ // from the trigger and from function manualTest()
var sheetName = "Control on "+ Utilities.formatDate(new Date(), FUS1, "MMM-dd-yy");
try{
var newsheet = ss.insertSheet(sheetName,2);
}catch(error){
FUS1=new Date().toString().substr(25,6)+":00";
var newsheet = ss.insertSheet(sheetName+' - '+Utilities.formatDate(new Date(), FUS1, "HH:mm:ss"),2);
}
newsheet.getRange(1,1).setValue(sheetName);
}
There is a catch here
SpreadsheetApp.setActiveSheet(ss.getSheets()[2]);
When you run it from script editor, It automatically gets the container spreadsheet and makes the said sheet active, but it is not the case when you run it from Custom Menu or triggers.
Modify this statement to:
ss.setActiveSheet(ss.getSheets()[2]);
ss.setActiveSheet(newsheet);
The best solution i have found is to reseed sheet. getActiveSpreadsheet() recognises the Spreadsheet currently in use so no need to openById once more, but
// SpreadsheetApp.setActiveSheet(ss.getSheets()[2]);
// SpreadsheetApp.setActiveSheet(newsheet);
sheet = SpreadsheetApp.getActiveSpreadsheet(); // reloads the active sheet (including changes to the Sheets array)
sheet.setActiveSheet(sheet.getSheets()[2]); // works as expected from editor and custom menu
I think this suggests that the original ss and sheet have cached the Spreadsheet to memory and their pointer isn't refreshed to reflect structural changes. I tried .flush() as a shortcut, but that seems a one way refresh to the sheet from the script, not the other way around.