naming a file on Google drive using a cell in spreadsheet - google-apps-script

I have made a Google form that uploads a file. I want to automatically change the name of the file by using an entry from the form, or a cell content in the spreadsheet. Is this possible?

Changing the names of uploaded file using onFormSubmit event
Put this in the spreadsheet with the linked sheet for your form
function onFormSubmit(e) {
var ft=e.values.slice(1);//this removes the timestamp
var fA=ft[0].split(',');//this splits the file url's into an array
for(var i=0;i<fA.length;i++) {
var file=DriveApp.getFileById(fA[i].slice(fA[i].indexOf("=")+1));//get file by id by getting the id from the file.
var t=Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "HHmmss"); //add the date to the filename
file.setName(Utilities.formatString('FileName-%s',t));//set the filename
Utilities.sleep(2000);//I added this to insure that the filenames would bee different.
}
}
My form looks like:
The first column is a timestamp and the second column are the urls of the uploaded files in a comma delimited string.
The files folder is loaded into a sub folder of the folder where the form was created that folder was named Form Title + " (File Responses)" and the files folder is named Question Name + " (File Responses)".
onFormSubmit Event Object

Related

How to read file names of items in a Zipped Folder? Google App Script

I am attempting to read the names of files within a zipped folder on Google Drive.
From there I will create new folders using a trimmed portion of the file name.
My below codes works, however the way I am reading the filename is to unzip it first, copy it to a temp location and read the filename. This function runs pretty slowly, my zipped file has 800+ files. Each one with a unique filename.
The code below first checks in the folder destination if a folder with yesterdays date as the title exists, if not it creates one. Then it checks a set folder for a zip file who's title contains yesterdays date. After finding it, it will loop through the zip file and extract each file within (jpegs) save them to a folder 'Temp' and retrieve a substring of the name. Then it checks the appropriate date folder to see if it has any folders that exist with the filename substring, if not it creates a new folder.
function CreateNewImageFolder() {
const optionalArgs={supportsAllDrives: true}; // enables support for shared drive
const timezone = Session.getScriptTimeZone(); // returns script timezone
const afId = 'archivefolderID' // Image Drive "Image_Archive" Folder ID
const aDest = DriveApp.getFolderById(afId); // returns 'Archive source' folder "Image_Archive"
const op20Id = 'fixedfolderW/allfilenames' // Image Drive "Folder that contains all possible filenames" Folder ID
const op20 = DriveApp.getFolderById(op20Id); // returns OP20 folder
const tId = 'tempfolderID' // Image Drive "temp" Folder ID
const temp = DriveApp.getFolderById(tId); // returns OP20 folder "temp"
var yday = Utilities.formatDate(GetYesterday(1), timezone, "MM-dd"); // returns yesterdays date for file name search
var yyear = Utilities.formatDate(GetYesterday(1), timezone, "yyyy-MM-dd"); // returns yesterdays date + year for folder name search
Logger.log("Yesterday: %s", yday);
//// Checks for existing Date Folder and creates a new one if not exist ///
var datefold = aDest.searchFolders("title contains '"+yyear+"'"); // search aDest for existing date folder
if (datefold.hasNext()===true) {
while (datefold.hasNext()) {
var dfolder = datefold.next();
Logger.log("Folder %s already exists", dfolder.getName());
}
} else{
var dfolder=aDest.createFolder(yyear); // if not exist create new folder in aDest
Logger.log("New Date Folder Name: %s", dfolder.getName());
}
var dfoldId = dfolder.getId();
var vDest = DriveApp.getFolderById(dfoldId);
Logger.log("New Folder Destination: %s", vDest.getName());
//// loops through ZIP file iterator ////
var zfi = op20.searchFiles("title contains '"+yday+"'"); // search op20 folder for Yesterdays Zip File 'file iterator'
while (zfi.hasNext()){ // loops through ZIP file iterator
var file = zfi.next(); // every loop sets active file to next
Logger.log("Zip Folder: %s", file.getName());
var fileBlob = file.getBlob(); // get file blob
fileBlob.setContentType("application/zip");
var unZippedfile = Utilities.unzip(fileBlob); // unzipped file iterator
//// loops all blob elements ////
for (i=0; i<unZippedfile.length; i++) {
var uzf = temp.createFile(unZippedfile[i]); // creates upzipped file in "temp" folder
var fileName = uzf.getName().substring(0, 17); // trims Image name string to first 17 characters
Logger.log("unzipped File Name: %s", fileName);
//// Checks for existing Folder and creates a new one if not exist ////
var vfold = vDest.searchFolders("title contains '"+fileName+"'"); // search vDest for existing folder
if (vfold.hasNext()===true) {
while (vfold.hasNext()) {
var vfolder = vfold.next();
Logger.log("Folder %s already exists", vfolder.getName());
}
} else{
var vfolder=vDest.createFolder(fileName); // if not exist create new folder in aDest
Logger.log("New Folder Name: %s", vfolder.getName());
}
uzf.setTrashed(true);
}
}
}
Simple Example
Zipped Folder Located at:
Root > Image_Archive > Station > Camera > Date > 'zippedfolderName_2022_10_23'
zipped folder contains several image files all starting with unique 17 character #. ex: 1ABCXXXXXXXXXXXX1
Desired Output
Root > Image_Archive > New_Folder (named with yesterdays date) > New_Folder (named using 17 character # ex: 1ABCXXXXXXXXXXXX1)
Listing ZIP files from Google Drive
After reviewing all documentation regarding Drive and how the apps script function, you would always need to unzip it in order to be able to view the data and files from Drive.
Being able to manually view or list a zip file and gather the data is not possible. This could be considered a missing feature or just a limitation in general on how it works. You might request a better clarification over here:
https://issuetracker.google.com/issues/new?component=191650&template=824106
Sadly it seems that Drive API is limited in a way that would require the unzip process as discussed directly in the community:
Google Script - How to use unzip
References
https://developers.google.com/apps-script/reference/utilities/utilities#unzip(BlobSource)
Is it possible to use the Google Drive API to get file from within a shared .zip file

Script to download several columns of a Google Sheets Tab into separate text files

I would like to create a script, to be executed in a Google Sheets environment, that grabs all the contents of several columns within a specific tab, stacks the contents of each columns into a specific text file, and names the file after the header of each column.
For instance:
The working tab would be"Text_Files".
It has several columns, for instance, 3, but there could be more: A:A, B:B and C:C.
The value of the header for column A:A (cell A1) is "1". (Same as the column number)
The value of the header for column B:B is "2".
The value of the header for column C:C is "3".
Then, the script should grab the contents of cells A2:A, stack them into a text file, name the file "1.jsx", do the same for range B2:B, name this file "2.jsx" and for range C2:C name the file "3.jsx". (If there were more columns in the tab, the script should run until the very last column).
After having gathered all the data, it should pop up the dialog box asking the folder where to save all the .jsx files, in a similar ways as when we use the Pdf download option in he menu.
That's it.
Thanks so much.
It can be done this way:
function save_columns_into_files() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var folder = DriveApp.getFolderById('###');
for (var column in data[0]) {
var file_name = data[0][column];
var file_body = data.slice(1).map(x => x[column]).join('\n')
var txt_file = DriveApp.createFile(file_name + '.jsx', file_body, MimeType.PLAIN_TEXT);
var pdf_file = DriveApp.createFile(file_name + '.pdf', file_body, MimeType.PDF);
txt_file.moveTo(folder);
pdf_file.moveTo(folder);
SpreadsheetApp.getUi().alert('Files saved in folder ' + folder.getName());
}
}
No dialog box, though. Folder ID is wired in the script.
Add a proper dialog to select folders is a rather tricky task. Here is the official example: https://developers.google.com/apps-script/guides/dialogs#dialog.html
As a simpler variant it can be just a prompt dialog with text input area where you should type a name of desired output folder every time you run the script (keep in mind, Drive can have many folders with the same name, so there can be collisions). Let me know if you really need it.

Google Forms Rename "File upload" File to "Question - Submitter"

I am using Google Forms to collect images from team members and I want to ensure that each file that is uploaded to Google Forms and saved in Google Drive has the same naming convention.
There are five File upload questions that team members are asked to upload their images to. The files are placed into Google Drive folders with random file names followed by - firstName lastName. On an onFormSubmit trigger I would like to change the names of the user-provided files to fileUploadQuestionName - firstName lastName.
I am pretty new to Google Apps Script and I have no idea how to go about doing this. Any help would be greatly appreciated!
You can change the name of the uploaded file on each form submit by the following process
retrieve the last form response onFormSubmit with form.getResponses()[LAST FORM SUBMISSION]
retrieve the ID of the uploaded file with getItemResponses()[QUESTION NUMBER].getResponse()
open the file ID with DriveApp and change its name as desired
function myFunction() {
var form=FormApp.getActiveForm();
// returns the total number of form submissions
var length=form.getResponses().length;
//replace QUESTION NUMBER through the index of the question prompting the file upload - keep in mind that the first question has the index 0
var id=form.getResponses()[length-1].getItemResponses()[QUESTION NUMBER].getResponse();
//getResponses()[length-1] retrieves the last form response, accounting for the fact that the first index is zero and hte last length-1
//gets the name of the question
var fileUploadQuestionName=form.getResponses()[length-1].getItemResponses()[QUESTION NUMBER].getItem().getTitle();
//accesses the uploaded file
var file=DriveApp.getFileById(id);
name = file.getName();
//changes the file name
var name = fileUploadQuestionName+' - '+name.split(' - ')[1]
file.setName(name);
}
PS: If you want to change a posteriori the names of all the files submitted and not just the last files - you need to loop through all form responses:
for(var i=0;i<length;i++){
var id=form.getResponses()[i].getItemResponses()[QUESTION NUMBER].getResponse();
...
...
}
The easiest way to do this would likely be by either iterating through the specified folder in google drive on a time-based trigger and either checking if they meet your specified condition or moving them to a different folder after they're renamed.
function checkFile()
{
var files = DriveApp.getFolderById('ID of Folder').getFiles();
// you can find this by going to form responses and clicking the link to an attached file and copying the id from the URL
// https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxxxxxxxxxxx
var fileUploadQuestionName = 'Test';
while(files.hasNext())
{
var file = files.next();
var name = file.getName();
if(name.indexOf(fileUploadQuestionName) == -1)
{
name = fileUploadQuestionName+' - '+name.split('-')[1]
file.setName(name);
}
}
}
From there you'll need to add a time-based trigger to run every hour or day or minute depending on how critical it is to always find files of the correct name.
I can't find any documentation on accessing the file from within the response item on google's formApp documentation.

Google Apps script to automate copies of Google Slides document

I'm trying to get a Google Apps script set up to automate saving of copies of a Google Slides document into a Drive folder each week. I realise that Slides is always backed up but I want to save a weekly copy of a constantly evolving document for reference.
Here's the script I'm trying to run:
function makeCopy() {
var timeZone = Session.getScriptTimeZone();
// generates the timestamp and stores in variable formattedDate as
// year-month-date hour-minute-second
var formattedDate = Utilities.formatDate(new Date(), timeZone , "yyyy-MM-dd' 'HH:mm:ss");
// gets the name of the original file and appends the word "copy"
// followed by the timestamp stored in formattedDate
var name = DocumentApp.getActiveDocument().getName() + " Copy " + formattedDate;
// gets the destination folder by their ID. REPLACE
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx with your folder's ID
// that you can get by opening the folder in Google Drive
// and checking the URL in the browser's address bar
var destination = DriveApp.getFolderById("MyFolderID");
// gets the current Google Sheet file
var file = DriveApp.getFileById(DocumentApp.getActiveDocument().getId())
// makes copy of "file" with "name" at the "destination"
file.makeCopy(name, destination);
}
Any ideas where I'm going wrong?
You use DocumentApp which is for Google Docs, not slides. Instead, it should be SlidesApp.getActivePresentation().
Instead of hard-coding the folder ID, you can also use DriveApp to get the current file folder if you want to keep them together by using .getId() and .getFileById() followed by .getParents(). Although if you want to keep the copies in a separate folder then ignore this.

using a variable in searchFiles Google script

I have a third party program that pulls daily data into CSV files with the filename starting with the date it ran e.g. 17072017filename.csv
I need a seperate spreadsheet that will take a date input from the user, which will then search through the files in drive until it matches the date on the CSV file. Once i find the file i want i can then use getFileID() and getRange() to copy various values from that CSV file.
This is what i have at the moment (where cell A2 in the spreadsheet is where the user can type the date they want e.g. 17072017).
Issue seems to be that i can't pass the date (which will change everyday) as a variable in searchFiles(). Is this even possible?
This is what i have so far
function myfunction()
{
var inputDate = SpreadsheetApp.getActiveSheet().getRange("A2").getValue();
var files = DriveApp.searchFiles('title contains 'inputDate'');
while (files.hasNext())
{
var file = files.next();
Logger.log(file.getName());
}
}
How about a following modification?
From :
var files = DriveApp.searchFiles('title contains 'inputDate'');
To :
var files = DriveApp.searchFiles("title contains '" + inputDate + "'");
If I misunderstand your question, I'm sorry.