How to Compare Destination Folders names with specific Single Source folder name? - google-apps-script

Presently, I've been trying to copy the files or folder with files from the source lastcreated folder into the destination folder by comparing the foldername on the basis of the last date created folder. Now I want to compare the source's last date created folder by name with all destination folders, if folder by same name exits than copy the data else create a new folder by same sourcefoldername and copy the contents.
By the help of StackOverflow community, I'm able to compare folder's on basis of last date created and copy the contents but now I want to compare the source last date created foldername with the destination's all folder. If folder by same exits than copy the data in it else it creates a new folder. Attached is the code for getting last date created folder and comparinng with destination folder.
var destSubFolders = destLastFolder.getFolders();
var destSubArray=[];
while(destSubFolders.hasNext()) {
var destSubfolder = destSubFolders.next();
destSubArray.push({
value: destSubfolder.getDateCreated().valueOf(),
sourceFolderId: destSubfolder.getId()
});
}
destSubArray.sort(function(a,b){return b.value-a.value;}); // Comparing between the date created and extracts the last created folder.
var destLastSubFolder=DriveApp.getFolderById(destSubArray[0].sourceFolderId);// gets the last created sub folder by id.
var destinationLastSubFolderFiles= destLastSubFolder.getFiles();//get files of the last created subfolder.
var d_SubName = destLastSubFolder.getName(); // get name of the last created subfolder.
if(s_SubName == d_SubName ) { //condition for comapring source and destination last created subfolder names.
var dfnA=[]; // getting files from source sub folder and copying into destination folder.
while(destinationLastSubFolderFiles.hasNext()) {
var dF=destinationLastSubFolderFiles.next();
dfnA.push(dF.getName());
}
while(sourceLastSubFolderFiles.hasNext()) {
var sF=sourceLastSubFolderFiles.next();
if(dfnA.indexOf(sF.getName())==-1) {
sF.makeCopy(sF.getName(),destLastSubFolder); // copying files after comparing by names.
}
}
} else { //creates new folder by source subfolder name and copies data into new created folder.
var sNewName = lastSubFolder.getName();
var dFolderName=destLastFolder.createFolder(sNewName);
while(sourceLastSubFolderFiles.hasNext()) {
var sFilesIterator=sourceLastSubFolderFiles.next();
sFilesIterator.makeCopy(sFilesIterator.getName(),dFolderName); // copying files after comparing by names.
}
}
I need a comparison of source folder name with destination all folder names and if matches then only copy the contents else create a new folder and contents.

This works for me:
function findSubFolderWithLastDate(startingFolderId) {
var startingFolderId=startingFolderId||'defaultId';
var startFolder=DriveApp.getFolderById(startingFolderId);
var srcFldrs=startFolder.getFolders();
var fldrA=[];
while(srcFldrs.hasNext()) {
var srcFldr=srcFldrs.next();
fldrA.push({value:srcFldr.getLastUpdated().valueOf(),id:srcFldr.getId(),name:srcFldr.getName()})
}
return fldrA.sort(function(a,b){return(b.value-a.value);})[0].id;
}
function copyingFilesFromSourceToDestinationFolderWithSameName(srcfldrId,desfldrId) {
var desFldr=DriveApp.getFolderById(desfldrId);
var srcFldr=DriveApp.getFolderById(srcfldrId);
var srcSubFldrs=srcFldr.getFolders();
while(srcSubFldrs.hasNext()) {
var srcSubFldrFound=false;
var srcSubFldr=srcSubFldrs.next();
var desSubFldrs=desFldr.getFolders();
while(desSubFldrs.hasNext()) {
var desSubFldr=desSubFldrs.next();
if(desSubFldr.getName()==srcSubFldr.getName()) {
srcSubFldrFound=true;
var files=srcSubFldr.getFiles();
while(files.hasNext()) {
var file=files.next();
file.makeCopy(file.getName(),desSubFldr);
}
break;
}
}
if(!srcSubFldrFound) {
var newFldr=desFldr.createFolder(srcSubFldr.getName());
var files=srcSubFldr.getFiles();
while(files.hasNext()) {
var file=files.next();
file.makeCopy(file.getName(),newFldr)
}
}
}
}

Related

how to Create a folder if it does not exist?

I am creating a script to add a folder on all subfolders if the folder is not existing. But unfortunately, I am generating only on one folder. How to make this changes under a parentfolder? Thank you for your answers.
Here is my code:
function folder_create(){
var foldername = 'CHECK FOLDS';
var folders = DriveApp.getFoldersByName(foldername);
var foldersnext = folders.next();
var subfolders = foldersnext.getFolders();
var subfolders = subfolders.next();
var files = subfolders.searchFolders("title contains 'Testing Test'");
{
while(files.hasNext()){
var reportFolderExist = files.next();
var yearFolders = reportFolderExist.getFoldersByName("TESTTT");
if(yearFolders.hasNext()){
} else {
reportFolderExist.createFolder("testing only----");
}
}
}}
Current situation:
If I understand you correctly, this is your current situation:
You have a main folder called CHECK FOLDS.
This main folder contains several subfolders.
For each of these subfolders, you want to check whether they contain a folder whose title contains Testing Test.
If the subfolder doesn't contain a Testing Test folder, create it.
Issue and solution:
If this is correct, the main issue in your code is that you are not iterating through all subfolders, but only accessing the first one var subfolders = subfolders.next();. You should use a loop instead, in order to check each subfolder (see code sample below).
Also, your code contains some confusing parts, like iterating through files (that is Testing Test folders) and looking for folders called TESTTT inside of these files. I don't think this makes sense, if the current situation is the one I described above.
Code sample:
function folder_create(){
var foldername = 'CHECK FOLDS';
var folders = DriveApp.getFoldersByName(foldername);
var foldersnext = folders.next(); // Main folder
var subfolders = foldersnext.getFolders();
while (subfolders.hasNext()) { // Loop through subfolders
var subfolder = subfolders.next(); // Subfolder
var files = subfolder.searchFolders("title contains 'Testing Test'");
if (!files.hasNext()) { // Check if "Testing Test" exists.
subfolder.createFolder("Testing Test"); // Create "Testing Test" folder inside subfolder
}
}
}

Copy files from one folder to another on Drive with Apps Script

Team members upload content (regardless of file type) into a folder on Drive. I need to copy this content into another folder automatically with a trigger, and be able to move it around from there.
I cannot use a "MoveFile" function as I am not the owner of the original content.
I have already tried to copy files automatically into the destination folder, and this works, using the code below:
function CopyFiles() {
var srcFldr = DriveApp.getFolderById("***ID***");
var srcFiles = srcFldr.getFiles();
var desFldr = DriveApp.getFolderById("***ID***");
var desFiles = desFldr.getFiles();
var dfnA = [];
while (desFiles.hasNext()) {
var df = desFiles.next();
dfnA.push(df.getName());
}
while (srcFiles.hasNext()) {
var sf = srcFiles.next();
if (dfnA.indexOf(sf.getName()) == -1) {
sf.makeCopy(sf.getName(), desFldr);
}
}
}
However, I need to move this copied content into other files throughout the day, yet every time I do, the same file gets copied back into the destination folder above with the new trigger, creating a permanent loop.
Is there a way of either:
moving the files from the original source folder despite not being the owner of those files?
copying contents only once, upon upload or modification?
Or 3) another, better, smarter way of doing this?
Thanks for your help!
I'd suggest the following workflow:
For every file that is copied to the destination folder, store the fileId. You could use Properties Service for this.
When copying files from one folder to the other, check the fileId has not been stored before.
Code snippet:
function CopyFiles() {
var srcFldr = DriveApp.getFolderById("***ID***");
var srcFiles = srcFldr.getFiles();
var desFldr = DriveApp.getFolderById("***ID***");
var desFiles = desFldr.getFiles();
var dfnA = [];
var key = "fileIDs";
var scriptProperties = PropertiesService.getScriptProperties();
var property = scriptProperties.getProperty(key); // Retrieve fileIDs property
// Get array of fileId, or empty array if no file has been copied before:
var arrayIDs = property ? JSON.parse(property) : [];
while (desFiles.hasNext()) {
var df = desFiles.next();
dfnA.push(df.getName());
}
while (srcFiles.hasNext()) {
var sf = srcFiles.next();
// Check not only file name, but also whether fileId has been stored before:
if (dfnA.indexOf(sf.getName()) == -1 && arrayIDs.indexOf(sf.getId()) == - 1) {
sf.makeCopy(sf.getName(), desFldr);
arrayIDs.push(sf.getId()); // Add fileId to array of IDs
}
}
scriptProperties.setProperty(key, JSON.stringify(arrayIDs)); // Store updated array
}
Reference:
Properties.getProperty(key)
Properties.setProperty(key, value)

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.

Google Script Question: Is there a way to create copies of files into multiple folders at once?

I have a spreadsheet from which I've written code to populate with the names of folders (column 1) and their IDs (column 2).
I would like to populate each of the folders listed in that spreadsheet with a copy of each of the documents contained a separate folder (a Shared Drive folder, if that matters). When I execute the code below, a copy of each document is created in the source folder (the Shared Drive folder) instead of in the destination folder (aka the folders whose IDs are captured in the spreadsheet). If it matters, each copy is labelled with a folderID from the spreadsheet. Can someone please tell me how I can get this code to create the copies inside the appropriate destination folders instead of in the source folder?
function CopiestoFolder() {
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 NAME = 0;
var FOLDERID = 1;
//For each folder ID listed in spreadsheet, create a copy of
//each item in the Resume Resources folder.
for (var i = 0; i < data.length; i++) {
var name = data[i][NAME];
var folderId = data[i][FOLDERID];
var srcFolder = DriveApp.getFolderById("folder ID");
var dstFolder = folderId;
var files = srcFolder.getFiles();
while (files.hasNext()) {
var file = files.next();
var f = file.makeCopy(dstFolder);
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
dstFolder.addFile(file);
f.getParents().next().removeFile(file);
}
}
}
}
I had this problem with Script Files. Here's how I fixed. Or I should say here's how Tanaike fixed it. You will need to enable Drive API.
var res=file.makeCopy(copyName,subFldr);
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
Drive.Files.update({"parents": [{"id": subFldr.getId()}]}, res.getId(), null, {"supportsTeamDrives":true}); // Added
}
The file.makeCopy() method has 3 overloads:
//Accepts no parameters
file.makeCopy();
//Accepts a name parameter as a string
file.makeCopy(name);
//Accepts a destination parameter as an instance of a Folder class
file.makeCopy(destination);
//Accepts 2 parameters, the first of which is name (String) and the second one is destination (Folder).
file.makeCopy(name, destination);
You are trying to pass folder id instead of the actual folder, which gets interpreted as a folder name (not destination). Also, the following code means that your 'dstFolder' parameter is a string but you try to call the 'addFile()' method on it:
var folderId = data[i][FOLDERID];
var dstFolder = folderId;
dstFolder.addFile(file);
If you want to copy a file to another folder via makeCopy, you should pass a Folder as a parameter, not a folder id (a string). If you provide a string (your id) as a parameter, the script will interpret this id as the name you want the copied file to have. So you should first get the Folder out of its id, via getFolderById(id). So you should change this line:
var dstFolder = folderId;
To this one:
var dstFolder = DriveApp.getFolderById(folderId);
You are making a copy of the file before checking if the file is a Google Apps Script project. I assume you just want GAS projects to be copied, so this should be included inside the if block. Also, inside the if block you are using addFile which can also be used to copy a file to another folder (it adds the file to the desired folder). So you don't need to use both functions, they are doing basically the same (copying your file to the desired folder).
You are using removeFile, which is not necessary if you want to keep the original files in the original folders.
So the while block could be something like:
while (files.hasNext()) {
var file = files.next();
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
dstFolder.addFile(file);
}
}
Finally, your full code could be like:
function CopiestoFolder() {
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 NAME = 0;
var FOLDERID = 1;
//For each folder ID listed in spreadsheet, create a copy of
//each item in the Resume Resources folder.
for (var i=0; i<data.length; i++) {
var name = data[i][NAME];
var folderId = data[i][FOLDERID];
var srcFolder = DriveApp.getFolderById("folder ID");
var dstFolder = DriveApp.getFolderById(folderId);
var files = srcFolder.getFiles();
while (files.hasNext()) {
var file = files.next();
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
dstFolder.addFile(file);
}
}
}
}
I hope this is of any help.

Do not make copy of existing file in destination folder

I've been trying to copy contents from one folder to another folder in google drive using google app script. With some online help and documentation of google script, I was able to copy files from one folder to other but it copies all files from source folder to destination folder on time trigger, but I want only the new files to get copied in my destination folder and skip the present files that are already same in my source and destination folder.
I tried to check files by name before copying but couldn't find a way to compare files by name in two different folders of gdrive.
function CopyFiles() {
var SourceFolder = DriveApp.getFolderById('Sid');
var SourceFiles = DriveApp.getFolderById('Sid').getFiles();
var DestFolder = DriveApp.getFolderById('Did');
var DestFiles = DriveApp.getFolderById('Did').getFiles();
while (SourceFiles.hasNext())
{
var files = SourceFiles.next();
var dfiles = DestFiles.next();
if ( files == dfiles){
file.setTrashed(true);}
else{
var f = files.makeCopy(DestFolder);
}
}
}
What I want to achieve is that Script compares files by name in destination folder and if files by that name already exist than skip else, create a copy of that new file in the destination folder.
Copies files from source to destination if destination does have the same file names
In this version no files get trashed.
function CopyFiles() {
var srcFldr=DriveApp.getFolderById('srcId');
var srcFiles=srcFldr.getFiles();
var desFldr=DriveApp.getFolderById('desId');
var desFiles=desFldr.getFiles();
var dfnA=[];
while(desFiles.hasNext()) {
var df=desFiles.next();
dfnA.push(df.getName());
}
while(srcFiles.hasNext()) {
var sf=srcFiles.next();
if(dfnA.indexOf(sf.getName())==-1) {
sf.makeCopy(sf.getName(),desFldr);
}
}
}