I have a standalone script that I need to run on Multiple Google Spreadsheets. I am able to assign a script to 1 spreadsheet using the following code:
function filter() {
var ss = SpreadsheetApp.openById('ID');
How to assign this to multiple spreadsheets?
There are more than a single way to do it.
1) You can manually get the id's of the various spreadsheets and hard code the id's as an array in the stand alone script.
2) You can move all the spreadsheets required to a single folder and automate opening the folder and opening the files in the particular folder. For this, say, the folder containing the required spreadsheets is "All spreadsheets", then try out the following code.
function myfunction()
{
var root = DriveApp.getFoldersByName("All spreadsheets");
while (root.hasNext())
{
var folder = root.next(); //If the folder is available, get files in the folder
var files = folder.getFiles();
while(files.hasNext()) //For each file,
{
var spreadsheet = SpreadsheetApp.open(files.next());
required_function(spreadsheet); //Call the required function
}
}
}
Hope it helps :)
Related
I would like some help checking how many files are inside a Google Drive folder before allowing a form submission.
I have this form here:
I would like that when the Submit button is clicked, a function checks how many files exist in a child folder of the folder where this GAS file is.
The HTML form GAS is linked to this worksheet here:
After checking how many files there are in the _ folder I would like to apply the following if/else statements:
If the _ folder has more than 3 files, display a confirmation pop-up, if the answer is Yes, create any file in the _ folder, if the answer is No, just don't allow the form submission.
If the _ folder contains 4 or more files, display an error message and disallow form submission.
The code of this HTML form can be seen here, accessing the spreadsheet's GAS:
HTML Form - Demonstration
Partial Solution:
I made some changes on the getLimitFolder() function to return the count of the files inside the _ folder.
function getLimitFolder(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pastapai = DriveApp.getFileById(ss.getId()).getParents();
var files = [];
Logger.log(pastapai);
//var limitfolder = pastapai.next().getFoldersByName("_").next().getId();
var limitfolder = pastapai.next().getFoldersByName("_").next().getFiles();
while(limitfolder.hasNext()){
var file = limitfolder.next();
files.push([file.getId()]);
}
console.log(files.length);
return files.length;
}
Inside the folder _:
From here, since the function can now return the count of files within the _ folder, you may need to create a new modal window on your HTML file to display the message first and create a separate function to determine the conditions for your if else statement.
I am writing an automator workflow to work with files and folders. I’m writing it in JavaScript as I’m more familiar with it.
I would like to receive a folder, and get the folder’s name as well as the files inside.
Here is roughly what I have tried:
Window receives current folders in Finder (I’m only interested in the first and only folder)
Get Folder Contents
JavaScript:
function run(input,parameters) {
var files = [];
for(let file of input) files.push(file.toString().replace(/.*\//,''));
// etc
}
This works, but I don’t have the folder name. Using this, I get the full path name of each file, which is why I run it through the replace() method.
If I omit step 2 above, I get the folder, but I don’t know how to access the contents of the folder.
I can fake the folder by getting the first file and stripping off the file name, but I wonder whether there is a more direct approach to getting both the folder and its contents.
I’ve got it working. In case anybody has a similar question:
// Window receives current folders in Finder
var app = Application.currentApplication()
app.includeStandardAdditions = true
function run(input, parameters) {
let directory = input.toString();
var directoryItems = app.listFolder(directory, { invisibles: false })
var files = [];
for(let file of directoryItems) files.push(file.toString().replace(/.*\//,'')) ;
// etc
}
I don’t include the Get Folder Contents step, but iterate through the folder using app.listFolder() instead. The replace() method is to trim off everything up to the last slash, giving the file’s base name.
I wrote the google-script. In that script I have a function that I need to use in 250+ different tables (google-sheets). Question is - How can I make it function accessible in each table?
To make a script or custom function available across other Google Sheets, publish it as a library.
Bruce Mcpherson has a nice post on how to do this: http://ramblings.mcpher.com/Home/excelquirks/gooscript/lib
Yes, it is possible.
Two options:
Create a Apps Script project that calls the 250+ spreadsheet, makes the operations and updates each spreadsheet which the results.
On this you'll find a collection of tutorials to start with apps script.
https://developers.google.com/apps-script/articles/tutorials
Create a function that you can call from any cell of your spreadsheet just as you call any other default function like SUM()
On this documentation you'll find explained how to do this second option.
https://developers.google.com/apps-script/guides/sheets/functions#arguments
Ok, I fond the solution. In my case files that I need to change is placed in deferent folders and have similar name
// function that i need to execute
function updatePrices(sheetId){
// do some staff
var activeSpreadsheet = SpreadsheetApp.openById(sheetId);
var histPricesSheet = activeSpreadsheet.getSheetByName(someSheetName);
....
var cell = histPricesSheet.getRange(range);
cell.setValues(someData);
}
function walkFolders(folderId){
// function that walk by folders and get ids of spradsheeds
and call func that I need in each spradsheed that I need
var fin_fold = DriveApp.getFolderById(folderId);
var folders = fin_fold.getFolders();
while (folders.hasNext()) {
var folder = folders.next();
var files = folder.searchFiles('title contains "карточка"');
while (files.hasNext()){
var file = files.next();
updatePrices(file.getId()); // call my function to every spreadsheet
Logger.log("обновлено");
}
}
}
walkFolders("folder ID wich contain folders with files to change");
I have a Google Sheets file with an attached Script. The script does a number of things, one is it makes a clone of it self using makeCopy. This portion works. Now I want to be able to keep the same cloned Google file name and same Google file ID and just update the content which includes a Spreadsheet and the associated Google script.
if (!fileFound){
var file = masterSSFile.makeCopy(reportFileName, RepFolder);
} else {
oldFile.setContent(masterSSFile.getBlob());
}
When I use makeCopy with the same file name it creates a second file with the same name but with a different file ID.
The else portion fails because .setContent argument seems to just accept text. The result is the word "Blob" in the oldFile, everything else is gone.
I have other scripts that update the contents of a existing spreadsheet by overriding the contents of the various sheets, but I also want the associated script to also be included in the updated file keeping the same file ID.
I found this....
Overwrite an Image File with Google Apps Script
and tried using
var masterSpreadsheetID = SpreadsheetApp.getActiveSpreadsheet().getId();
var masterSpreadsheetFile = DriveApp.getFileById(masterSpreadsheetID);
var oldFileID = oldFile.getId();
var oldFileName = oldFile.getName();
var newBlob = masterSpreadsheetFile.getBlob();
var file = {
title: oldFileName,
mimeType: 'application/vnd.google-apps.spreadsheet'
};
var f = Drive.Files.update(file, oldFileID, newBlob);
I get error: "We're sorry, a server error occurred. Please wait a bit and try again. " on this line: "Drive.Files.update(file, oldFileID, newBlob);"
After reading this:
https://github.com/google/google-api-nodejs-client/issues/495
it looks like Drive.Files.update(), does not support bound scripts.
In my script I am trying to create a folder, create a date-stamped-document in said folder, create a sub folder, and copy some documents into that sub folder.
All of this works great. When I try to zip the parent folder via either of the methods found here: Creating a zip file inside google drive with apps script - it creates a zip file with a sole PDF file that has the same name as the date-stamped-document. The zipped PDF is blank, and the subfolder isn't there.
Any insight about why this is happening would be great.
var folder = DocsList.createFolder(folderTitle);
var subFolder = folder.createFolder('Attachments');
subfolder.createFile(attachments[]); //In a loop that creates a file from every
//attachment from messages in thread
var doc = DocumentApp.create(docTitle); //Google Doc
var docLocation = DocsList.getFileById(doc.getId());
docLocation.addToFolder(folder);
docLocation.removeFromFolder(DocsList.getRootFolder());
//Everything works fine, I can view file and subfolder, and subfolder's documents
//This is where the problem is:
var zippedFolder = DocsList.getFolder(folder.getName());
zippedFolder.createFile(Utilities.zip(zippedFolder.getFiles(), 'newFiles.zip'));
//this results in a zipped folder containing one blank pdf that has the same title as doc
The DocsList service has been deprecated so Phil Bozak's previous solution no longer works. However, refer to another SO question for solution that works with DriveApp class.
This is a great question. It does not seem that the zip function has the ability to zip sub folders. The reason that your script doesn't work is because you only select the files from the folder.
A solution would be to zip each of the subfolders and store that in the one zipped file. You can use the function that I wrote for this.
function zipFolder(folder) {
var zipped_folders = [];
var folders = folder.getFolders();
for(var i in folders)
zipped_folders.push(zipFolder(folders[i]));
return Utilities.zip(folder.getFiles().concat(zipped_folders),folder.getName()+".zip");
}
This recursively zips all subfolders. Then you need to create the file with something like
DocsList.getFolder("path/to/folder/to/store/zip/file").createFile(zipFolder(folderToZip));
I will put in a feature request to allow subfolders to be zipped.