Drive Folder ID from file - google-apps-script

after the renewal of DriveApp API I'm struggling to update my script.
It was able to find the Drive Folder ID starting from a file.
Basically starting from a Spreadsheet, I found what was the ID of the folder that contained the file.
Now if i try:
var thisFile =(the file I have)
var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents()[0];
var targetFolder = DriveApp.getFolderById(parentFold);
targetFolder.addFile(newFile);
The system sends an error at line 4 "No item with the given ID could be found, or you do not have permission to access it." (even if I open all the permissions).
Any suggestion?
Thanks!

The getParents() method returns a FolderIterator. It doesn't return the folder ID. You need to get the folder:
var folder = folders.next();
The code given assumes that there is only one parent folder to the file.
Updated Answer:
function copyToParent() {
var thisFile = DriveApp.getFileById('file ID');
//var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents();//Get all parents - normally just one parent
var folder = parentFold.next();//Get the first parent folder
//Logger.log('folder name: ' + folder.getName());//For testing - log folder name
folder.addFile(newFile);
}
Old Answer:
This answer has unneeded steps.
Then get the ID of the folder:
var theId = folder.getId();
Full code:
function copyToParent() {
var thisFile = DriveApp.getFileById('file ID');
//var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents();
var folder = parentFold.next();
var theId = folder.getId();
var targetFolder = DriveApp.getFolderById(theId);
Logger.log('targetFolder name: ' + targetFolder.getName());
targetFolder.addFile(newFile);
};

Related

How can I modify this to save a spreadsheet into a new folder

I've found scripts that save a copy of a spread sheet, but so far I've not been able to figure out how to modify the following code to save my spreadsheet into the newly created/already existing folder.
//Create folder if it does not exist
function createFolder(folderID, folderName){
var parentFolder = DriveApp.getFolderById(folderID);
var subFolders = parentFolder.getFolders();
var doesntExist = true;
var newFolder = '';
// Check if folder already exists.
while(subFolders.hasNext()){
var folder = subFolders.next();
//If the folder exists return the id of the folder
if(folder.getName() === folderName){
doesntExist = false;
newFolder = folder;
return newFolder.getId();
};
};
//If the folder doesn't exist, then create a new folder
if(doesntExist == true){
//If the file doesn't exist
newFolder = parentFolder.createFolder(folderName);
return newFolder.getId();
};
};
function start(){
var FOLDER_ID = 'my folder id';
var NEW_FOLDER_NAME = SpreadsheetApp.getActiveSheet().getRange('A1').getValue();
var myFolderID = createFolder(FOLDER_ID, NEW_FOLDER_NAME);
};
Update:
My goal is to create a new folder based on the contents of cell A1 if that folder doesn't exist and save the file in that folder. If the folder already exists, then save the file in the existing folder. The file name will be in cell A2.
I want to save a copy, and leave the original file where it is.
Since September 30, 2020, Drive files cannot have multiple parent folders.
Therefore, you should either move your file to the new folder, or make a copy of the file. But you cannot have the same file in two different folders.
You should use either moveTo(destination), if you want to move the file to the new folder, or makeCopy(destination) if you want to copy your file to the new folder.
Update: You mentioned in comments that you want to make a copy the file (not move it) and specify the name of the copied file (corresponding to value in A2). Therefore, you should use makeCopy(name, destination).
Considering that you want to save the active spreadsheet, your main function could be like this:
function start(){
var PARENT_FOLDER_ID = 'my folder id';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var NEW_FOLDER_NAME = sheet.getRange('A1').getValue();
var FILE_NAME = sheet.getRange('A2').getValue();
var spreadsheetId = ss.getId();
var file = DriveApp.getFileById(spreadsheetId);
var folder = createFolder(PARENT_FOLDER_ID, NEW_FOLDER_NAME);
file.makeCopy(FILE_NAME, folder);
}
And the function createFolder could be greatly reduced in size, using Folder.getFoldersByName(name):
function createFolder(folderID, folderName){
var parentFolder = DriveApp.getFolderById(folderID);
var subFolders = parentFolder.getFoldersByName(folderName);
if (subFolders.hasNext()) return subFolders.next(); // Return existing folder
else return parentFolder.createFolder(folderName); // Return created folder
}
Notes:
Because of this behaviour change in Drive, methods like addFile(child) are deprecated.
Reference:
Single-parenting behavior changes
The script in your example creates a new folder. It doesn't save anything, as far as I can tell.
If you want just save your current spreadsheet in some already existing folder, here you go:
var id = SpreadsheetApp.getActiveSpreadsheet().getId();
var file = DriveApp.getFileById(id);
var folder = DriveApp.getFolderById("FOLDER_ID"); // <-- ID of the destination folder
folder.addFile(file);
Update. In case you know the name of destination folder and the folder shares the same parent folder with current spreadsheet file the script can look like this:
var ss = SpreadsheetApp.getActiveSheet();
var dest_folder_name = ss.getRange('A1').getValue();
var copy_name = ss.getRange('A2').getValue();
var dest_folder = "";
var file_id = SpreadsheetApp.getActiveSpreadsheet().getId();
var file = DriveApp.getFileById(file_id);
var parent_folder = file.getParents().next();
var sub_folders = parent_folder.getFolders();
// search a destination folder in current folder
while (sub_folders.hasNext()) {
dest_folder = sub_folders.next();
if (dest_folder.getName() === dest_folder_name) {
break;
}
dest_folder = "";
}
// create the destination folder if nothing was found
if (dest_folder === "") {
dest_folder = parent_folder.createFolder(dest_folder_name);
}
// copy the spreadsheet to the destination folder
file.makeCopy(copy_name, dest_folder);
The script tires to finds destination folder (the name taken from cell 'A1') inside current folder and creates the folder if nothing was found. After that it saves a copy of current spreadsheet (the name taken from cell 'A2').
NB. GoogleDrive allows files or subfolders with the same names inside one folder. So it's not unlikely to get many spreadsheets with identical names. Perhaps it makes sense to check names of existing files before the saving.

duplicate folder and rename file structure

I'm trying to automate my duplicating folder process in google drive. As part of the process, I want to rename files and folders for each new client.
I've adapted some code found previously. It was previously working well, but for some reason now any folders/files that are more than 1 level deep of the root folder come back "undefined" in the replace section of the command.
function duplicatefolder(){
var newclientname = Browser.inputBox('Client Name')
var sourceFolder = "1. Master Client Folder";
var targetFolder = newclientname;
var source = DriveApp.getFoldersByName(sourceFolder);
var target = DriveApp.createFolder(targetFolder);
if (source.hasNext()) {
copyFolder(source.next(), target, newclientname);
}
}
function copyFolder(source, target,client) {
var folders = source.getFolders();
var files = source.getFiles();
while(files.hasNext()) {
var file = files.next();
var newname= file.getName().toString().replace("Master",client)
file.makeCopy(newname, target);
}
while(folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var newFolderName = subFolder.getName().replace("Master",client)
var targetFolder = target.createFolder(newFolderName);
copyFolder(subFolder, targetFolder);
}
}
The script also creates the folder in the root directory of google drive. Ideally, I'd like it to be created inside the folder "Clients". How would I add this to the script?
Appreciate the help.
Cheers
Please see attached link hope this is it what you are looking for
https://yagisanatode.com/2018/07/08/google-apps-script-how-to-create-folders-in-directories-with-driveapp/

Google Apps - How to get all files name from current directory?

How I can get all files name from current directory?
I have a code
function showAllFollderFronRoot() {
// get all files from the ROOT folder
var files = parentFolder;
while (files.hasNext()) {
var file = files.next();
// Logger.log(file.getName());
DocumentApp.getUi().alert(file.getName());
}
}
But it work only with ROOT dir.
How I can get all file names in array in current dir?
UPDATE:
I have a file structure: MT/MT.100-107/MT.100-1007.1001.doc
I need make code, if somebody open New Template from Docs - script need automatically safe this file with true structure - with next filename + 1 (example MT.100-1007.1002.doc, next new file from Template - MT.100-1007.1003.doc ...)
Script need to find all filenames => show last bigger count (1002.doc) => count + 1 => save this file with new filename MT.100-1007.1003.doc
My code work, but it make tmp file in Root dir & not work perfect, because it not calculate last bigger count in current dir and if I delete file, example MT.100-1007.1003.doc in dir MT, and make new file in dir UA - count be MT.100-1007.1004.doc no matter what the names of the files are in the folder UA.
These script with mistakes, how I can fix it?
/**
* #OnlyCurrentDoc
*/
function saveFilename() {
// Get current file name
const ui = DocumentApp.getUi(),
doc = DocumentApp.getActiveDocument(), //Added
thisFileId = doc.getId(),
thisFileName = doc.getName();
const thisFile = DriveApp.getFileById(thisFileId);//Modified from getFolderById
const parentFolder = thisFile.getParents();
const currentFolder = parentFolder.next();//Modified from currentFolderName
const currentFolderName = currentFolder.getName();//Added
//ui.alert(currentFolderName);
/*Store a init file in root to getLatestFileNumber*/
var initIter = DriveApp.getFilesByName(currentFolderName + 'init00'),
initBool = initIter.hasNext(),
init;
if (!initBool) {
init = DriveApp.createFile(currentFolderName + 'init000', '0');
} else {
init = initIter.next();
}
/*Get current Number and format it to 4 digits*/
var currentNum = init.getBlob().getDataAsString() * 1 + 1,
formatNum = ('0000' + currentNum).substr(-3);
/*If filename already contains folderName, do nothing*/
if (!(thisFileName.search(currentFolderName) + 1)) {
doc.setName(currentFolderName +'.' + formatNum).saveAndClose();
init.setContent(currentNum);
}
// delete TMP file from ROOT dir
DriveApp.getFileById(init.getId()).setTrashed(true)
}
You want to retrieve filenames of all files in the parent folder of the active document.
If my understanding is correct, how about this answer?
Flow:
The flow of this script is as follows.
Retrieve file ID of the active document.
Retrieve parent folder ID of the active document.
Retrieve files in the parent folder ID.
Retrieve filenames of files.
Modified script:
function showAllFollderFronRoot() {
var fileId = DocumentApp.getActiveDocument().getId();
var parentFolderId = DriveApp.getFileById(fileId).getParents().next().getId();
var files = DriveApp.getFolderById(parentFolderId).getFiles();
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName())
}
}
Note:
This sample script supposes as follows.
The parent of the active document is only one.
All files in the parent folder of the active document are retrieved. But the folders are not retrieved.
References:
getId()
getParents()
getFolderById(id)
getFiles()
If I misunderstand your question, please tell me. I would like to modify it.
I fix this problem, but idk how to parse last 4 digits in filename and find MAX from it. Do you have any idea? method slice(4) not working in apps script :(
function currFiles() {
const ui = DocumentApp.getUi(),
doc = DocumentApp.getActiveDocument(),
thisFileId = doc.getId(),
thisFileName = doc.getName();
const thisFile = DriveApp.getFileById(thisFileId);
const parentFolder = thisFile.getParents();
const currentFolder = parentFolder.next();
const currentFolderName = currentFolder.getName();
const currentFolderId = currentFolder.getId();
// get all files in currentFolder
var folderId = currentFolderId;
// Log the name of every file in the folder.
var files = DriveApp.getFolderById(folderId).getFiles();
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName());
}
}

How to create a file in the active Directory

The problem I have is that the file is created in the root and I cannot find the right instruction to change to a named directory!
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create( invNo );
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
invtoSend.copyTo(newSpreadsheet);
just create the spreadSheet, get its ID and then use DriveApp to move it (and to remove it from root otherwise it will be available in both !)
var newSpreadsheet = SpreadsheetApp.create( invNo );
var file = DriveApp.getFileById(newSpreadsheet.getId());
DriveApp.getFolderById('0B3°°°°°°°1lXWkk').addFile( file );
DriveApp.getRootFolder().removeFile(file);
EDIT
I reallize that your question can be understood differently : you might want that the destination folder would be the "current spreadsheet" folder, in this case here is the appropriate code :
function xxxx(){
var newSpreadsheet = SpreadsheetApp.create( "invNo" );
var file = DriveApp.getFileById(newSpreadsheet.getId());
var folders = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getParents();
while(folders.hasNext()){ // a file might be in multiple folders, include it in all of them except root
var folder = folders.next();
if(folder.getName()!=DriveApp.getRootFolder().getName()){ // root folder name changes with user's locale
folder.addFile(file);
DriveApp.getRootFolder().removeFile(file);
Logger.log('destination folder name = '+folder.getName());
}
}
}

How to change sharing permission google drive subfolder files?

I have a main folder Folder 1
inside Folder 1 there is multiple subfolder which have files. i want to change all subfolder files sharing permission Access.ANYONE_WITH_LINK no sign in require. currently i have follow code but it only work if there is no subfolders.
function myFunction() {
var folderId = "Folder 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);
};
}
This code will help you with your current problem:
function myFunction() {
var folderId = "main-id-folder";
// Take the mainder folder
var mainFolder = DriveApp.getFolderById(folderId);
// Take the subfolders inside your main folder
var subFolders = mainFolder.getFolders();
var result = [];
// Iterate over each subfolder
while(subFolders.hasNext()){
var subFolder = subFolders.next();
// Take the files inside the current subfolder
var files = subFolder.getFiles();
// Take each file inside the current subfolder
while(files.hasNext()){
var file = files.next();
var tmp = {
file_name: file.getName(),
url: "https://docs.google.com/spreadsheets/d/" + file.getId() + "/edit#gid=0"
};
// For the current file, stablish the permissions you want
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
result.push(tmp);
}
}
Logger.log(result);
}
The problem you had is you were only trying to get the files from your main folder but in order to get the files inside each subfolder, you needed to first take each subfolder using .getFolders(); and then for each one of them, you could use .getFiles();.
Docs
These are the docs I used to help you, in case you want to see them or anyone else who has a similar issue:
Class File
Enum Access