Copy one sheet to many others spreadsheets at the same folder - google-apps-script

I have many spreadsheets inside a folder and today I have developed a new sheet (tab) inside one of these spreadsheets. I have a code to copy and paste one sheet to another spreadsheet, but for this there is another way without code.
My goal is:
a way to copy one sheet (order number 13) to all other spreadsheets at the same folder.
This is my code for copying one-to-one:
function sendspreadsheet(){
var source = SpreadsheetApp.getActiveSpreadsheet();
var aba = source.getSheets()[13];
var destination = SpreadsheetApp.openByUrl('https:sheetID');
aba.copyTo(destination);}
I have a great help from #Tanaike about similar issue at post: "Array for Google Sheet celarcontet" and I have studied this code and Google Class Sheet, but something is not working.
Code I'm trying to copy one-to-multiple spreadsheets at the same folder:
Function sendtomultiple(){
var source = SpreadsheetApp.getActiveSpreadsheet();
var aba = source.getSheets()[13];
var destination = DriveApp.getFolderById('1o6p-53Q1ntJAVIJt9w4k0UK___XXXXXX');
var sheetDestino = destination.getFilesByType(MimeType.GOOGLE_SHEETS);
while (sheetDestino.hasNext()) {
SpreadsheetApp.open(sheetDestino.next()).getSheets().forEach(aba => {
aba.copyTo(sheetDestino);
});
};
}
I guess this line into while instruction is the problem, I have tried other options, but all them return error message, kind this:
Exception: The parameters (DriveApp.FileIterator) don't match the method signature for SpreadsheetApp.Sheet.copyTo.
Hope someone can help to fix this.

Explanation / Issue:
Your goal is to copy a particular sheet (tab) into multiple spreadsheets within the same folder.
The issue has do to with the fact that sheetDestino.next() is a file object but copyTo(spreadsheet) accepts a spreadsheet object.
You can get the id of the file and then use openById(id) to get the spreadsheet object which you can use to copy the sheet to.
Bonus code:
I added an if condition to make sure the code does not try to copy the sheet to the origin spreadsheet file.
I added a code to rename the copied sheet to the destination sheet to the original name. The default would be copy of Sheet14...
Solution:
function sendtomultiple(){
const source = SpreadsheetApp.getActiveSpreadsheet();
const source_id = source.getId();
const aba = source.getSheets()[13];
const destination = DriveApp.getFolderById('1o6p-53Q1ntJAVIJt9w4k0UK___XXXXXX');
const sheetDestino = destination.getFilesByType(MimeType.GOOGLE_SHEETS);
while (sheetDestino.hasNext()) {
let target_file = sheetDestino.next();
let target_id = target_file.getId();
let target_ss = SpreadsheetApp.openById(target_id);
if(target_id!=source_id){
aba.copyTo(target_ss).setName(aba.getName());
}
};
}
Keep in mind that sheet getSheets()[13] is the 14th sheet in the spreadsheet file. If you want to get the 13th sheet you need to use getSheets()[12].

Related

Google Sheet - Reference a folder that is inside the worksheet folder

I am a beginner in creating Scripts in Google Sheets, so I would like some help to reference a folder that is inside the spreadsheet folder.
I would like to create a script that checks if there are more than 3 files in a given folder, if so, I would like it to return an error on the screen.
Important point: the files that need to be checked will always be in a folder that is inside the spreadsheet folder, so I would need to reference this, in the CMD it would be something like .\FolderWithFiles.
In this case, I cannot use the ID a of the folder which I want to be checked, because this is a model worksheet that will be duplicated several times.
Any idea how I can do this?
I believe your goal is as follows.
You want to check the number of files in the folder including the active Spreadsheet you are using.
When the number of files is more than 3, you want to show an error.
In this case, how about the following sample script?
Sample script:
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet(); // This is your active Spreadsheet.
const parentFolder = DriveApp.getFileById(ss.getId()).getParents();
if (parentFolder.hasNext()) {
const files = parentFolder.next().getFiles();
let count = 0;
while (files.hasNext()) {
const file = files.next();
// console.log(file.getName()); // When you use this line, you can see the filename of the files.
count++;
}
if (count >= 3) {
throw new Error("Your expected error.");
}
} else {
throw new Error("Spreadsheet has no parent folder.");
}
}
When this script is run, the number of files in the folder including the active Spreadsheet is checked. When the number of files is more than 3, an error like Your expected error. occurs.
If you want to use another Spreadsheet instead of the active Spreadsheet, please modify const ss = SpreadsheetApp.getActiveSpreadsheet(); to const ss = SpreadsheetApp.openById("###spreadsheetId###");.
Reference:
getParents()

Google App Script - save to Folder from another Person

I would like to save Documents into a open folder in Google Drive from another person.
I tried the following code but it doesnt work if i´m not the owner of the code.
function saveToFolder() {
var folder = DriveApp.getFolderById("###");
//var destSpreasheet = SpreadsheetApp.open(DriveApp.getFolderById(SpreadsheetApp.getActiveSpreadsheet().getId()).moveTo(folder))
//var ss = SpreadsheetApp.getActiveSpreadsheet().
//get active Sheet
var sSpreadsheet = SpreadsheetApp.getActive;
var sheetname = sSpreadsheet().getActiveSheet().getName();
var sSheet = sSpreadsheet().getSheetByName(sheetname);
//var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sSpreadsheet().getId()).makeCopy("test",folder))
var destSpreadsheet = DriveApp.getFileById(sSpreadsheet().getId()).makeCopy(SpreadsheetApp.getActiveSpreadsheet().getName(), folder)
}
The goal is that a lot of people can safe there google sheets to the same folder in google drive by using a button.
Thanks a lot for your help
You have some typos in your code like getActive() and using sSpreadsheet() instead of sSpreadsheet (please refer to the documentation linked). Here is your "fixed code" that takes a Spreadsheet and creates a copy of it in a Drive folder (the code has self-explanatory comments):
function myFunction() {
// Get folder by ID
var folder = DriveApp.getFolderById("FOLDER ID");
// Get active Spreadsheet (if this script is not bounded use openById or openByUrl)
var sSpreadsheet = SpreadsheetApp.getActive();
// Make copy
DriveApp.getFileById(sSpreadsheet.getId()).makeCopy(SpreadsheetApp.getActive().getName(), folder)
}
Also bare in mind that in order to use DriveApp you must first enable the Drive API service.

How to "Copy to Sheet" only if file exists

So here is my problem, I have a script for copying a bunch of independent one sheet google spreadsheets into one master spreadsheet as tabs, but because I'm using "title contains" it creates sheets (tabs) for non existent spreadsheets (in the example below: it will make "ADC Lunch" even though that sheet doesn't exist). I have about 50 of these in a script, what is the best way to ensure that only the sheets that have actual spreadsheet files correspondent to their name exist in my master spreadsheet? I was thinking maybe a "if then" like IF(ID=true, sheet.copyTo(destination).setName("ADC Breakfast")) but I don't have much experience in api script yet so I don't know how to formulate it around this function. Any help would be appreciated, thank you.
Illustration:
"Spreadsheet 1"
"Spreadsheet 2" --> compiled --> Master Spreadsheet (with 3 sheets)
"Spreadsheet 3"
Problem:
Master Spreadsheet searches for Spreadsheet X by "title contains" search, if it doesn't find one of the spreadsheets with the specific requirements, it just copies another spreadsheet that is close enough into the master spreadsheet as Spreadsheet X. How can I make it so it will only copy a spreadsheet to the master spreadsheet (as a tab) if it actually exists and fulfills the "title contains" parameters? I hope this clarifies things, sorry for my poor description.
function ArrayBuilder() {
var filesource = DriveApp.searchFiles('title contains "ADC Breakfast" and parents in "File_ID"');
while(filesource.hasNext()){
var File = filesource.next();
var ID = File.getId();
}
var name = File.getName()
var source = SpreadsheetApp.openById(ID);
var sheet = source.getSheets()[0];
var destinationID = "File_ID";
var destination = SpreadsheetApp.openById(destinationID);
sheet.copyTo(destination).setName("ADC Breakfast");
Finding Spreadsheets that have only one sheet
I know this isn't the answer to your question but perhaps it will help you think about it another way. This function finds Spreadsheets that only have 1 sheet and it appends the file name, file id and sheet name to a spreadsheet. It also adds an extension to the file name like (n) where n is an integer indicating how many files have had that name. With the information in the spreadsheet you could probably figure out which ones you would like to copy into your master spreadsheet or if you wish assistance in modifying it please let me know.
function findSpreadsheetsWithOnlyOneSheet() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('File Data Sheet');
var nA=[];
var nObj={};
var files=DriveApp.getFolderById('Folder Id').getFilesByType(MimeType.GOOGLE_SHEETS);
while(files.hasNext()) {
var file=files.next();
var id=file.getId();
var name=file.getName();
if(Sheets.Spreadsheets.get(id).sheets.length==1) {
var sheetname=Sheets.Spreadsheets.get(file.getId()).sheets[0].properties.title;
if(nA) {
if(nA.indexOf(name)==-1) {
nA.push(name);
sh.appendRow([name,id,sheetname]);
}else{
if(nObj.hasOwnProperty(name)) {
nObj[name]+=1;
}else{
nObj[name]=1;
}
sh.appendRow([name + '(' + nObj[name] + ')',id,sheetname])
}
}else{
sh.appendRow([name,id,sheetname]);
}
}
}
}
This is what my spreadsheet looks like:
Sheets API version 4
DriveApp Class

Copy a range in active sheet, create new spreadsheet with custom name, paste range

I recently wrote my first Google Apps script that makes a copy of a spreadsheet (including all tabs within that spreadsheet) and places it into a specific folder in the user's Drive. The copy is renamed based on a cell value in the original spreadsheet. Here is my script, for reference:
function copyDocument() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // Get current active spreadsheet.
var id = ss.getId(); // Get current active spreadsheet ID.
var sstocopy = DriveApp.getFileById(id); // Get spreadsheet with DriveApp.
var sheet = ss.getActiveSheet(); // Get current active sheet.
var sheet_name = sheet.getRange("B1").getValue(); // Get the value of cell B1, used to name the new spreadsheet.
var folder_name = sheet.getRange("C23").getValue(); // Get the target folder ID.
var folder = DriveApp.getFolderById(folder_name); // Get the ID of the folder where you will place a copy of the spreadsheet.
sstocopy.makeCopy(sheet_name,folder); // Make a copy of the spreadsheet in the destination folder.
}
This script works, but I have been asked to modify it because the script I wrote is copying over unnecessary tabs and data that is causing confusion to users.
The new script should make a copy of a specific range in a specific sheet, create a new spreadsheet, and paste that range into it. It should also name itself after a cell value in the range.
However, the only method I have come across that specifically copies a sheet into a new spreadsheet is copyTo(spreadsheet). However, the Google Apps Script Guide specifies that "the copied sheet will be named 'Copy of [original name]'" by default.
I want to be able to rename the copied sheet after a specific cell. My question is, can I use copyTo(spreadsheet) and give the new spreadsheet a custom name, based on a cell?
Thanks!
You will need to get the data from the specific sheet to copy out to a variable of using:
var sourceSheet = ss.getSheetByName("Sheet1");
var sourceData = sourceSheet.getDataRange().getValues();
var originalRangeNotation = sourceSheet.getDataRange().getA1Notation();
Then you need to create a new, empty file and make a sheet with the same name
var ssNew = SpreadsheetApp.create("My New File Name");
ssNew.insertSheet('My New Sheet');
Then add the contents from the saved data to the new file. Since the insertSheet makes the new sheet the active one, we use:
var sheetNew = ssNew.getActiveSheet();
var rangeNew = sheet.getRange(originalRangeNotation);
range.setValues(sourceData);
Thanks. I ended up using this in place of sstocopy.makeCopy()
folder.addFile()
new_sheet.getActiveSheet().getRange("X:Y").setValues(sheet.getRange("X:Y").getValues())
DriveApp.getRootFolder().removeFile(temp)

Create a copy of a Google Sheet with Google Apps Script

I am new in google apps script. I need help for creating new spreadsheet by using existing spreadsheet and copy and sort the data into newly created spreadsheet using google apps script. Can anyone help me?
this does the trick:
function copySpreadSheet(newSpreadSheetName) {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var data = sheet.getSheetValues(1, 1, 1000, 26);
var newSheet = SpreadsheetApp.create(newSpreadSheetName)
newSheet.getSheetByName("Sheet1")
.getRange(1,1,1000,26).setValues(data);
}
function main() {
copySpreadSheet("some_Spreadsheet");
}
After executing main, you can find the new spreadsheet in your drive file list. If you want to change the range of the data that should be copied, adjust the getSheetValues() method like this: getSheetValues(startRow, startColumn, numRows, numColumns). Don't forget to do the same for the getRange method a few lines below, otherwise you will get an error.
You can use this simpler code:
function copySpreadSheet() {
var s = SpreadsheetApp.openById("id");
var destination = DriveApp.getFolderById("idOfFolder");
DriveApp.getFileById("id_ofFile").makeCopy("New name", destination);
}
This will create a copy of your file in a new destination.
The SpreadsheetApp#spreadsheet class has a method copy:
var wb = SpreadsheetApp.getActiveSpreadsheet();
var new = wb.copy("Copy of " + wb.getName());
This copy method copies the current spreadsheet and returns a reference to the new one, so additional tasks (such as removing unneeded sheets, formatting ranges, adding additional values, etc.) can be performed.