I have two parent folders that I want to check if Folder(folderName) exists in. folderName is defined by the range S2:2 in my spreadsheet
If Folder(folderName) does not exist in EITHER parent folder, then I want that folder to be created in Parent Folder 1.
So far my script is managing to check Parent Folder 1 and create in Parent Folder 1, but is not checking Parent Folder 2.
This is the script I have so far:
function myfunction() {
var parent = DriveApp.getFolderById("parent Folder 1")
SpreadsheetApp.getActive().getSheetByName('Letter History').getRange('S2:S').getValues()
.forEach(function (r) {
if(r[0]) checkIfFolderExistElsesCreate(parent, r[0]);
})
}
function checkIfFolderExistsElseCreate(parent, folderName) {
var folder;
try {
folder = parent.getFoldersByName(folderName).next();
} catch (e) {
folder = parent.createFolder(folderName);
}
function myFunction() {
var parentFolder1 = DriveApp.getFolderById('<ParentFolder1 ID>').getFolders(); //Get ID for Folder 1
var parentFolder2 = DriveApp.getFolderById('<ParentFolder2 ID>').getFolders(); //Get ID for Folder 2
var sheet = SpreadsheetApp.getActive().getSheetByName('Letter History');
//Iterating to read all the subfolders in ParentFolder 1 and 2
var childNames = [];
while (parentFolder1.hasNext()) {
var child = parentFolder1.next();
childNames.push([child.getName()]);
}
while (parentFolder2.hasNext()) {
var child = parentFolder2.next();
childNames.push([child.getName()]);
}
//Checking if the subfolder/s is existing or not, then creating in folder 1 if not yet existing
var data = sheet.getRange(2, 19, sheet.getLastRow() - 1, 1).getValues(); //S = 19, Change 19 according to column.
for (var i = 0; i < data.length; i++) {
if (childNames.flat().includes(data[i][0])) {
console.log(data[i][0] + "- already exist")
} else {
DriveApp.getFolderById('<ParentFolder1 ID>').createFolder(data[i][0])
console.log(data[i][0] + "- has been created")
}
};
}
The above code will create subfolder/s in Folder 1 based on range S2:S column in spreadsheet, if it is checked that the subfolder name does not yet exist either in Parent Folder 1 or 2.
Please take note to change the following:
ParentFolder 1 ID
ParentFolder 2 ID
Reference: How to create a folder if it doesn't exist?
I believe your goal is as follows.
You want to expand your showing script for using 2 parent folders.
In this case, how about the following sample script?
Sample script:
Please set your parent folder IDs to parentFolderIDs and save the script.
function myfunction() {
// Please set your parent folder IDs you want to use.
const parentFolderIDs = ["###parent folder ID1###", "###parent folder ID2###"];
// 1. Retrieve subfolders from folders of parentFolderIDs.
const parentFolders = parentFolderIDs.map(id => DriveApp.getFolderById(id));
const subFolders = parentFolders.map(folder => {
const temp = [];
const folders = folder.getFolders();
while (folders.hasNext()) {
temp.push(folders.next().getName());
}
return { parent: folder, subFolderNames: temp };
});
// 2. Create new folders when the folder names are not existing.
const sheet = SpreadsheetApp.getActive().getSheetByName('Letter History');
const values = sheet.getRange('S2:S' + sheet.getLastRow()).getDisplayValues();
values.forEach(([s]) => {
if (s) {
subFolders.forEach(({ parent, subFolderNames }) => {
if (!subFolderNames.includes(s)) {
parent.createFolder(s);
}
});
}
});
}
When this script is run, the subfolders in parentFolderIDs are retrieved. And, using the retrieved subfolders, the new subfolders are created in the parent folders of parentFolderIDs.
References:
map()
forEach()
Related
I'm having trouble creating a script in Google Apps Script that checks the number of files in a subfolder of the spreadsheet folder.
A friend here on the forum helped me to create a script that checks the spreadsheet folder, but now I need to modify it to check the subfolder of the spreadsheet folder.
The script I have at the moment is this one:
/** Written by Tanaike */
function CheckForFiles() {
const ss = SpreadsheetApp.getActiveSpreadsheet(); // This is your active Spreadsheet.
const parentFolder = DriveApp.getFileById(ss.getId()).getParents();
if (parentFolder.hasNext()) {
const files = parentFolder.next().getFiles();
let count = 0;
while (files.hasNext()) {
const file = files.next();
// console.log(file.getName()); // When you use this line, you can see the filename of the files.
count++;
}
if (count >= 3) {
throw new Error("Your expected error.");
}
} else {
throw new Error("Spreadsheet has no parent folder.");
}
}
Important point: note that the spreadsheet folder is a template folder, that is, it will be duplicated and its name will be changed several times, for this reason I need the script to be something like "Check how many files there are inside the subfolder FolderToBeCheck which is inside the folder of this worksheet, if the number of files is more than 3, return an error"
How can I achieve this?
Test Folder
In your situation, how about the following modification?
Modified script:
In this modification, from your showing image, it supposes that the folder name of the subfolder is FolderToBeCheck. In your question, it seems that the folder name is FolderToBeChecked. Please be careful about this difference.
function CheckForFiles() {
const subFolderName = "FolderToBeCheck"; // Please set your subfolder name.
const ss = SpreadsheetApp.getActiveSpreadsheet(); // This is your active Spreadsheet.
const parentFolder = DriveApp.getFileById(ss.getId()).getParents();
if (parentFolder.hasNext()) {
const innerFolder = parentFolder.next().getFoldersByName(subFolderName); // <--- Modified
if (innerFolder.hasNext()) {
const files = innerFolder.next().getFiles();
let count = 0;
while (files.hasNext()) {
const file = files.next();
// console.log(file.getName()); // When you use this line, you can see the filename of the files.
count++;
}
if (count >= 3) {
throw new Error("Your expected error.");
}
} else {
throw new Error("Folder of 'FolderToBeCheck' was not found.");
}
} else {
throw new Error("Spreadsheet has no parent folder.");
}
}
When this script is run, the subfolder of FolderToBeCheck is checked. And, the number of files in the folder is counted.
Hope that somebody can help me. I create a Google script for New Folder include Hyperlink. (very new in Script)
For some reason it gives no Errors but it also creates No Folders..
The Hyperlink must be in Column R and the Name of the Folder is from the last row Column a,b together.
(is there also a possibility to Copy a existing Template Folder to a New Folder)
function createAndHyperlink() {
var ss, sh, parent, parent2, r, v, thisCell, folder
ss = SpreadsheetApp.getActive()
sh = ss.getSheetByName('MOC Permanent')
parent = DriveApp.getFileById(ss.getId()).getParents().next();
parent2 = DriveApp.getFolderById("1vxS3FebsDLqrGGQc9kG7cE3tO9zN8Qre")
r = sh.getLastRow()
v = sh.getMaxColumns()
for (var i = 0, l = v.length; i < l; i++) {
thisCell = sh.getRange(i + 3, 2)
if (v[i][0] && !thisCell.getFormula()) {
folder = parent2.createFolder(v[i][0]);
thisCell.setFormula('=HYPERLINK("' + folder.getUrl() + '"; "' + v[i][0] + '")');
}
}
}
Google Sheet :
https://docs.google.com/spreadsheets/d/12n2Cmu6OqZskD_j7YhVrU14qaQPPGnQyIoSEIw8stqE/edit?usp=sharing
Hope somebody can help me
If I understand your post correctly, you want to create Sub folders named after every row data on column A + Column B inside of your Parent Folder. Then, get each link of the Sub Folders and add each of these links on Column R as HYPERLINKS.
RECOMMENDATION
I have tweaked your current script and you may use this sample script below as reference:
UPDATED
//MAIN SCRIPT TO RUN
function createAndHyperlink() {
var ss, sh, lastRow, name;
ss = SpreadsheetApp.getActive();
sh = ss.getSheetByName('MOC Permanent');
lastRow = sh.getDataRange().getLastRow();
for(var row=2; row<=lastRow; row++){
name = sh.getRange(row,1).getValue()+sh.getRange(row,2).getValue();
if(sh.getRange(row,18).getValue().toString()==""){
sh.getRange(row,18).setFormula('=HYPERLINK('+"\""+createFolder(name).getUrl()+"\",\""+name+"\")");
Logger.log("Created a folder for "+"Name:\n"+name);
}else{
Logger.log("R"+row+" contains a hyperlink already!");
}
}
//THIS CODE BELOW ENSURES THE LAST ROW OF COLUMN R WAS ADDED WITH HYPERLINK BEFORE COPYING FUNCTION BEGINS
if(sh.getRange(lastRow,18).getValue().toString()!=""){
addTempFileCopy();
}
}
//FUNCTION TO CREATE SUB FOLDERS INSIDE THE PARENT FOLDER
function createFolder(folderName){
var parent, folders, firstLevelFolder, newfolder;
parent = DriveApp.getFolderById("PARENT_FOLDER_ID").getName();
folders = DriveApp.getFoldersByName(parent);
firstLevelFolder = (folders.hasNext()) ? folders.next() : DriveApp.createFolder(parent);
//CREATE UNIQUE SUBFOLDERS INSIDE OF THE PARENT FOLDER
newfolder = firstLevelFolder.createFolder(folderName);
return newfolder; //RETURNS THE LINK OF THE CREATED SUBFOLDER
}
//FUNCTION TO ADD THE TEMPLATE FILE INTO EACH CREATED SUB FOLDERS
function addTempFileCopy(){
var parent, subFolder, ss;
ss = SpreadsheetApp.getActive();
parent = DriveApp.getFolderById("PARENT_FOLDER_ID").getFolders();
while(parent.hasNext()) {
subFolder = parent.next();
var destFolder = DriveApp.getFolderById(subFolder.getId());
DriveApp.getFileById(ss.getId()).makeCopy(subFolder.getName()+" - Template file copy", destFolder);
Logger.log("Template file name: "+ss.getName()+"\nAdded to folder: "+subFolder.getName());
}
}
SAMPLE SHEET
RESULT
After running the script, HYPERLINKS were added on the on COLUMN R:
Here are the created Sub folders on Google Drive inside of the Parent folder:
Execution log result:
I need to access the last created subfolder from a parent folder and subfolder's files but i'm failing to do so. Any help in this regard would be highly appreciated.
I'm trying to get files of the last created folder but it gives me an error.
function myFunction() {
// set the folder to pull folder names from
var parentid = "19mrz1uwYVCnmW1XZJYq3";
var parent = DriveApp.getFolderById(parentid);
var parentfolder= parent.getfolders();
var folders = parentfolder.getLastupdated();
var dd = folders.getfiles();
}
I need to excess the last created subfolder and work on it's content to copy somewhere else.
You can find the newest folder with the JS function reduce() and the Apps Script method getDateCreated().
Sample:
function myFunction() {
var parentid = "19mrz1uwYVCnmW1XZJYq3";
var parent = DriveApp.getFolderById(parentid);
var parentfolder= parent.getFolders();
var array=[];
var arrayFolders=[];
while (parentfolder.hasNext()) {
var folders = parentfolder.next();
array.push(folders.getDateCreated());
arrayFolders.push(folders.getId());
}
var date=array.reduce(function (a, b) {
return a > b ? a : b;
});
var index=array.indexOf(date);
var newestFolder=DriveApp.getFolderById(arrayFolders[index]);
var myFiles=newestFolder.getFiles();
}
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());
}
}
I created a script that generates a folder in Google Drive and gets the folder ID of that folder.
Upon trying to access that folder in a unique function I get the error:
no item with the given ID could be found, or you do not have permission to access it on Folder
Please see my script below (called independently from html):
var childFolderIdA;
function doGet() {
return HtmlService.createHtmlOutputFromFile('multifile').setTitle('test – multi upload').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function test(parent,child){
createSharedSubFolder(parent,child);
}
function createSharedSubFolder(parent,child) { // folder names as string parameters
var folders = DriveApp.getFolders();
var exist = false
while (folders.hasNext()) {
var folder = folders.next();
if(folder.getName()==parent){exist = true ; var folderId = folder.getId(); break};// find the existing parent folder
}
if(exist){ //parent folder exists
var child = DriveApp.getFolderById(folderId).createFolder(child).setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT);
var childFolderId = child.getId();
childFolderIdA = childFolderId;
}else{
var childFolder = DriveApp.createFolder(parent).createFolder(child); //create parent and child folders
childFolder.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT);
}
}
function saveFile(data,name,folderName) {
var contentType = data.substring(5,data.indexOf(';'));
var file = Utilities.newBlob(Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)), contentType, name); //does the uploading of the files
DriveApp.getFolderById(childFolderIdA).createFile(file);
}
You can't depend on global variables to save state between calls. Each time you call a script a new script instance is spawned. Each one will maintain its own state.
For example:
google.script.run.createSharedSubFolder(...) --> Script Instance 1..var childFolderIdA=folderId;
google.script.run.saveFile(...) --> Script Instance 2..var childFolderIdA=null;
You can save the the folderId to the users property store:
PropertiesService.getUserProperties().setProperty("childFolderId", childFolderId);
You can retrieve the folder Id:
var folderId = PropertiesService.getUserProperties().getProperty("childFolderId");
Your code with this change:
function doGet() {
return HtmlService.createHtmlOutputFromFile('multifile').setTitle('test – multi upload').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function test(parent,child){
createSharedSubFolder(parent,child);
}
function createSharedSubFolder(parent,child) { // folder names as string parameters
var folders = DriveApp.getFolders();
var exist = false
while (folders.hasNext()) {
var folder = folders.next();
if(folder.getName()==parent){exist = true ; var folderId = folder.getId(); break};// find the existing parent folder
}
if(exist){ //parent folder exists
var child = DriveApp.getFolderById(folderId).createFolder(child).setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT);
var childFolderId = child.getId();
PropertiesService.getUserProperties().setProperty("childFolderId", childFolderId);
}else{
var childFolder = DriveApp.createFolder(parent).createFolder(child); //create parent and child folders
childFolder.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT);
}
}
function saveFile(data,name,folderName) {
var contentType = data.substring(5,data.indexOf(';'));
var file = Utilities.newBlob(Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)), contentType, name); //does the uploading of the files
var childFolderId = PropertiesService.getUserProperties().getProperty("childFolderId");
DriveApp.getFolderById(childFolderId).createFile(file);
}