How update Google form display after changing file name with script - google-apps-script

I'm using a Google form with multiples subpart (Multiple choices, Short answer...) and one upload file box.
When I upload a file, the name of the logged user is added into the file name. I don't want this.
So I use a Google script to change their name, it's ok in the folder directory (the file names are correctly updated), but in the Google form display ("Responses" section), there is always the old names.
How can I force the refresh of the Form display ?
Here is my script :
function myFunction() {
var existingForm = FormApp.getActiveForm();
var formResponses = existingForm.getResponses();
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
var title = itemResponse.getItem().getTitle();
var files = itemResponse.getResponse();
for (var n in files) {
var my_file = files[n];
var dFile = DriveApp.getFileById(my_file);
var dFileName = dFile.getName();
dFile.setName("New name " + n);
}
}
}
}
Thanks for your help

Upon checking the available methods and Form Settings, there is no way to change the file names under Responses even if the actual file in the directory/folder is already renamed.
Even the Forms UI doesn't provide any way of renaming the uploaded file name under Responses so it is highly unlikely to be supported in Apps Script as well.

Related

Most efficient way to traverse Gmail attachments and download to Google Drive?

Using Google Apps Script, is there a more efficient way to traverse my Gmail - picking out 'non-starred' emails that have a particular label assigned to them and then download the attachments to Google Drive?
My code works, but typically 'times out' after processing about 25 image attachments (using non-paid Gmail account)
The piece of code that does the work is as follows:
// Loop through the messages for each thread
for (var i = 0 ; i < messages.length; i++) {
for (var j = 0; j < messages[i].length; j++) {
var CurrentMsg = messages[i][j];
if (!CurrentMsg.isStarred()){
var att = CurrentMsg.getAttachments();
// If there were no attachments, create a 'dummy text file' to notify the user that there were no attachments for that email.
var MsgSubject = CurrentMsg.getSubject();
if (att.length == 0){
var file = folder.createFile(MsgSubject,'There were no attachments',MimeType.PLAIN_TEXT);
}
else{
for (var k = 0; k < att.length; k++){
var file = folder.createFile(att[k].copyBlob().getAs('image/jpeg').setName(MsgSubject));
}
}
CurrentMsg.star();
}
}
}
Any tips gratefully received!
If you want to look through certain emails only, like those that are not starred in your case, consider using the search() method. This will help you avoid looping over threads and messages you don't need.
If you need to bypass your maximum execution time, check out this answer and this article (also linked in the answer).
I would recommend limiting results via a query then using the foreach function to go through messages:
// limit the list of messages to iterate through
var query = 'has:attachment label:particular';
var results = Gmail.Users.Messages.list(userId, {q: query});
results.messages.forEach(function (m) {
var msg = GmailApp.getMessageById(m.id);
msg.getAttachments().forEach(function (a) {
var fileName = a.getName();
fileName = saveAttachmentToFolder(folder, a, fileName, msg.getDate(), input.tz);
});
});
The code snippet above is based on a Gmail add-on that I created, specifically for saving attachments to labeled folders in Drive: https://github.com/ellaqezi/archiveByLabel/blob/main/Code.gs#L24
In the label field, you can define nested directories to create in Drive e.g. foo/bar.
In the query field, you can copy the parameters as you would use them in Gmail's search bar.

Google Forms Upload File - using/modifying the response

Within a larger process (not relevant here) I would like to use the native Google Forms "File Upload" Question in a form.
I have been trying to understand how to use the response to :
rename the file uploaded
move/copy/save the file to a specific location
(this will be in the end determined by another response item, but for the moment, lets just call it "myDesitinationFolder"
I can of course, in the responses, in the Google interface, or in a Spreadsheet, see the files (and from the spreadsheet, the URL to the file)
but I would like to do my processing before the file is "saved to Drive" or in any case, during the onFormSubmit()
All i find though is a value [randomalphanumeric] and I am unable to find the documentation that explains what this [element] is. (if it is an object - but the square [] would seems to say this is NOT the case)
(Updated after clarification)
the sample code used to get the value comes from Stack.
.
fonction onFormSubmit(e){
var form = FormApp.getActiveForm()
var formResponses = form.getResponses();
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
Logger.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
console.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}
}
OUTPUT :
Response #19 to the question "fileUpload" was "[1OQeNOTREALCODE5SoAaPiw4s2M-cfRDJ]"
(NOTREALCODE added by me to anonymise response)
my Question : is that a file object? can i access the "save" process to change the destination and the name before hand?
or would my best option be to do a post submit process on an updated sheet (where i have the file URL etc..) (I really dont want to go that way, I would prefer to have it all within the form (I don't need the sheet otherwise)
thanks
When a file upload form is submitted, Google Form response stores the ID of the file in Google Drive. You can use the DriveApp service to access the uploaded file by ID and rename it, move it or copy to another folder.
function renameFile(id) {
var file = DriveApp.getFileById(id);
file.setName("Some name here");
}

Google Drive API - Bulk Uploader, File Renaming and Timeouts

I recently found a great google script which allows one to use Google Sheets to list lots of downloads (Jpegs in my case) and set titles. The script transloads(?)... moves the files from a remote place to your Google Drive. So no pointless downloading, uploading in-between.
function SaveToGoogleDrive(){
var folderID = 'FOLDER_HERE'; // put id of the Google Drive folder
var folder = DriveApp.getFolderById(folderID)// get the folder
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
var pdfURL = data[i][2];
var myFileName = data[i][1] + '.pdf';
var file = UrlFetchApp.fetch(pdfURL);
folder.createFile(myFileName,file);
}
}
(code comes via - http://unexpectedweb.blogspot.com.es/2017/11/directly-save-file-to-google-drive-by.html )
The script should allow me to set a name for each upload, which will be applied to the file on adding to Google Drive, but this doesn't work for me.
Is there something obvious in the code which doesn't look good to you as renaming doesn't work. Perhaps there's a script that will allow me to rename once the files are all in my Google Drive?
Also- I'm transloading(?) about 500 files and Google's Scripts can only run for 6mins. How would I incorporate something like the script demonstrated here:
That code...
/* Based on https://gist.github.com/erickoledadevrel/91d3795949e158ab9830 */
function isTimeUp_(start) {
var now = new Date();
return now.getTime() - start.getTime() > 300000; // 5 minutes
}
function SaveToGoogleDrive(){
var folderID = 'FOLDER_HERE'; // put id of the Google Drive folder
var folder = DriveApp.getFolderById(folderID)// get the folder
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var threads = GmailApp.getInboxThreads(0, 50);
var start = new Date();
for (var i in threads) {
if (isTimeUp_(start)) {
Logger.log("Time up");
break;
}
// Process the thread otherwise
for (var i = 1; i < data.length; i++) {
var pdfURL = data[i][2];
var myFileName = data[i][1] + '.pdf';
var file = UrlFetchApp.fetch(pdfURL);
folder.createFile(myFileName, file);
}
}
}
Thanks for your thoughts. Having so much trouble marrying the two together with my limited knowledge.
Change
folder.createFile(myFileName,file);
to
folder.createFile(file).setName(myFileName);

Using a script to edit data from a form submission

It appears the data submitted to a Google Form is saved not just in the associated spreadsheet, but also in the Form itself I have an HTML interface that displays the data to internal staff in a Non-Profits account. Some of this data may change or may not be known at the time of submission. Other information is saved in additional fields in the associated spreadsheet. I can add and edit that data, but is it possible to edit the data in the form file as well?
It is possible to get the data saved as a response in the form itself, and you can submit new responses programmatically. I don't think you can alter existing responses with Google Apps Script. See https://developers.google.com/apps-script/reference/forms
// Open a form by ID and log the responses to each question.
var form = FormApp.openById('1234567890abcdefghijklmnopqrstuvwxyz');
var formResponses = form.getResponses();
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
Logger.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}

Get the current response onSubmit

Is there any way to find out the current response of the Google Form (programmatically)?
In the onSubmit function.
Looked over their documentation but I have to provide the respondId.
How do I find the respondId?
A snipped code from them about this is:
// Open a form by ID and log the responses to each question.
var form = FormApp.openById('1234567890abcdefghijklmnopqrstuvwxyz');
var formResponses = form.getResponses();
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
Logger.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}
UPDATE:
function onSubmit(e) {
/* Get values entered by filling the form */
var itemResponses = e.response.getItemResponses();
var myWantedValue = itemResponses[COLUMN_NUMBER].getResponse();
}
Note: By passing the e(vent) as parameter the values can be accessed by submitting the live form, NOT by the script editor!
This code gives you the values for the last form response, is that what you're looking for ?
function myFunction() {
var formResponses = FormApp.getActiveForm().getResponses();
Logger.log(formResponses.length);
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
Logger.log('Last response to the question "%s" was "%s"',
itemResponse.getItem().getTitle(),
itemResponse.getResponse());
}
}
You are trying to read the exact response that triggered the execution of onSubmit(), to run another process on particular data, such as sending a confirmation email.
If the above is correct:
Instead of using the form as a data source for your later processing, try to read the Google Sheet storing the responses. It may seem the problem is the same: reading either data source (the form itself, or the sheet storing the data), doesn't point you to the exact entry that has triggered the onSubmit() event.
The difference is that in a sheet you can create a "reply_sent" column, to timestamp the instant each form response has been postprocessed, for example, having sent an automated reply based on its contents.
Then, when onSubmit() is run, it goes through all responses and processes not only the last one received, or the one having triggered the onSubmit() funtion, but also any other response that may have been left unreplied for whatever reason ("reply_sent" field blank). A last benefit from this approach is that your script is logging how it is behaving, since a date is recorded along with each response as it triggers obSubmit().
You cannot set up a custom confirmation message for each user.