How to solve google app script timeout issue - google-apps-script

My google app script stop work after a certain times. the following code changes the file permission. in my folder there is like 10K files. when i run the script after changing 1~2K file sharing permission script stop work. is there anyway to solve the issue?
function myFunction() {
var folderId = "ID";
var files = DriveApp.getFolderById(folderId).getFiles();
var result = [];
while (files.hasNext()) {
var file = files.next();
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var temp = {
file_name: file.getName(),
url: "http://drive.google.com/uc?export=view&id=" + file.getId(),
};
result.push(temp);
};
}

There are several workarounds, from upgrading your account to grant access to longer timeouts, you could also make the script work with a cache service and store the state of the iteration before the timeout, then run again the script with this value stored on the cache.
Although, all of this may be to much for what you are attempting to: permissions on Drive have inheritance.
What does this mean? This means that if you change the permission settings on any folder you'll override the permissions of each file on that folder.
In summary, you really do not need to make any iteration thru all the files, change the permissions for that folder and you are done.
Check this docs in case of doubt.
A working code to change your folder permission and all its contained files:
function myFunction() {
var folder = DriveApp.getFolderById("YOUR_FOLDER_ID");
folder.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
}
This works, but due to the large number of files on your folder propagation may take some time, up to several hours, be patient and check it tomorrow.

Related

Google Apps Script returning all files in Drive, rather than files in a folder

I have a folder in Google Drive, where there are some files. I want to retrieve all of these file information, and that's all I want. There are many other files in other folders, but I don't need them. However, my following code is showing all files' names. How can I limit the result only to the files in the specified folder?
//Folder ID
var myFolderId = "XXXXXXXXXXXXXXXXXXXXXXXXX";
var files = DriveApp.getFolderById(myFolderId).getFiles();
while(files.hasNext())
{
var file = files.next();
Logger.log(file.getName());
}
For now, there are only 4 files in this folder, but the log shows the entire file names in my Google Drive. I don't know what I am doing wrong, because I am specifying the folder with ID. How come it is returning every file in Google Drive?
Answer:
Your code already works great!
Further information:
Google Apps Script doesn't allow the running of global code as specific functions need to be declared and run, at least, not in the same was as locally-run code. The global variables are static and can not be changed in the runtime.
Things you can do:
As Cooper mentioned in their comment - all you need to do is put your code in a function, call the function and you're set. The code works great:
function functionName(){
var myFolderId = "XXXXXXXXXXXXXXXXXXXXXXXXX";
var files = DriveApp.getFolderById(myFolderId).getFiles();
while(files.hasNext())
{
var file = files.next();
Logger.log(file.getName());
}
}
As a side-note: if you really want to use a global scope (or at least. use an emulation of it), the PropertiesService is available to you, though you'd still have to set them in a function and run a function to retrieve them:
function setVars(){
PropertiesService.getScriptProperties().setProperty('myFolderId', 'XXXXXXXXXXXXXXXXXXXXXXXXX');
}
function listFiles(){
var files = DriveApp.getFolderById(PropertiesService.getScriptProperties().getProperty('myFolderId')).getFiles();
//continue this code
}

Trying to copy files I do not own from a shared drive to personal drive

I am an educator and have content I created and co-created on a school google drive. I am leaving the school and trying to take a copy of the lessons I created and co-created. The school drive has files where I am the owner and not the owner in a main folder with subfolders. Our tech person said to try the code below, but I am getting an error and no further support from my school.
I have tried sharing files within the google drive application and then have gotten as far as trying to use the code below by inputting my folder names, but it give me an error on line 22 of the code. I don't know what to do other than open each individual file and manually save it. I only have access to the shared drive until July 26. PLEASE HELP!
function duplicate() {
var sourceFolder = "5-8 Shared Humanities";
var targetFolder = "Copy of humanities curriculum from FSMN";
var source = DriveApp.getFoldersByName(sourceFolder);
var target = DriveApp.createFolder(targetFolder);
if (source.hasNext()) {
copyFolder(source.next(), target);
}
}
function copyFolder(source, target) {
var folders = source.getFolders();
var files = source.getFiles();
while(files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), target);
}
while(folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}
I expected the code to copy the file structure and all files from all owners from the shared drive to the new personal drive I created. It seems like I am still running into file permissions issues for files I do not own. I am getting the following error:
Access denied: DriveApp. (line 22, file "Code")
I tried your script on stuff that was shared with me, both with modification permission and just read-only, and it worked fine.
That error is usually about drive apps being disabled (which prevents scripts too). See link
But since, it works for the files you own, I'm guessing that those you don't are either in 'read-only' or 'comment' mode. As is it wouldn't prevent you from making a copy, but when sharing the owner can check a box to disable print, download and copy options for commenters and readers.
So I think your only solution is to ask the owner to uncheck that box :/
To copy the files into your personal storage than do the following:
Make a shortcut of the folder in your personal drive.
Create a new Google Colaboratory notebook.
Mount your drive using following code:
from google.colab import drive
drive.mount("/content/drive")
Next, Enter Command:
!cp -rp '/content/drive/JAVA_ANDROID/*' '/content/drive/My Drive'
Where,
JAVA_ANDROID is name of the shortcut of the folder, put the name of the folder you desire to copy and append /* to copy all files at that location.
Next is path of the folder where copied files are to be saved, which is /content/drive/My Drive in this case.
Edit: I have noticed that in some cases adding /* doesn't work. So if it doesn't work the above specified way. Just don't append * to the shortcut name and try. So in this case the above command would be:
!cp -rp '/content/drive/JAVA_ANDROID/' '/content/drive/My Drive'

Acquiring the Google Drive folder my google script is located

With the help of a nice article (https://www.labnol.org/internet/google-drive-tree/21198/), I just setup my first google script in Google Drive.
Quick Question:
How may I get a running script /myFolder1/music/myFirstScript.gs, to determine it's running in /myFolder1/music?
This didn't work. I got the Url but nothing in the log file showed the correct answer.
var files = DriveApp.searchFiles('title contains "GoogleTreeAgenda5"');
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName());
Logger.log(file.getUrl());
Logger.log(file.getDownloadUrl());
Logger.log(file.getDescription());
Logger.log(file.getOwner());
Logger.log(file.getParents());
Logger.log(file.getParents()[0].getName());
Logger.log("------------------------------");
}
Longer Behind The Scenes Reason:
The file will be modified a bit so that each month I will create a new tree structure off the root with agenda topics and the script will create an html file from the directory tree which is based on topic. Basically it will be an outline creator based on the current location of the script file. So Let's say this month it's in: /myFolder1/music (so in other words it's /myFolder1/music/myFirstScript.gs. The script needs to determine that folder is /myFolder1/music so that I can have it print the tree structure starting from the folder it's located in to an html file..
In the example application provided by the site I noted above, there are 2 options to print the tree from the google script:
1) Tree starting from the root folder
var parentFolder = DriveApp.getRootFolder();
2) Starting from a particular folder (but I can't figure out and will need "Folder_Name" to be determined dynamically from the location where the .gs file is located)
var parent = DriveApp.getFoldersByName("FOLDER_NAME").next();
I've used getScriptId() this will:
Gets the script project's unique id.
This id is also the unique id in the Google Drive. Then from there, create a recurring getParents() until you reach the root folder.
Here is the complete code:
function myFunction() {
var scriptID = ScriptApp.getScriptId();
// Logger.log(scriptID)
// Log the name of every parent folder
var driveFile = DriveApp.getFileById(scriptID);
var parentFolder = driveFile.getParents();
while (parentFolder.hasNext()) {
var folder = parentFolder.next();
Logger.log(folder.getName());
}
}
NOTE:
There is no real or concrete path since a file can have multiple parents. It is also stated here in this related SO post.
Hope this helps.

Spreadsheet creation - Permissions, file location and remove file

I have an Adwords script that creates a new spreadsheet by using the command below:
var ssNew = SpreadsheetApp.create("Name document");
Is it possible to create this file in a specific folder of my Google Drive?
If so; the file will have the default access (view, edit, comment) permissions as the folder has, right?
If not; is it possible to give the created file a permission as in "Everyone in [company] can edit this file"?
Furthermore, is it possible to set some sort of expiration date for the file?
I'm planning on running the script daily and old files will no longer be relevant.
I can build some sort of check to find the old file, delete it and then run the script again, but if there is some sort of expiration function that would save me quite some code.
Thanks!
It is apparently not possible to create Spreadsheets within folders.
You'll have to use something like this:
function createNewSpreadsheetinFolder(){
var ssNew = SpreadsheetApp.create("Name document");
var targetFolder = DriveApp.getFolderById("0B1TY_1aqz3fpWktMa25LbVkzQTQ");
var ssnewFile = DriveApp.getFileById(ssNew.getId());
var ssFinal = ssnewFile.makeCopy("Name document", targetFolder);
ssnewFile.setTrashed(true);
try {ssFinal.addViewers(targetFolder.getViewers())} catch(e){};
try {ssFinal.addEditors(targetFolder.getEditors())} catch(e){};
}

Google apps script Permissions on created file in shared folder

I have a script which creates a file in a shared Google Drive folder, this is the script:
var spr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Klantenlijst');
var data = spr.getDataRange().getValues();
var klanNumbers = data; //some var declared before this piece of code
var file = DriveApp.createFile(fileName, JSON.stringify(klanNumbers));
This file needs to be updated frequently, to do so I remove the existing file and create a new one to replace it (with the new data). The problem is that when I try to perform the setTrashed action as a user other than the file owner, this error pops up:
You do not have authorization to perform that action.
Any ideas on how to fix that? :)
Thanks!
EDIT: I can delete the file in drive manually with the other users.
I have seen this article but I totally disagree with the conclusion that the problem is "too localized". Look around on Google and you will find cases with the same problem without a decent solution.
Workaround for this moment:
Rename the file
Move it to another folder
Create the new file in the old folder
I will not delete this post so people can add other ideas here.
You can only trash files that you own. When you delete the file manually (using the GUI to trash the file), it appears that you've trashed the file, but you are not actually setting the trashed flag on it. Rather, you are removing it from view in your own Google Drive, without affecting anyone else. The owner still sees it shared with you, and any other collaborators are unaffected. In fact, you can still see the file if you search for it by its full name, or use one of the alternate views such as the "Recent" file list, or use the file's URL.
To get the same effect from a script, use removeFile().
Here's a utility that will treat a file differently for owners than collaborators, to either trash or remove it.
/**
* Remove the given file from view in the user's Drive.
* If the user is the owner of the file, it will be trashed,
* otherwise it will be removed from all of the users' folders
* and their root. Refer to the comments on the removeFile()
* method:
*
* https://developers.google.com/apps-script/reference/drive/drive-app#removeFile(File)
*
* #param {File} file File object to be trashed or removed.
*/
function deleteOrRemove( file ) {
var myAccess = file.getAccess(Session.getActiveUser());
if (myAccess == DriveApp.Permission.OWNER) {
// If I own the file, trash it.
file.setTrashed(true);
}
else {
// If I don't own the file, remove it.
var parents = file.getParents();
while (parents.hasNext()) {
// Remove the file from the current folder.
parents.next().removeFile(file);
}
// Remove the given file from the root of the user's Drive.
DriveApp.removeFile(file);
}
}
Example:
function test_deleteOrRemove() {
var files = DriveApp.getFilesByName('536998589.mp3');
while (files.hasNext()) {
var file = files.next();
deleteOrRemove( file );
}
}