Transfer Ownership of GoogleDrive Folder including Subfolders and Files - google-apps-script

due to some File migration from a Fileserver to Google Drive for a bunch of users in a company, it is necessary that I change the ownership of a Folder and all its containing subfolders and Files.
First I copy the whole folder to my drive(get the ownership this way), then I start my script to transfer the ownership to the new owner.
I wrote a small Script that is working fine for some smaller Folders (<1GB approx.) but almost always gives me an Error when transferring ownership of bigger ones:
Action not allowed (Line 85, File"Code")
Line 85 is containing the following code:
file.setOwner(newOwner);
I have to run that script a few times, sooner or later it finishes successfully.
Have no clue why the script gets that error.
Any Ideas?
Many thanks!
The script:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Transfer')
.addItem('Transfer Folder', 'Transferfolder')
.addSeparator()
.addItem('Disable Sharing Settings for Editors', 'Ownersettings')
.addToUi();
}
function Transferfolder()
{
var me=Session.getActiveUser().getEmail();
var ss = SpreadsheetApp.getActive();
var data = ss.getDataRange().getValues();
var idname=data[2][1];
var newOwner=data[3][1];
var fol = DriveApp.getFolderById(idname);
subfolderTransfer(fol,me,newOwner);
}
function Ownersettings()
{
var me=Session.getActiveUser().getEmail();
var ss = SpreadsheetApp.getActive();
var data = ss.getDataRange().getValues();
var idname=data[2][1];
var fol = DriveApp.getFolderById(idname);
disablesharebyeditors(fol,me);
}
function disablesharebyeditors(fol,me)
{
var files = fol.getFiles();
var folders=fol.getFolders();
Logger.log(fol.getOwner().getEmail());
if(fol.getOwner().getEmail()==me){
fol.setShareableByEditors(false);
Logger.log(fol);
}
while (files.hasNext())
{
var file = files.next();
if(file.getOwner().getEmail()==me){
file.setShareableByEditors(false);
}
}
while (folders.hasNext())
{
var subfolder = folders.next();
disablesharebyeditors(subfolder,me);
}
}
function subfolderTransfer(fol,me,newOwner)
{
Logger.log("subfolderTransfer");
var files = fol.searchFiles('"me" in owners');
var folders=fol.searchFolders('"me" in owners')
Logger.log(fol.getName());
if(fol.getOwner().getEmail()==me){
fol.setOwner(newOwner);
}
//file.removeEditor(me);
while (files.hasNext())
{
var file = files.next();
Logger.log(file.getName());
if(file.getOwner().getEmail()==me){
file.setOwner(newOwner);
}
}
Logger.log("folders");
while (folders.hasNext())
{Logger.log(fol.getName());
var subfolder = folders.next();
subfolderTransfer(subfolder,me,newOwner);
}
}
function transferfiles(files,me,newOwner)
{
while (files.hasNext())
{
var file = files.next();
if(file.getOwner().getEmail()==me){
file.setOwner(newOwner);
}
//file.removeEditor(me);
}
}

Related

Google Apps Script - Move folder from Root not working

I have the following code in a Spreadsheet app that:
Creates a folder in a given location;
Finds and copies a set of template folders and files from a master directory;
Moves them into the folder created in step 1.
However, periodically, the template folders are not moved during step 3 and remain under the Root. It seems to consistently happen with one specific set of templates that contains 21 folders and 38 files with a total size of 2.64 MB.
There are no errors that are highlighted in the App Script editor. The script message ends as expected.
Can anyone suggest why this may be happening and help with the code to prevent this from occurring.
Update: When this error occurs, I am left with a copy of the template folder in the Root of MyDrive. If I then run the 'moveFolder()' function on its own the problematic template folder move works 100%.
My Code:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Admin')
.addItem('Create Project', 'createProjectFolder')
.addItem('Get Template Folder', 'start')
.addItem('Move Template Folder', 'moveFolder')
.addToUi();
}
//******************************************************************************** */
//Create new Project Folder
//******************************************************************************** */
function createProjectFolder(FolderName, TargetFolder)
{
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName('Config');
var newFolderName = sh.getRange('NewProjectName').getValue();
//Change 'parentFolder' ID to the Verification Projects
var parentfolder = DriveApp.getFolderById('ID'); //Folder ID of Verification Projects folders
var newFolder = DriveApp.createFolder(newFolderName);
var currentFolders = newFolder.getParents();
while (currentFolders.hasNext())
var currentFolder = currentFolders.next();
currentFolder.removeFolder(newFolder);
parentfolder.addFolder(newFolder);
var newFolderID = newFolder.getId();
Logger.log(newFolderID)
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var configSheet = spreadSheet.getSheetByName('Config');
var range = configSheet.getRange('NewProjectNameID').setValue(newFolderID);
start();
return newFolderID;
}
//**************************************************************** */
//Copy master folder structure
//**************************************************************** */
function start() {
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var configSheet = spreadSheet.getSheetByName('Config');
var sourceFolder = configSheet.getRange('SourceFolder').getValue();
var targetFolder = configSheet.getRange('ProjectFolderLibraryName').getValue();
Logger.log(sourceFolder);
Logger.log(targetFolder);
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);
}
moveFolder();
}
function moveFolder(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Config');
var folderName = sh.getRange('ProjectFolderLibraryName').getValue();
Logger.log(folderName);
var folderNameID = sh.getRange('NewProjectNameID').getValue();
Logger.log(folderNameID);
var folder = DriveApp.getFoldersByName(folderName).next();
var destination = DriveApp.getFolderById(folderNameID);
destination.addFolder(folder);
folder.getParents().next().removeFolder(folder);
}
This has been resolved. I was calling the next function from within the current function. I suspect that the call to execute the next function was placed too early and conflicts then arose.
Solution: I created a separate function that contained the functions in order. This allowed each function to complete before the next was executed.
EG:
function allFunctions(){
function1();
function2();
function3();
}

Google Apps Script to Copy a given folder using UI Prompt for target folder name

I am trying to copy a given folder and its contents (sub folders and files) to a new folder using a simple Ui Prompt for the target folder name.
This is my updated script after suggestions from Meera:
function start() {
var sourceFolder = 'SourceFolderName'; // Folder exists in Drive
var source = DriveApp.getFoldersByName(sourceFolder);
var ui = SpreadsheetApp.getUi();
var folderPrompt = ui.prompt('Enter the Target Folder Name');
Logger.log(folderPrompt.getResponseText());
if (folderPrompt.getSelectedButton() == ui.Button.OK){
var target = folderPrompt.getResponseText();
if (source.hasNext()) {
copyFolder(source.next(), target);
}
Logger.log(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);
var target_folder = DriveApp.getFoldersByName(target); // Added as per Meera
var target = target_folder.next(); // Added as per Meera
}
while (folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}
}
}
The prompt box still displays but after entering the folder name and selecting OK nothing happens. Still no new target folder is created.
You need to make sure that you have a folder in your google Drive with the name "SourceFolderName" as you entered in line 2 of code. Else change the value to any existing folder name.
Also in the copyFolder function, the file.makeCopy(file.getName(), target); will not work as target is just the name(string) of the target folder. You have to add below two lines of code to get the folder var target_folder=DriveApp.getFoldersByName(target);var target=target_folder.next(); [refer here ]and the rest will work.
I have found a solution for target.createFolder is not a function.
When passing the target it is a string. Using the method getFoldersByName for the target folder as well you can get a folder instead of a string.
I have modified the script like:
function start() {
var sourceFolder = 'sourceFolder';
var targetFolder;
var ui = SpreadsheetApp.getUi();
var folderPrompt = ui.prompt('Enter the Target Folder Name');
//Logger.log(folderPrompt.getResponseText());
if (folderPrompt.getSelectedButton() == ui.Button.OK) {
targetFolder = folderPrompt.getResponseText();
}
var source = DriveApp.getFoldersByName(sourceFolder);
var folders = DriveApp.getFoldersByName(targetFolder);
while (folders.hasNext()) {
var folder = folders.next();
}
if (source.hasNext()) {
copyFolder(source.next(), 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);
}
while (folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}

Using Google Apps Script to find Docs/Slides/Sheets in all folders (and subfolders)

Starting with a link to a folder I'm trying to get info on all Docs/Slides/Sheets in that folder, the subfolders (and subfolders of subfolders).
With some online searching I finally got some code that will find ALL FILES, but I need to modify it to ONLY find Docs, Slides, and Sheets. What would be the best way to do that?
Here's the code I'm currently using:
function generateFolderTree(my_id) {
var parentFolder = DriveApp.getFolderById(my_id);
var f = parentFolder.getFiles();
Logger.log(f.next().getName())
getChildFolders(parentFolder);
}
function getChildFolders(parent) {
var childFolders = parent.getFolders();
while (childFolders.hasNext()) {
var childFolder = childFolders.next();
var files = childFolder.getFiles();
while (files.hasNext()) {
Logger.log(files.next().getName()); // Print list of files inside the folder
}
getChildFolders(childFolder); // Recursive call for any sub-folders
}
}
With a bit of playing around with this i'm positive you could implement it into your code ;)
https://developers.google.com/apps-script/reference/base/mime-type
// Use MimeType enum to log the name of every Google Doc in the user's Drive.
var docs = DriveApp.getFilesByType(MimeType.GOOGLE_DOCS);
while (docs.hasNext()) {
var doc = docs.next();
Logger.log(doc.getName())
}
// Use plain string to log the size of every PNG in the user's Drive.
var pngs = DriveApp.getFilesByType('image/png');
while (pngs.hasNext()) {
var png = pngs.next();
Logger.log(png.getSize());
}
Here is the code I wound up using and it seems to be doing everything I wanted/needed:
function getFolders() {
var my_link = Browser.inputBox('Enter Folder Link', 'Paste a folder link below...', Browser.Buttons.OK);
var my_id = getIdFromUrl(my_link);
fcount = 2;
SpreadsheetApp.getActiveSpreadsheet().toast("Im looking for SLIDES.", "WORKING...",600);
generateFolderTree(my_id,MimeType.GOOGLE_SLIDES);
SpreadsheetApp.getActiveSpreadsheet().toast("Im looking for DOCS.", "WORKING...",600);
generateFolderTree(my_id,MimeType.GOOGLE_DOCS);
SpreadsheetApp.getActiveSpreadsheet().toast("Im looking for SHEETS.", "WORKING...",600);
generateFolderTree(my_id,MimeType.GOOGLE_SHEETS);
SpreadsheetApp.getActiveSpreadsheet().toast("Your search is complete!", "FINISHED!");
};
// -------------------------------------------------------------------------------
function generateFolderTree(my_id,type) {
var parentFolder = DriveApp.getFolderById(my_id);
var f = parentFolder.getFilesByType(type);
while (f.hasNext()) {
file = f.next();
display(file);
}
getChildFolders(parentFolder,type);
}
function getChildFolders(parent,type) {
var childFolders = parent.getFolders();
while (childFolders.hasNext()) {
var childFolder = childFolders.next();
var files = childFolder.getFilesByType(type);
while (files.hasNext()) {
mfs = files.next();
display(mfs);
}
getChildFolders(childFolder,type); // Recursive call for any sub-folders
}
}
function myFunction()
{
var folders = DriveApp.getFoldersByName("Projects");
var folder = folders.next();
var sheets = getFilesInFolderByType(folder, MimeType.GOOGLE_SHEETS);
var docs = getFilesInFolderByType(folder, MimeType.GOOGLE_DOCS);
for each (var sheet in sheets)
{
console.log(sheet);
}
for each (var doc in docs)
{
console.log(doc);
}
}
function getFilesInFolderByType(folder, type)
{
var files = []
var filesInFolder = folder.getFilesByType(type);
while (filesInFolder.hasNext())
{
files.push(filesInFolder.next());
}
// Use method to recurse through sub folders.
var subFolders = folder.getFolders();
while (subFolders.hasNext())
{
var fileArray = getFilesInFolderByType(subFolders.next(), type);
files.concat(fileArray);
}
return files;
}

Google Script get files names into spreadsheet issues

I made a code App Script that lists all the Folder Names and Files names into a Spreadsheet which works good until I rename one of the folders or file. Then the next time I run the script it will not include the renamed Folder/File into the Spreadsheet. Is there something I have done wrong in the script?
Thanks in advance for the help.
Link to spreadsheet: https://docs.google.com/spreadsheets/d/1T3eKmyXKhLCbcoMdZRzMQ1__-dL3bTlH0wMKaWVFJ1Y/edit?usp=sharing
Link to Google Script: https://script.google.com/d/1LVTe29Y3jDbElt8LM4ciZ8Kj0gPzmFAxawZaYmRaFvkkfrewtJ5fxO0B/edit?usp=sharing
Link to Folder: https://drive.google.com/drive/folders/1VPQC9Cp4QT0r_ILmq9c0nOsSSduqh6jg?usp=sharing
function listFolders(folder) {
var ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1T3eKmyXKhLCbcoMdZRzMQ1__-dL3bTlH0wMKaWVFJ1Y/edit#gid=0');
var first = ss.getSheetByName("Sheet1");
first.clear("A2:D405");
var sheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1T3eKmyXKhLCbcoMdZRzMQ1__-dL3bTlH0wMKaWVFJ1Y/edit#gid=0');
sheet.appendRow(["File Name", "URL", "Folder Name"]);
var folder = DriveApp.getFolderById('1VPQC9Cp4QT0r_ILmq9c0nOsSSduqh6jg');
var subfolders = folder.getFolders();
while (subfolders.hasNext()) {
//Logger.log(folder);
var name = subfolders.next();
while (subfolders.hasNext()) {
//Logger.log(folder);
var name = subfolders.next();
var files = name.getFilesByType('application/vnd.google-apps.spreadsheet');
var cnt = 0;
var file;
while (files.hasNext()) {
var file = files.next();
cnt++;
Logger.log(file);
Logger.log(cnt);
data = [
file.getName(),
file.getUrl(),
name, //folder name
];
sheet.appendRow(data);
};
}
}
}

Copying active spreadsheet to all spreadsheet documents in a folder

I am attempting to copy an individual spreadsheet to all spreadsheet files within a folder. I could not figure out how to do it, so I am using a previous code I found that lists all of the files, but it ends up listing all of the files in my drive, not just in that folder.
Could I get assistance either in making a script to copy it to all files in a specific folder, or change it so that the below code shows only that of the folder it is in? From what I have seen/changed DriveApp.getFiles() should only be listing those files in the folder?
function List()
{
var app = UiApp.createApplication();
app.setTitle("Copy Sheet in Multiple Spreadsheets");
var form = app.createFormPanel();
var flow = app.createFlowPanel();
var label = app.createLabel("Select Spreadsheet where you want to copy the current sheet:").setId('selectLabel');
flow.add(label);
var allfiles = DriveApp.getFiles();
var verticalPanel = app.createVerticalPanel().setId('verticalPanel');
var i = 0;
while (allfiles.hasNext())
{
var file = allfiles.next();
var temp = app.createCheckBox(file.getName()).setName('cb'+i).setId('cb'+i);
var tempvalue = app.createHidden('cbvalue'+i, file.getId());
verticalPanel.add(temp);
verticalPanel.add(tempvalue);
i++;
}
var scrollPanel = app.createScrollPanel().setId('scrollPanel');
scrollPanel.add(verticalPanel);
scrollPanel.setSize("400", "250")
flow.add(scrollPanel);
var buttonsubmit = app.createSubmitButton("Copy");
flow.add(buttonsubmit);
form.add(flow);
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
return app;
}
function doPost(eventInfo) {
var app = UiApp.getActiveApplication();
var allfiles = DriveApp.getFiles();
var tempSsId = "";
var i = 0;
while (allfiles.hasNext())
{
var temp = eventInfo.parameter['cb'+i];
if(temp == 'on')
{
tempSsId = eventInfo.parameter['cbvalue'+i];
var activeSheet = SpreadsheetApp.getActiveSheet().copyTo(SpreadsheetApp.openById(tempSsId));
activeSheet.setName(SpreadsheetApp.getActiveSheet().getSheetName());
}
i++;
}
var label = app.createLabel('statusLabel');
label.setText("Copied Active sheet in all selected Spreadsheets...");
label.setVisible(true);
app.add(label);
return app;
}
DriveApp.getFiles(); will get every file in your Drive.
DriveApp.getFolderById('folder id').getFiles(); If you want to get files in a specific folder (this will get the files in that folder but not in subfolders).
This script has nothing to do with the question you asked and I think you may have worded your question incorrectly.
Do you mean you are attempting to copy an individual sheet from a spreadsheet to all of the other spreadsheets in a particular folder?
EDIT
function copyTo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = ''; // ENTER THE NAME OF THE SHEET YOU WANT TO COPY
var targetFolder = DriveApp.getFolderById(''); //ENTER THE ID OF THE TARGET FOLDER HERE
var sheet = ss.getSheetByName(sheetName);
var getFiles = targetFolder.getFiles();
while (getFiles.hasNext()) {
var file = getFiles.next();
if (file.getMimeType() == 'application/vnd.google-apps.spreadsheet') {
var targetSheet = SpreadsheetApp.openById(file.getId());
sheet.copyTo(targetSheet).setName(sheetName);
}
}
}