Google Script: Issue deleting Specific Sheet in google spreadsheet - google-apps-script

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 ^^

Related

Trigger when change is happening in specific sheet

I have a sheet with data that is imported through IMPORTRANGE to another sheet. When I make changes to Spreadsheet 1 >>> Spreadsheet 2 I have a script that copy the data from Copy to Paste. It is working all fine however I want to make sure that the script only runs when changes are made in the 'Copy' sheet and not any other. At the moment it runs independent on what sheet I make changes in.
Spreadsheet 1
Spreadsheet2
I tried onChange trigger two different ways...
This one makes the change but triggers when changes are made in any of the sheets
function Trigger2(e) {
var sheet = e.source.getActiveSheet();
if (sheet.getName() === 'Copy') {
copyInfo();
}
}
AND
(this does not work)
function Trigger2(e) {
var sheet = e.source.getActiveSheet();
var sheet = SpreadsheetApp.getActiveSpreadsheet();
if( sheet.getActiveSheet().getName() !== "Copy" ) return;{
copyInfo();
}}
The copy code looks like this...
function copyInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Copy");
var pasteSheet = ss.getSheetByName("Paste");
// get source range
var source = copySheet.getRange(2,1,12,8);
// get destination range
var destination = pasteSheet.getRange(2,1,12,8);
// copy values to destination range
source.copyTo(destination);
}
Copy Changes from one Sheet To Another after Imported Range Changes
Spreadsheet 2 Imports a range to Sheet1 from Spreadsheet 1 Sheet1 and when a change occurs in Spreadsheet 2 Sheet1 we copy data from Spreadsheet2 Sheet1 to Spreadsheet2 Sheet 2.
function onMyChange(e) {
//Logger.log(JSON.stringify(e));//useful during setup
//e.source.toast("Entry");//useful during setup
const sh = e.source.getSheetByName("Sheet1")
Logger.log(sh.getName());
if(e.changeType == "OTHER") {
let tsh = e.source.getSheetByName("Sheet2");
sh.getRange(2,1,12,8).copyTo(tsh.getRange(2,1));//Only need the upper left hand corner of the range. Thus you change change the size of the source data without having to change the target range.
}
}
One might be inclined to attempt to use e.source.getActiveSheet() unfortunately this does not necessary get the sheet that you have written unless in is SpreadsheetApp.getActive().getSheets()[0]. onChange event object always returns the most left sheet in the spreadsheet in this situation so it can't be used to identify the sheet that is being written to from the importRange function.
With this function you no longer require another function.
A simple if should work, but you're trying to compare the name to the wrong field. According to Google's documentation, the source field in the Event Object e returns the Spreadsheet object, which is the entire document.
Instead you can use the e.range field, which contains the exact range where the edit was made, and the Range class has a getSheet() method to get the parent Sheet.
So you can modify your sample to the following:
function Trigger2(e) {
var sheet = e.range.getSheet();
if (sheet.getName() === 'Copy') {//Edit: this will only work if sheet is the most left sheet in the spreadsheet
copyInfo();
}
}

Google apps script for sheets, how to create a 2-way link between two spreadsheets?

I'm attempting to write a script to continuously update two spreadsheets so that the information put in one always goes into the other.
The full project is to create a master spreadsheet with 50 people on it and each one of them has their own sheet/page, however they aren't allowed to access this master sheet as they are not allowed to see the other peoples data. (I am currently unaware of any viewing permission commands but I'm pretty sure there aren't any).
So the solution that I have been considering is creating 50 other spreadsheets and each of them will have a single sheet with all of the same information as the master Spreadsheet and the name of the sheet will be the same as on the master page.
I found this code on another post that was for a similar problem
function onEdit(e) {
// Get the event object properties
var range = e.range;
var value = e.value;
//Get the cell position
var row = range.getRowIndex();
var column = range.getColumnIndex();
exportValue(row,column,value)
}
function exportValue(row,column,value) {
var ss = SpreadsheetApp.openById(targetID);
var s = ss.getSheetByName(targetSheetName);
var target = s.getRange(row, column);
target.setValue(value);
}
in this I understand what everything is doing except the ("var range = e.range; var value = e.value;") lines, is ths what im looking for or not, idk
Thanks in advance
:)

Google Sheets Auto Copy, Paste, Delete

Does anyone know a script that would let me copy data from cells A3:E1000 on Sheet1 and paste it to Sheet2. After pasting I need it to delete the exact data that it copied from Sheet1 (Sheet2 will still have copied data) and I need it to do this everyday at 11:30pm. I need Sheet2 to be able to keep taking the data forever as a digital archive of the data that is being copied daily from Sheet1. I hope this makes sense. I can't figure it out. When I run this it works if I run dailyLog and then run clearRange separately. When I run autoArchive it deletes the data from Info sheet but doesn't paste it into the Archive sheet.
function autoArchive(){
dailyLog();
clearRange();
}
function dailyLog() {
var ss = SpreadsheetApp.openById("SheetID").getSheetByName("Info");
var sourceSheet = ss.getSheetByName('Info');
var logSheet = ss.getSheetByName('Archive');
var lastRow = logSheet.getLastRow();
var range = sourceSheet.getDataRange();
range.copyTo(logSheet.getRange(lastRow + 2, 1), {contentsOnly: false});
}
function clearRange() {
var sheetActive =
SpreadsheetApp.openById("SheetID").getSheetByName("Info");
var start, end;
start = 2;
end = sheetActive.getLastRow() - 1;
sheetActive.deleteRows(start, end);
}
have a look at the record macro function it will generate Google Apps Script for you. Just records the steps you take and give it a name so you only need to click the macro in the menu or use a shortcut.
#Cooper the current limit for a spreadsheet is 5.000.000 cells. Doesn't matter if it is in one sheet or all sheets together. However this might be increased in the nearby future.
Use SpreadsheetApp.flush(); to force Google Apps Script to apply the changes made so far.
Example:
function autoArchive(){
dailyLog();
SpreadsheetApp.flush();
clearRange();
}

On Google Form Submit clear cells of active row in Google Sheets

I'm quite new to google sheet script and looking for some assistance. I am trying to make a google script that will erase cells in a response sheet after a user has submitted it. As this could be a form edit url, it may not necessarily be the last row.
So everytime a form is submitted / edited, columns AN:AQ are cleared.
Any help greatly appreciated
I'm adding the working script to OP's question for anyone who comes across this.
function onFormSubmit11(e) {
var range = e.range;
var ss = range.getSheet();
var row = range.getRowIndex();
ss.getRange("AN"+row).clear();
ss.getRange("AO"+row).clear();
ss.getRange("AP"+row).clear()
ss.getRange("AQ"+row).clear()
}
The Spreadsheet trigger invoked by the Google Form contains the Range object. You can retrieve the sheet linked to the range as well the index of the row linked to the current form submission.
function formTrigger(e) {
var range = e.range;
var sheet = range.getSheet();
var rowIndex = row.getRowIndex();
sheet.getRange(rowIndex + 1, 1).setValue("Hello");
}
You could try something as simple as an onFormSubmit running the script through your linked spreadsheet. The script below will clear AN:AQ every time a form is submitted which is 'alf of what I think you're asking for.
As for on edit, that's something I'm trying to figure out myself in my own question!
function onFormSubmit() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sh = ss.getActiveSheet()
sh.getRange('AN1:AQ').clear();
}
Hi Again,
Try this below. As before, make sure your trigger is set on OnFormSubmit and it should work flawlessly. I've tested it myself, it only cleared the range between AN:AQ on row (wherever the form edits). If you want to delete different sections just replace the AN:AQ for whatever column(s) you wish to clear.
function onFormSubmit(e) {
var range = e.range;
var ss = range.getSheet();
var row = range.getRowIndex();
ss.getRange("AN:AQ"+row).clear();
}

Divide a spreadsheet in two or more spreadsheets?

How to divide a google spreadsheet (with about 100 sheets) in two (or more) spreadsheets (of about 50 sheets each) in google-apps-script ?
Alas, due to a google bug (see https://productforums.google.com/d/topic/docs/H2ZakBguOgk/discussion), I can't copy the entire spreadsheet file and delete some sheets in each spreadsheets.
I can only copy sheets one by one on another spreadsheet, then delete the original sheet(s) if copy is a success.
Thanks in advance ;)
Here is a code snippet that should do what you want, I didn't test it so maybe you'll have to tweak some details but the general idea is there...
EDIT : I tested and made the corrections to make it work... sorry for the typos in first version
function splitSS() {
var oldFileID = 'original ss Id'
var newFile = DocsList.getFileById(oldFileID).makeCopy()
var newFileID = newFile.getId()
var ss = SpreadsheetApp.openById(newFileID);
Logger.log(ss.getNumSheets())
var todel = parseInt((ss.getNumSheets())/2);
Logger.log(todel)
var tokeep = ss.getNumSheets()-todel
Logger.log(tokeep)
for (pa=ss.getNumSheets()-1;pa>tokeep;--pa){
ss.setActiveSheet(ss.getSheets()[pa]);
var delsheet = ss.deleteActiveSheet(); // delete sheets begining with the last one
Utilities.sleep(400);
}
var ssold = SpreadsheetApp.openById(oldFileID);
for (pa=todel;pa>1;--pa){
ssold.setActiveSheet(ssold.getSheets()[pa]);
var delsheet = ssold.deleteActiveSheet(); // delete sheets begining with the last one
Utilities.sleep(400);
}
}