Google Form Upload to New Folder - google-apps-script

I have a form with a number of questions including first name, last name and several questions that require the user to upload a document. My goal is that when the user submits the form that a new folder will be created, a suffix added if there is already a folder with the same name and all of the files uploaded go into the new folder for that user. Thanks to the solution posted by Tanaike “here” and with more modifications from Tanaike "here", the form works in completing the new folder however there are 2 elements I’m trying to figure out;
How do I move all uploads from the submission? Currently only the first upload question moves to the new folder.
Our folder names are usually, “lastname, firstname”. I can change the form for the user to enter their name like this but it seems like figuring out how to combine the name fields would be the better solution ie. Last Name+”, “+First Name
function onFormSubmit1(e) {
const folderId = "1fOttSZooEA-dK8ee7COzRtrjVQhzh2Yv"; // Please set top folder ID of the destination folders.
const form = FormApp.getActiveForm();
const formResponses = form.getResponses();
const itemResponses = formResponses[formResponses.length-1].getItemResponses();
Utilities.sleep(3000); // This line might not be required.
// Prepare the folder.
const destFolder = DriveApp.getFolderById(folderId);
let folderName = itemResponses[0].getResponse();
const subFolder = destFolder.searchFolders("title contains '" + folderName + "'");
const reg = new RegExp(`^${folderName}$|^${folderName}_\\d{2}$`);
if (subFolder.hasNext()) {
const folderNames = {};
while (subFolder.hasNext()) {
const fol = subFolder.next();
const fName = fol.getName();
if (reg.test(fName)) folderNames[fName] = fol;
}
const len = Object.keys(folderNames).length;
if (len == 1 && folderNames[folderName]) {
folderNames[folderName].setName(folderName + "_01");
}
folderName += "_" + ("00" + (len + 1)).slice(-2);
}
const folder = destFolder.createFolder(folderName);
// Move files to the folder.
itemResponses[1].getResponse().forEach(id => DriveApp.getFileById(id).moveTo(folder));
}

Related

when uploading google forms files to a custom folder only one file uploads

I m using a code found here
My goal, which is half way accomplished, is as follows:
Create a sub folder based on respondent answer [done]
Add all files in the form to said sub folder [so far is adding only one file of multiples that I request under the form]
rename each file according to the type of file requested under question, and if multiple files under the same question are uploaded add, i.e.: "phototest" "phototest1"
function onFormSubmit(e) {
const folderId = "1gvlYEr-CJwFVNZVipNkVNV3ussNvgfhR"; // Please set top folder ID of the destination folders.
const form = FormApp.getActiveForm();
const formResponses = form.getResponses();
const itemResponses = formResponses[formResponses.length-1].getItemResponses();
Utilities.sleep(3000); // This line might not be required.
// Prepare the folder.
const destFolder = DriveApp.getFolderById(folderId);
const folderName = itemResponses[0].getResponse();
const subFolder = destFolder.getFoldersByName(folderName);
const folder = subFolder.hasNext() ? subFolder.next() : destFolder.createFolder(folderName);
// Move files to the folder.
itemResponses[2].getResponse().forEach(id => DriveApp.getFileById(id).moveTo(folder));
}

Upload file using a form. Moving a file to a specific folder issue

High School teacher here with hardly any experience in GAS or Javascript. Using a google form to have students upload a file(s). The file gets moved to an assignment folder in a period folder based off what the student enters. The file should get renamed so that it has the student's name in Last First name order at the beginning of the file.
All of that is working! BUT for some reason it is giving me two versions of the file! One in the correct place, but another one in the root directory of my Google Form. What is wrong with my code?
function myFunction2() {
const folderId = ""; // I deleted the ID since I don\'t know if there is any privacy issues
const form = FormApp.getActiveForm(); //gets the form
const formResponses = form.getResponses(); //gets all the responses
const itemResponses = formResponses[formResponses.length-1].getItemResponses(); //gets the last response
// Prepare the folder names
const rootFolder = DriveApp.getFolderById(folderId); //root folder
const periodName = itemResponses[1].getResponse(); //period name
const assignmentName = itemResponses[2].getResponse(); //assignment name
// Checks to see if the period folder exists
const periodIterator = rootFolder.getFoldersByName(periodName); //Folder iterator
const periodFolder = periodIterator.hasNext() ? periodIterator.next() : rootFolder.createFolder(periodName); //does the period Folder exist?
// Checks to see if the assignment folder in the period exists
const assignmentIterator = periodFolder.getFoldersByName(assignmentName); //Assignment iterator
const assignmentFolder = assignmentIterator.hasNext() ? assignmentIterator.next() : periodFolder.createFolder(assignmentName);//does the assignment folder exist
// Puts all files in the Period/Assignment folder
// Renames files so that it has Last Name, First Name order at beginning of the name
files = itemResponses[3].getResponse();
if (files.length > 0) {
for (var n in files) {
var dFile = DriveApp.getFileById(files[n]);
var fullFileName = dFile.getName();
var firstPart = fullFileName.substring(0, fullFileName.lastIndexOf("-")-1);
var namePart = fullFileName.substring(fullFileName.lastIndexOf("-")+2, fullFileName.lastIndexOf("."));
var firstName = namePart.substring(0,namePart.indexOf(" "));
var lastName = namePart.substring(namePart.indexOf(" ")+1);
var flippedName = lastName+", "+firstName;
dFile.setName(flippedName+" - "+ firstPart); //Rename the file
dFile.moveTo(assignmentFolder); //Move the file
}
}
}

Google App Script to copy and rename folder structure, including updating fields within a doc and sheet contained within the folders?

I must first apologise as I've never done any coding before. I've been doing a lot of googling and looking at other peoples codes to try and work out whats going on. I have the logic, but I don't know all the classes, triggers or even the right terminology! I can map out in my mind what needs to happen but need to learn the language first, so hoping you can point me in the right direction for learning materials, and help with this particular project.
I would like to automate something that we do a lot in our office, which is creating a new customer folder containing pre-defined sub-folders, and taking a template doc and sheet, filling out name and address fields, and saving them with the customer name appended with the doc or sheet name into relevant newly copied/created folders. I'm struggling to coherently explain this, so I've drawn something which will hopefully help:
sketch of folder structure with doc and sheet location
I've made a Google Form that posts results to a spreadsheet, and I've put a script in that sheet. I've worked out how to take a template sheet and doc, copy and rename them into a folder, but can't figure out what I need to do with the folders so they can be filed into unique places on drive.
Here is the code that I'm testing to copy the templates, add fields and rename and save:
function autoFillGoogleDocFromForm(e) {
var timestamp = e.values[0];
var title = e.values[1];
var firstName = e.values[2];
var lastName = e.values[3];
var emailAddress = e.values[4];
var premisesType = e.values[6];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('1QjYas1erxtQjLPduNMoY1EIEAjBOI5qbAMeX59qPib4');
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById('18GWERZFqgf9TbPfKDRX8gK02kbKpRLch')
var copy = file.makeCopy(lastName + ', ' + firstName, folder);
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
var header = doc.getHeader();
//Then we call all of our replaceText methods
header.replaceText('{{Premises type}}', premisesType);
body.replaceText('{{First Name}}', firstName);
body.replaceText('{{Surname}}', lastName);
body.replaceText('{{Salutation}}', title);
body.replaceText('{{email}}', emailAddress);
body.replaceText('{{Premises type}}', premisesType);
//Lastly we save and close the document to persist our changes
doc.saveAndClose(); }
// REPLICATE ABOVE WITH SHEETS, fills out cell G2 with test info
function autoFillGoogleSheetFromForm(e) {
var timestamp = e.values[0];
var title = e.values[1];
var firstName = e.values[2];
var lastName = e.values[3];
var emailAddress = e.values[4];
var premisesType = e.values[6];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('1yvOtPcnGMQnE7Hc0d6vVMSG2Q5nY9u-MijaDZ51jlOU');
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById('18GWERZFqgf9TbPfKDRX8gK02kbKpRLch')
var copy = file.makeCopy(lastName + ', ' + firstName, folder);
//Once we've got the new file created, we need to open it as a document by using its ID
var ss = SpreadsheetApp.openById(copy.getId());
// ss is now the spreadsheet the script is associated with
var sheet = ss.getSheets()[0];
// sheets are counted starting from 0
// sheet is the first worksheet in the spreadsheet
var cell = sheet.getRange("G2");
cell.setValue(premisesType);
}
Hoping in anticipation someone can help without flaming me. I'm embarrassed enough posting this! I promise I am trying to learn and not going for the easy option!
Vince.
Edit: thanks to #iansedano I've almagamted some code which gets me whaere I need to be, except on some occasions I have the folder structer created multiple times, as though the smae form has been resubmitted several times. Here is the code I am now testing:
function autoCreateFoldersSheetDoc(e) {
var title = e.values[1];
var firstName = e.values[2];
var lastName = e.values[3];
var emailAddress = e.values[4];
var premisesType = e.values[6];
// This is the root directory where all the client folders would be stored
const customerRoot = DriveApp.getFolderById('1s4fD0wk8Mj_YiCkEOj7hUZedOv_AyPdl');
const mainFolder = customerRoot.createFolder(lastName + ', ' + firstName);
// Creating the sub folders
// Some are assigned to variables so that later children can be added
mainFolder.createFolder("1. Customer Correspondence")
const costsFolder = mainFolder.createFolder("2. Costs")
const proposalsFolder = mainFolder.createFolder("3. Proposals")
mainFolder.createFolder("4. Drawings")
mainFolder.createFolder("5. Testing & Commissioning")
// Creating children
costsFolder.createFolder("1. Suppliers")
const dcaFolder = costsFolder.createFolder("2. DCA")
// Take the template proposal doc and save a copy to the proposals folder
var fileA = DriveApp.getFileById('1QjYas1erxtQjLPduNMoY1EIEAjBOI5qbAMeX59qPib4');
var copyA = fileA.makeCopy(lastName + ', ' + firstName, proposalsFolder);
// Open new proposal doc and replace text
var doc = DocumentApp.openById(copyA.getId());
var body = doc.getBody();
var header = doc.getHeader();
header.replaceText('{{Premises type}}', premisesType);
body.replaceText('{{First Name}}', firstName);
body.replaceText('{{Surname}}', lastName);
body.replaceText('{{Salutation}}', title);
body.replaceText('{{email}}', emailAddress);
body.replaceText('{{Premises type}}', premisesType);
doc.saveAndClose();
// Take the template costs sheet and save a copy to the DCA folder
var fileB = DriveApp.getFileById('1yvOtPcnGMQnE7Hc0d6vVMSG2Q5nY9u-MijaDZ51jlOU');
var copyB = fileB.makeCopy(lastName + ', ' + firstName, dcaFolder);
// Open new costs sheet and replace text
var ss = SpreadsheetApp.openById(copyB.getId());
var sheet = ss.getSheets()[0];
var cellA = sheet.getRange("G2");
var cellB = sheet.getRange("H5");
var cellC = sheet.getRange("H6");
var cellD = sheet.getRange("H4");
var cellE = sheet.getRange("I2");
cellA.setValue(premisesType);
cellB.setValue(firstName);
cellC.setValue(lastName);
cellD.setValue(title);
cellE.setValue(emailAddress);
}
Any ideas how I can prevent the duplicates?
Sample function
/**
* This function takes three arguments, the client name,
* the costing sheet id, and the proposal doc id.
* It will then create the folders and place the documents in the
* right place, wherever they are in drive.
*/
function createClientAccountFolder(clientName, costingSheetId, ProposalDocId) {
// This is the root directory where all the client folders would be stored
const customerRoot = DriveApp.getFolderById('[YOUR_ROOT_FOLDER_ID]');
if (clientName) {
// This creates the main folder with the customer name
const mainFolder = customerRoot.createFolder(clientName);
// Creating the sub folders
// Some are assigned to variables so that later children can be added
mainFolder.createFolder("1. Customer Correspondence")
const costsFolder = mainFolder.createFolder("2. Costs")
const proposalsFolder = mainFolder.createFolder("3. Proposals")
mainFolder.createFolder("4. Drawings")
mainFolder.createFolder("4. Testing & Commissioning")
// Creating children
costsFolder.createFolder("1. Suppliers")
const dcaFolder = costsFolder.createFolder("2. DCA")
// Getting the documents
const costingSheet = DriveApp.getFileById(costingSheetId)
const proposalDoc = DriveApp.getFileById(ProposalDocId)
// Moving the documents to the respective folders
costingSheet.moveTo(dcaFolder)
proposalDoc.moveTo(proposalsFolder)
} else {
Logger.log('No Client Name Specified')
}
}
function test(){
createClientAccountFolder("John Smith", "[SHEET_ID]", "[DOC_ID]")
}
I was not sure how exactly to integrate it into your other script, since I don't have the data to be able to test it. Though, as a suggestion, you might add a line to the end of the functions autoFillGoogleDocFromForm and autoFillGoogleSheetFromForm.
return id
You would need to get the id of the documents first, and assign it to an id variable. Be sure to assign it as a string if you want to use the function above without any changes.
So all you would need to do is call all the functions from a main functions like this:
function main(){
const clientName = "John Smith"
const docId = autoFillGoogleDocFromForm()
const sheetId = autoFillGoogleSheetFromForm()
createClientAccountFolder(clientName, sheetId, docId)
}
You might also want a way to get the clientName in a different way, so this could all be automated easier. Though hopefully you get an idea of the kind of thing that would need to be done and you can modify it to your needs.
Let me know if anything is unclear!
References
createFolder(name)
getFolderById(id)
getFileById(id)
moveTo(destination)

How to automatically rename folder based on uploaded file if there are duplicated folder name Google Form

This is the next episode of my previous question (which was solved): Google Form Upload files to specific new folder based on the value submitted
SO, I succeeded to create a new folder on Google Drive based on value inputted by user in field NAME using this script.
function onFormSubmit(e) {
const folderId = "###"; // Please set top folder ID of the destination folders.
const form = FormApp.getActiveForm();
const formResponses = form.getResponses();
const itemResponses = formResponses[formResponses.length-1].getItemResponses();
Utilities.sleep(3000); // This line might not be required.
// Prepare the folder.
const destFolder = DriveApp.getFolderById(folderId);
const folderName = itemResponses[0].getResponse();
const subFolder = destFolder.getFoldersByName(folderName);
const folder = subFolder.hasNext() ? subFolder : destFolder.createFolder(folderName);
// Move files to the folder.
itemResponses[1].getResponse().forEach(id => DriveApp.getFileById(id).moveTo(folder));
}
The problem is when there are 2 or more person with the same NAME uploaded a file it will fail to create the folder. And put the files on the root folder instead.
What I need is to add suffix on the folder name. Let's say there are 3 person with NAME = noobsee. SO, the folder should be:
noobsee_01
noobsee_02
noobsee_03
How to do it?
I believe your goal as follows.
When the folder name of value of Name is existing, you want to create new folder by adding the suffix.
As a sample situation, when the folder name of sample is existing and Name of sample is submitted, you want to rename the existing folder name to sample_01 and want to create new folder with the folder name of sample_02.
In your situation, the script is put in the container-bound script of Google Form. And onFormSubmit has been installed as the installable trigger of OnSubmit trigger.
In this case, I would like to propose to modify the script of "Prepare the folder." as follows.
Modified script:
From:
// Prepare the folder.
const destFolder = DriveApp.getFolderById(folderId);
const folderName = itemResponses[0].getResponse();
const subFolder = destFolder.getFoldersByName(folderName);
const folder = subFolder.hasNext() ? subFolder : destFolder.createFolder(folderName);
To:
// Prepare the folder.
const destFolder = DriveApp.getFolderById(folderId);
let folderName = itemResponses[0].getResponse();
const subFolder = destFolder.searchFolders("title contains '" + folderName + "'");
const reg = new RegExp(`^${folderName}$|^${folderName}_\\d{2}$`);
if (subFolder.hasNext()) {
const folderNames = {};
while (subFolder.hasNext()) {
const fol = subFolder.next();
const fName = fol.getName();
if (reg.test(fName)) folderNames[fName] = fol;
}
const len = Object.keys(folderNames).length;
if (len == 1 && folderNames[folderName]) {
folderNames[folderName].setName(folderName + "_01");
}
folderName += "_" + ("00" + (len + 1)).slice(-2);
}
const folder = destFolder.createFolder(folderName);
In this case, only when the same value of Name is submitted, the suffix is added.
From your question, it supposes that the number of digits of suffix is 2 like _01, _02,,,.

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());
}
}