Google Apps Script : Making an A Function Execute on Open - google-apps-script

I found a script that will move my spreadsheet to a folder. How can I make it so that the functions runs when the spreadsheet is open. I will be applying this to a template so that everytime the template is opened, the "Copy of " spreadsheet file will automatically be moved to my Packing Lists folder.
Here's the code I have....
function MoveFileTo()
{
var docs=DocsList.find('Save Test');
var doc=docs[0]; /*Since we assume there is only one file with the name "Hello World", we take the index 0 */
var folders = doc.getParents();
var newFolder=DocsList.getFolder('Packing Lists');
doc.addToFolder(newFolder); // This will add the document to its new location.
var docParentFolder=folders[0];
doc.removeFromFolder(docParentFolder); // This will remove the document from its original location.
}
EDIT: I tried changing function MoveFileTo to onOpen() and onEdit() but it doesn't seem to work properly. Is there something I am missing?

Try use driveapp instead of doclist (it's deprecated). the impinball comment is really usefull, you should have a look at it.
Anyway here a working code:
function myFunction() {
var destFolder = DriveApp.getFolderById("FOLDER_ID_WHERE8YOU_WANT_TO_MOVE_YOUR_FILES");
var fileList = DriveApp.searchFiles("mimeType = 'application/vnd.google-apps.spreadsheet' and title contains 'FILE_TITLE'"); // change this search if necessary
var originalFileId="THE_ID_OF_THE_ACTUAL_SPREADSHEET_TO_BE_EXCLUDED_FROM_THE_SCRIPT_TREATMENT";
while(fileList.hasNext()){
var fileToMove = fileList.next();
if(fileToMove.getId()==originalFileId){
continue; // don't do anything if it's the original file
}
var papas = fileToMove.getParents();
destFolder.addFile(fileToMove); // do the job
while(papas.hasNext()){
papas.next().removeFile(fileToMove); // remove the actuals parents (can be more than one)
}
}
}

Related

Save a Single Sheet in Google Sheets as PDF using Script

I would like to be able to save just the active sheet as a pdf when clicking the save pdf button. Currently my code saves all of the sheets. How should I edit this code?
function onOpen() {
var submenu = [{name:"Save PDF", functionName:"saveAsPDF"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Save as PDF', submenu);
}
function saveAsPDF() {
const folderName = `social`;
const fileNamePrefix = SpreadsheetApp.getActiveSheet().getRange('a1').getValue();
const PhasePrefix = SpreadsheetApp.getActiveSheet().getRange('a2').getValue();
var actualSheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
DriveApp.getFoldersByName(folderName)
.next()
.createFile(SpreadsheetApp.getActiveSpreadsheet()
.getBlob()
.getAs(`application/pdf`)
.setName(`${fileNamePrefix} - ${PhasePrefix} - ${Utilities.formatDate(new Date(), `GMT-8`, `yyyy-MM-dd`)}`));
var ui = SpreadsheetApp.getUi()
ui.alert('New PDF file created in ' + folderName )
}
first, be careful as the save as pdf option is going away in December. I'm not sure if this will affect the script function, but you'll get a warning when trying it manually. worth checking out...
(not tested)
save as pdf goes to the folder and saves the file. if you're already in the file, you just want to save one sheet, you probably don't need to go and grab the whole file.
I was going to write this up, but I think this link will do what you want best.
https://xfanatical.com/blog/print-google-sheet-as-pdf-using-apps-script/
Scroll down to the Source Code section.
You're looking for this function 'exportCurrentSheetAsPDF'
function exportCurrentSheetAsPDF() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var currentSheet = SpreadsheetApp.getActiveSheet()
var blob = _getAsBlob(spreadsheet.getUrl(), currentSheet)
_exportBlob(blob, currentSheet.getName(), spreadsheet)
}
This has the simple excerpt. I do encourage you to go to give them clicks and there's lots of other good stuff there. I think that is probably more than you wanted, but maybe things you didn't know you wanted...

Where would I put the file search contains certain words

I have this and I ran the debug and it did not give me any errors. Where can I put the search function for files with certain words? Any help will be greatly appreciated.
This was one I was trying to use
var filesIterator = folder.searchFiles('title contains "Untitled"');
function MoveFiles() {
var SourceFolder = DriveApp.getFolderById('abcdefghijklmnopqrstuvwxyz');
var SourceFiles = DriveApp.getFolderById('abcdefghijklmnopqrstuvwxyz').getFiles();
var DestFolder = DriveApp.getFolderById('1hbuV93CsdOeHkZWLES8BhXYMrayoKTBr');
while (SourceFiles.hasNext()) {
var file = SourceFiles.next();
DestFolder.addFile(file);
SourceFolder.removeFile(file);
}
}
Find and Move Files
This function will show a prompt where you can enter the string to complete the query 'title contains "the string"'. You also have to provide the id of the folder to search for and the id of the destination folder.
function findAndMoveFiles() {
var SourceFolder = DriveApp.getFolderById('Id');
var DestFolder = DriveApp.getFolderById('Id');
var result = SpreadsheetApp.getUi().prompt('Enter the string to complete the search query');
var qry = Utilities.formatString('title contains "%s"', result.getResponseText());//you just need to enter the string that gets put into %s
var SourceFiles = SourceFolder.searchFiles(qry);
while (SourceFiles.hasNext()) {
var file = SourceFiles.next();
DestFolder.addFile(file);
SourceFolder.removeFile(file);
}
}
Enter the script into a gs file in the script editor. You can run the script from the script editor once it start a dialog prompt will appear on the spreadsheet so make sure to switch back to the spreadsheet at that point.
You can also run it from a menu by entering in the following code:
function onOpen(){
SpreadsheetApp.getUi().createMenu('Search Menu')
.addItem('Find and Move Files', 'findAndMoveFiles')
.addToUi()
}
You will need to save it to the Script Editor and select it and run it one time to get the menu into the spreadsheet. Also it will display in the spreadsheet upon opening the spreadsheet next time.
DriveApp Reference
UI Reference
Also checkout all of the features in the help menu of the Script Editor.

Move Folder Using App Script

So i'm brand new to JS and trying to build a program for internal operation at the company I work for. Below is the first bit of my code. I have a created a google form, and set a trigger so that when the submit button is clicked the below code will start. The trigger works and the first two functions work, but I cannot seem to get the Karrie folder to move from the root to the sub folder id (I do have the correct ID but omitted it from this post). Maybe I'm doing this all backwards so any help would be appreciated.
// Create Karrie Folder In Root
function start() {
var sourceFolder = "Property Template";
var targetFolder = "Karrie";
var source = DriveApp.getFoldersByName(sourceFolder);
var target = DriveApp.createFolder(targetFolder);
if (source.hasNext()) {
copyFolder(source.next(), target);}}
// Adds Property data to Karrie Folder
function copyFolder(source, target) {
var folders = source.getFolders();
var files = source.getFiles();
while(files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), target);}
// Adds Photo Folders to Karrie Folder
while(folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);}}
// Moves Karrie folder to propertie folder
function MoveFiles(){
var files = DriveApp.getFolderByName("Karrie");
var destination = DriveApp.getFolderById("ID NA");
destination.addFolder(files);}
Debugger
I understood that MoveFiles() in your script doesn't work. If my understanding is correct, how about this modification?
Modification points :
In order to move a folder, it required to move the parent of the folder.
But when addFolder() is used to the folder, the folder has 2 parents.
So original parent has to be removed.
There is no getFolderByName(). Please use getFoldersByName().
Modified script :
function MoveFiles(){
var folder = DriveApp.getFoldersByName("Karrie").next();
var destination = DriveApp.getFolderById("ID NA");
destination.addFolder(folder);
folder.getParents().next().removeFolder(folder);
}
Note :
In this script, The folder and parent of "Karrie" supposes only one in the Google Drive, respectively.
References :
getFoldersByName()
addFolder()
removeFolder()
If I misunderstand your question, please tell me. I would like to modify it.
Edit 1 :
When you run this function, does the ID of Logger.log(r) show the folderId of "Karrie"?
function sample() {
var r = DriveApp.getFoldersByName("Karrie").next().getId();
Logger.log(r)
}
Edit 2 :
Please confirm and consider the following points.
Confirm the folder name and the existence of the folder again.
Run sample() and confirm folder ID of "Karrie".
Confirm whether there are no functions with the same name.
Can I ask you the folder ID of "Karrie"? If you cannot retrieve the folder ID using DriveApp.getFoldersByName("Karrie").next().getId(), I propose to use directly the folder ID of "Karrie".
Updated on March 30, 2022:
In the current stage, the files and folders can be moved using moveTo. Ref This method has added on July 27, 2020. When moveTo is used, the above script can be modified as follows.
function MoveFiles(){
var folder = DriveApp.getFoldersByName("Karrie").next();
var destination = DriveApp.getFolderById("ID NA");
folder.moveTo(destination);
}
Reference:
moveTo(destination) of Class Folder
As of 2020, the easier way I found to move a file is to use this function:
function moveToFolder(file, sourceFolder, destFolder) {
var file = DriveApp.getFileById(file.getId());
destFolder.addFile(file);
sourceFolder.removeFile(file);
}
Because of the first line, you can convert your Spreadsheet, Google Form, Document or others Google objects into a File.
Then we just use methods of the Folder class : https://developers.google.com/apps-script/reference/drive/folder
Notes:
If you created your file by using .create() your sourceFolder will be DriveApp.getRootFolder().
If you have multiple files to move, just iterate over them.

Make Folders from Spreadsheet Data in Google Drive?

I am just beginning to learn Javascript and Google Apps Script. I have looked at and played with a few scripts, and so am attempting to create my own. What I want to do is take a list of students (Name and Email) and run a script to create "dropboxes", or folders that uses their name and is shared to their email address. This way, they can easily submit work to me in an organized manner. I have written this rough script, which I know will not work.
I was wondering if anyone can give me some tips?
function createDropbox () {
// Get current spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = sh1.getDataRange().getValues();
// For each email address (row in a spreadsheet), create a folder, name it with the data from the Class and Name column, then share it to the email
for(n=1;n<data.length;++n){
var class = sheet.getSheetValues(n, 1, 1, 1);
var name = sheet.getSheetValues(n, 2, 1, 1);
var email = sheet.getSheetValues(n, 3, 1, 1);
var folder = DocsList.createFolder('Dropbox');
folder.createFolder(class . name);
var share = folder.addEditor(email);
}
}
You've got the basic structure of your script right, it's only the semantics and some error handling that need to be worked out.
You need to determine how you want to access the contents of your spreadsheet, and be consistent with that choice.
In your question, you are first getting all the contents of the spreadsheet into a two-dimensional array by using Range.getValues(), and then later trying to get values directly from the sheet multiple additional times using .getSheetValues().
Since your algorithm is based on working through values in a range, use of an array is going to be your most effective approach. To reference the content of the data array, you just need to use [row][column] indexes.
You should think ahead a bit. What will happen in the future if you need to add more student dropboxes? As your initial algorithm is written, new folders are created blindly. Since Google Drive allows multiple folders with the same name, a second run of the script would duplicate all the existing folders. So, before creating anything, you will want to check if the thing already exists, and handle it appropriately.
General advice: Write apps script code in the editor, and take advantage of auto-completion & code coloring. That will help avoid mistakes like variable name mismatches (ss vs sh1).
If you are going to complete the exercise yourself, stop reading here!
Script
This script has an onOpen() function to create a menu that you can use within the spreadsheet, in addition to your createDropbox() function.
The createDropbox() function will create a top level "Dropbox" folder, if one does not already exist. It will then do the same for any students in the spreadsheet, creating and sharing sub-folders if they don't already exist. If you add more students to the spreadsheet, run the script again to get additional folders.
I've included comments to explain some of the tricky bits, as a free educational service!
/**
* Create menu item for Dropbox
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Create / Update Dropbox",
functionName : "createDropbox"
}];
sheet.addMenu("Dropbox", entries);
};
function createDropbox () {
// Get current spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getDataRange() // Get all non-blank cells
.getValues() // Get array of values
.splice(1); // Remove header line
// Define column numbers for data. Array starts at 0.
var CLASS = 0;
var NAME = 1;
var EMAIL = 2;
// Create Dropbox folder if needed
var DROPBOX = "Dropbox"; // Top level dropbox folder
try {
// getFolder throws an exception if folder not found.
var dropbox = DocsList.getFolder(DROPBOX);
}
catch (e) {
// Did not find folder, so create it
dropbox = DocsList.createFolder(DROPBOX);
}
// For each email address (row in a spreadsheet), create a folder,
// name it with the data from the Class and Name column,
// then share it to the email
for (var i=0; i<data.length; i++){
var class = data[i][CLASS];
var name = data[i][NAME];
var email = data[i][EMAIL];
var folderName = class + ' ' + name;
try {
var folder = DocsList.getFolder(DROPBOX + '/' + folderName);
}
catch (e) {
folder = dropbox.createFolder(folderName)
.addEditor(email);
}
}
}
Even though the question is ~6 years old it popped up when I searched for "create folders from sheets data" .
So , taking the answer as inspiration, I had to update the code to allow for changes in the Google API, i.e. no more DocsList.
So here it is.
function createMembersFolders () {
// Get current spreadsheet
var MembersFolder = DriveApp.getFolderById("1Q2Y7_3dPRFsblj_W6cmeUhhPXw2xhNTQ"); // This is the folder "ADI Members"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getDataRange().getValues() // Get array of values
// Define column numbers for data. Array starts at 0.
var NAME = 1;
// For each name, create a folder,
for (var i=1; i<data.length; i++){ // Skip header row
var name = data[i][NAME];
Logger.log(name);
if(MembersFolder.getFoldersByName(name).hasNext()){
Logger.log("Found the folder, no need to create it");
Logger.log(Object.keys(MembersFolder.getFoldersByName(name)).length);
} else {
Logger.log("Didn't find the folder so I'll create it");
var newFolder = MembersFolder.createFolder(name);
}
}
}
Note that I'm taking the parent folder directly using it's ID (which you get from the URL when viewing the folder).
You could also do this by name using the DriveApp.getFoldersByName("Folder Name").hasNext() condition which checks if the folder exist. If it does exist then you can access that folder you have found via DriveApp.getFoldersByName("Folder Name").next()
I didn't find that use of hasNext and next very intuitive but there it is.

create a Google spreadsheet in a particular folder

this question teaches how to adjust the folders of a file to move it into a particular folder, and out of the root.
It also suggests using folder.createFile to create it directly in the desired folder... but it appears createFile only applies to Docs... is there a way to create a spreadsheet directly in a particular folder?
Since DocsList is deprecated, currently the following solution works:
var folder=DriveApp.getFoldersByName(folderName).next();//gets first folder with the given foldername
var file=SpreadsheetApp.create(fileName);
var copyFile=DriveApp.getFileById(file.getId());
folder.addFile(copyFile);
DriveApp.getRootFolder().removeFile(copyFile);
Create spreadsheets using Apps Script does not work with regular Google accounts and Google Apps Standard Edition accounts. However, you can always make a copy of a dummy spreadsheet and then modify it accordingly using Google Apps Script. Here is a sample code.
function createSpreadsheetInfolder() {
var dummySS = DocsList.getFileById('ID of dummy SS');
var myCopy = dummySS.makeCopy('My new file');
//Get your target folder
var folder = DocsList.getFolder('ID or path of folder');
myCopy.addToFolder(folder);
}
The answers already given don't seem to work, maybe they're outdated.
Here's my answer (worked for me).
var folders=DriveApp.getFoldersByName("existingFolder");
while (folders.hasNext()) {
var folder = folders.next();
var file=SpreadsheetApp.create("the file that must be in a folder");
var copyFile=DriveApp.getFileById(file.getId());
folder.addFile(copyFile);
DriveApp.getRootFolder().removeFile(copyFile);
}
Admittedly, my answer is derived from the previous ones, none of which did exactly what I needed. This function has been tested with current Google Apps Script and spreadsheet documents. With duplicate folder names it will work, but move the file to the first folder returned by the API.
// Arguments are a file object and a folder name.
function moveFileToFolder(file, folderName)
{
var folders = DriveApp.getFoldersByName(folderName);
var copyFile = DriveApp.getFileById(file.getId());
if (folders.hasNext()) {
var folder = folders.next();
folder.addFile(copyFile);
DriveApp.getRootFolder().removeFile(copyFile);
}
}
Now it is possible to create Google spreadsheet in a specific folder.
For that you need to use advanced drive service v2. Enable it from Advanced Services menu in google app script editor.
var oFile = placeGoogleSpreadsheetInSpecificFolder("my file", "target folder id");
var oSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(oFile.getId()));
function placeGoogleSpreadsheetInSpecificFolder(sSpreadsheetName, sTargetFolderId) {
var oGeneratedFile = Drive.Files.insert({
"mimeType": "application/vnd.google-apps.spreadsheet",
"parents": [{
id: sTargetFolderId
}],
"title": sSpreadsheetName
});
return oGeneratedFile;
}
This solution worked perfectly fine for me.
This code works for me, I think there is no way to avoid the "remove from root" step, at least not that I know.
function createSpreadsheet() {
var folder = DocsList.getFolder('GAS');// this value as test for me
var root = DocsList.getRootFolder()
var newFileId = SpreadsheetApp.create('testNewSS').getId();// this defines the name of the new SS
var newFile = DocsList.getFileById(newFileId); // begin the 'move to folder process'
newFile.addToFolder(folder);
newFile.removeFromFolder(root);// had to do it in 2 separate steps
}
This question has beeen answerd in.
https://stackoverflow.com/a/19610700
It is a nice solustion.
folder.createFile("name", '',MimeType.GOOGLE_SHEETS);
using anything but a empty string leaves me with a error.
Just a 'heads up' for people who are reading this old answers like me. The most solutions are already deprecated. You have to use "moveTo" and you will not need to remove from root-directions or something else.
Have a look at this link for more details.
My solution to do so:
/**
* function createSS
* #description: Creates a new SpreadSheet with imported values and directly in provided folder
* #param {string} ssName name of SpreadSheet
* #param {object} sheetData values as range
* #param {object} ssFolder reference to a folder
*/
function createSS(ssName, sheetData, ssFolder = false){
var ss = SpreadsheetApp.create(ssName);
ss.setSpreadsheetLocale("de");
if(ssFolder){
// Move to provided folder
var file = DriveApp.getFileById(ss.getId());
file.moveTo(ssFolder);
}
var sheet = ss.getActiveSheet();
sheet.getRange(1, 1, sheetData.length, sheetData[0].length).setValues(sheetData);
return sheet;
}
Example with folder assignment:
var folders = DriveApp.getFileById(ssFileId).getParents();
var folder = folders.next();
// add new file (directly in correct folder)
var sourceSheet = createSS(newFileName, relevantValues, folder);
( This is only working this way, if you're sure your file is in 1 folder only. Otherwise, do it with .hasNext() and a loop )