Unauthorized error 401 using UrlFetchApp - google-apps-script

I am trying to create a webapp, part of which will allow the user to create a new spreadsheet file in my drive. The fileURL is a link to an excel file ( download link taken from a file cabinet).
I am struggling with passing authority so that a google spreadsheet can be created. I am getting an unauthorized error 401. I had read that having DriveApp.getRootFolder() adds the Drive scope, but I am going wrong somewhere.
function downloadFile(fileURL, folder) {
var filename = fileURL.match(".+/(.+?)([\?#;].*)?$")[1];
var auth = ScriptApp.getOAuthToken();
var header = {"authorization": "Bearer " + auth};
var params = { 'method':'post', 'headers':header, 'muteHttpExceptions':true};
var holder = DriveApp.getRootFolder();
var response = UrlFetchApp.fetch(fileURL, params);
var rc = response.getResponseCode();
var blob = response.getBlob();
//delete file if it already exists
var fileList = DriveApp.getFilesByName(filename);
while (fileList.hasNext()) {
var fileId = fileList.next().getId();
DriveApp.getFileById(fileId).setTrashed(true);
}
var resource = {
"mimeType": "application/vnd.google-apps.spreadsheet",
"parents": [{id: folder}],
"title": filename
}
//Create file
var res = Drive.Files.insert(resource, blob); //put
}

Related

I want to change the names of old files uploaded to Google Forms

I have a google form and all the files uploaded by the participants contain random names.
The data is summarized in personal photos, ID photos, photos of certificates.
That is why we want to name the files with the names of the people themselves by choosing a specific field.
I tried in a code via the google apps script to change the names but it is no more than 70 to 80 files and then it stops
Is there a code that will help me with this work, especially since the number of files is large?
function renamefile() {
var form = FormApp.openById('16aPNgaSuDZ-e0ibw08jW7_-YMULGWV-_iUP9uQHE'); //DDD
var formResponses = form.getResponses();
var baseString = 'https://drive.google.com/file/d/';
var endString = '/view?usp=drivesdk';
var folder = DriveApp.getFolderById('1BPA7wkECV1vOB6bo3tGfUZd9MifjwYJG2BVI_sHSeNojFY-xiN4dvLW_vc2zw4IEe');
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
for (var i = 0; i < formResponses.length; i++) {
var formResponse = formResponses[i];
var itemResponses = formResponse.getItemResponses();
var itemResponseFname = itemResponses[1];
var itemResponsePhoto = itemResponses[15];
var photoID = itemResponsePhoto.getResponse();
var newName = itemResponseFname.getResponse() + " - " + "PHOTO" ;
var url = baseString + photoID + endString;
var urlCheck = file.getUrl();
if ( url == urlCheck) {
var modName = newName + ".pdf" ;
file.setName(modName);
}
}
}
}
Modification points:
From your showing script, it seems that the form responses are retrieved every loop of the "while loop". I thought that this might be a high process cost.
From your script, it seems that you want to rename PDF files. In this case, when PDF files are retrieved. The process cost might be able to be reduced.
I thought that in your situation, the file ID can be used for checking the file instead of URL.
When these points are reflected in your script, how about the following modification?
Modified script:
function renamefile() {
var form = FormApp.openById('###'); // Please set your file ID of Google Forms.
var folder = DriveApp.getFolderById('###'); // Please set your folder ID.
// Create an object for searching file ID.
var obj = form.getResponses().reduce((o, f) => {
var itemResponses = f.getItemResponses();
var itemResponseFname = itemResponses[1];
var itemResponsePhoto = itemResponses[15];
var fileId = itemResponsePhoto.getResponse();
var newName = itemResponseFname.getResponse() + " - " + "PHOTO";
o[fileId] = newName + ".pdf";
return o;
}, {});
// Rename files.
var files = folder.getFilesByType(MimeType.PDF);
while (files.hasNext()) {
var file = files.next();
var fileId = file.getId();
if (obj[fileId]) {
file.setName(obj[fileId]);
}
}
}
When this script is run, first, an object is created. This object is used for searching the file ID in the folder. And, using the object, the PDF files in the folder are renamed.
Note:
If your files are not PDF files, please modify var files = folder.getFilesByType(MimeType.PDF); to var files = folder.folder.getFiles();.
When the number of files is large and the processing time is over 6 minutes, I would like to propose using the batch requests. The sample script of batch request can be seen at this thread. And, when the above script is modified, the sample script is as follows. When you use this script, please enable Drive API at Advanced Google services. And also, please install a Google Apps Script library of BatchRequest. Ref
function renamefile2() {
var form = FormApp.openById('###'); // Please set your file ID of Google Forms.
var folderId = "###"; // Please set your folder ID.
// Create an object for searching file ID.
var obj = form.getResponses().reduce((o, f) => {
var itemResponses = f.getItemResponses();
var itemResponseFname = itemResponses[1];
var itemResponsePhoto = itemResponses[15];
var fileId = itemResponsePhoto.getResponse();
var newName = itemResponseFname.getResponse() + " - " + "PHOTO";
o[fileId] = newName + ".pdf";
return o;
}, {});
// Rename files using batch request.
var { items } = Drive.Files.list({ q: `'${folderId}' in parents and trashed=false and mimeType='${MimeType.PDF}'`, maxResults: 1000, fields: "items(id)" });
var requests = items.reduce((ar, { id }) => {
if (obj[id]) {
ar.push({
method: "PATCH",
endpoint: `https://www.googleapis.com/drive/v3/files/${id}`,
requestBody: { name: obj[id] },
});
}
return ar;
}, []);
var result = BatchRequest.EDo({ batchPath: "batch/drive/v3", requests });
}
In this sample, it supposes that the number of your files is less than 1000. When the number of files is more than 1000, please retrieve all files using pageToken.
Reference:
reduce()

Uploading a file to Google Shared Drive via Spreadsheet

I'm trying to use google spreadsheets to upload files to a certain folder on a Shared Drive. I've found this code online and it didn't actually work to start with but I played with it and it would still not initiate the upload.
The code I used came from this website.
I've modified the upload function:
folderId = 'my folder ID'
driveId = 'my shared drive ID'
function onOpen(e){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var menuEntries = [];
menuEntries.push({name: "File", functionName: "doGet"});
ss.addMenu("Attach", menuEntries);
}
//the upload script
function upload(obj) {
var metadata = {
"parents": [{
"id": folderId,
"kind": "drive#parentReference"
}],
"teamDriveId": driveId };
var optionalParams = {
"supportsAllDrives": true
};
file = Drive.Files.insert(metadata, optionalParams);
var activeSheet = SpreadsheetApp.getActiveSheet();
var File_name = file.getName()
var value = 'hyperlink("' + file.getUrl() + '";"' + File_name + '")'
var activeSheet = SpreadsheetApp.getActiveSheet();
var selection = activeSheet.getSelection();
var cell = selection.getCurrentCell()
cell.setFormula(value)
return {
fileId: file.getId(),
mimeType: file.getMimeType(),
fileName: file.getName(),
};
}
I think the obj refers to the type of file you are uploading maybe, you can review the proper code in this documentation https://developers.google.com/drive/api/v3/manage-uploads#multipart
Just make sure to select "Java."
Here is the example in that KB:
File fileMetadata = new File();
fileMetadata.setName("photo.jpg");
java.io.File filePath = new java.io.File("files/photo.jpg");
FileContent mediaContent = new FileContent("image/jpeg", filePath);
File file = driveService.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
System.out.println("File ID: " + file.getId());

Get specific Range to Export

can anyone help me with my problem?
Need to export a specific range (A1:J39), not the full sheet.
function SavePDFtoDrive() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ltrsht = ss.getSheetByName("Schichtübergabe-Protokoll");
var datasheet = ss.getSheetByName("Daten");
var sheets=SpreadsheetApp.getActiveSpreadsheet().getSheets();
for(var i =0;i<sheets.length;i++){
if(sheets[i].getName()!="Schichtübergabe-Protokoll"){ sheets[i].hideSheet() }
}
var pdf = DriveApp.getFileById(ss.getId());
var theBlob = pdf.getBlob().getAs('application/pdf').setName(datasheet.getRange("I8").getValue()+".pdf");
var folderID = "1dyKFNvQWrSiNFA8N5PyUMPJQpWSVhsLf"; // Folder id to save in a folder
var folder = DriveApp.getFolderById(folderID);
var newFile = folder.createFile(theBlob);
}
Answer:
Rather than getting your blob using DriveApp, you can obtain your blob from an export URL using UrlFetchApp.
More Information:
When you use DriveApp to create a blob of a file, it doesn't have the functionality to read the specifics of the file. In this case, you can't specify the range of a Sheet you wish to export with DriveApp.
You can, however, build a URL with all your export parameters and create your export in Drive by creating a blob of the response and creating it in Drive.
Code:
function SavePDFtoDrive() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ltrsht = ss.getSheetByName("Schichtübergabe-Protokoll");
var datasheet = ss.getSheetByName("Daten");
// build your URL:
var url = "https://docs.google.com/spreadsheets/d/" + ss.getId() + "/export?"
//define your parameters:
var params = 'exportFormat=pdf&format=pdf'
+ '&portrait=false'
+ '&fitw=true'
+ '&gid=' + ltrsht.getSheetId()
+ '&range=A1:J39';
//get token for UrlFetch:
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + params, {
'headers': {
'Authorization': 'Bearer ' + token
}
});
var fileName = datasheet.getRange("I8").getValue() + ".pdf";
var theBlob = response.getBlob().setName(fileName);
var folderID = "1Hp-P1dzWaKHhhS2FTPzKib6pwJibS12t";
var folder = DriveApp.getFolderById(folderID);
folder.createFile(theBlob);
}
References:
Class UrlFetchApp | Apps Script | Google Developers
Related Questions/Answers:
how to print a long Google sheets column in fewer columns

Optimize Google Scripts - Triggers not working

Problem
My Google Script triggers aren't running because it "uses to much CPU time", according to error emails I receive. How can I optimize my scripts to use less CPU time?
I've separated sortGsheetFiles into different trigger, but it still uses to much time. It used to be combined with the importXLSXtoGsheet function.
Scripts explained
I've got 52 folders, each containing one spreadsheet file.
Each folder is shared with different colleagues.
During the day, people make changes to the files.
At the end of the day, all files are collected in one folder (gsheetFolder) and converted to XLSX files, using the function collectAndExportXLS.
These files are copied to a local server in the evening (using batch script and drive sync) which updates other information in the file and are copied back to the importXLSXfolder.
In the morning the importXLSXtoGsheet function runs and converts all XLSX files in the importXLSXfolder folder to Gsheet files in the gsheetFolder.
After that sortGsheetFiles runs, sorting and moving every Gsheet file in one of the 52 folders (using an array list from the current spreadsheet).
Other actions include cleaning the folders with the deleteFolder function.
Triggers
importXLSXtoGsheet - every day - between 6 am and 7 am
sortGsheetFiles - every day - between 7 am and 8 am
collectAndExportXLS - every day - between 10 pm and 11 pm
Script
var gsheetFolder = 'xxx';
var XLSXfolder = 'xxxxx';
var importXLSXfolder = 'xxxxx';
function checkEmptyFolder() {
var folders = DocsList.getAllFolders()
for(n=0;n<folders.length;++n){
if(folders[n].getFiles().length==0 && folders[n].getFolders().length==0){
folders[n].setTrashed(true)
Logger.log(folders[n].getName())
}
}
}
function importXLSXtoGsheet(){
// ========= convert all XLS files in XLS folder to GSheet and put in the general gsheet folder - after that sort in gsheet filiaal folders =========
// cleanup exportXLS folder first
deleteFolder(XLSXfolder);
var files = DriveApp.getFolderById(importXLSXfolder).searchFiles('title contains ".xlsx"');
while(files.hasNext()) {
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')) {
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name + ('.xlsx'),
key : ID,
parents: [{"id": gsheetFolder}]
}
file = Drive.Files.insert(newFile, xBlob, {convert: true});
}
}
deleteFolder(importXLSXfolder);
}
function sortGsheetFiles() {
// ========= sort Gsheet folder and move to corresponding filiaal folders =========
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var myArrayFileName = sheet.getRange("A2:A53").getValues();
var myArrayFolderId = sheet.getRange("B2:B53").getValues();
var a = myArrayFileName.join().split(',').filter(Boolean);
var b = myArrayFolderId.join().split(',').filter(Boolean);
var folderId = gsheetFolder;
// Log the name of every file in the folder.
var files = DriveApp.getFolderById(folderId).getFiles();
while (files.hasNext()) {
var file = files.next();
for (var i in a) {
var id = file.getId();
if (file.getName() == a[i]) {
moveFiles(id, b[i]); // Match found and move to corresponding folder
}
}
}
deleteFolder(importXLSXfolder);
}
function collectAndExportXLS() {
// ========= collect all Gsheet files, copy to gsheet folder and convert to xlsx and move to xlsx folder =========
// cleanup gsheet folder
deleteFolder(gsheetFolder);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var myArrayFileName = sheet.getRange("A2:A53").getValues();
var myArrayFolderId = sheet.getRange("B2:B53").getValues();
var a = myArrayFileName.join().split(',').filter(Boolean);
var b = myArrayFolderId.join().split(',').filter(Boolean);
var folderId = gsheetFolder;
for (var i in b) {
var files = DriveApp.getFolderById(b[i]).getFiles();
while (files.hasNext()) {
var file = files.next();
var id = file.getId();
moveFiles(id , folderId);
}
}
ConvertBackToXLS()
deleteFolder(gsheetFolder);
}
function moveFiles(sourceFileId, targetFolderId) {
var file = DriveApp.getFileById(sourceFileId);
file.getParents().next().removeFile(file);
DriveApp.getFolderById(targetFolderId).addFile(file);
}
function deleteFolder(folder) {
//delete files in a folder without sending to trash!
var eachFile, idToDLET, myFolder, rtrnFromDLET, thisFile, files;
files = DriveApp.getFolderById(folder).getFiles();
while (files.hasNext()) {//If there is another element in the iterator
eachFile = files.next();
idToDLET = eachFile.getId();
//Logger.log('idToDLET: ' + idToDLET);
rtrnFromDLET = Drive.Files.remove(idToDLET);
};
Logger.log('folder deleted');
}
function ConvertBackToXLS() {
// Log the name of every file in the folder.
var files = DriveApp.getFolderById(gsheetFolder).getFiles();
var dir = DriveApp.getFolderById(XLSXfolder);
while (files.hasNext()) {
try {
var file = files.next();
var ss = SpreadsheetApp.openById(file.getId());
Logger.log(file.getId());
var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + file.getId() + "&exportFormat=xlsx";
var params = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(ss.getName());
var newfile = dir.createFile(blob);
} catch (f) {
Logger.log(f.toString());
}
}
}
How about this modification? Please think of this as just one of several answers.
And as an important point, please test the script using a test situation, before you run with your actual situation.
About your script:
collectAndExportXLS(): Abou this function name, I didn't modify collectAndExportXLS(). Because I thought that you might be using this function name at other script or triggers.
Delete all files in gsheetFolder.
Convert a Google Spreadsheet in each folder ID retrieved from "B2:B53" of the sheet with the 1st index in the active Spreadsheet to XLSX format.
Filename is like sample.xlsx.
All converted files are put in XLSXfolder.
Delete all files in all folder IDs.
XLSX files in XLSXfolder are put in importXLSXfolder by other script.
importXLSXtoGsheet(): Abou this function name, I didn't modify collectAndExportXLS(). Because I thought that you might be using this function name at other script or triggers.
Delete all files in XLSXfolder.
Convert all XLSX files in importXLSXfolder to Google Spreadsheet.
Filename is like sample.xlsx.
Converted Google Spreadsheets are put in gsheetFolder.
Delete all files in importXLSXfolder.
sortGsheetFiles()
Move Google Spreadsheets in gsheetFolder to each folder ID retrieved from "B2:B53" of the sheet with the 1st index in the active Spreadsheet.
In order to match the folder ID, the filenames of Google Spreadsheet and the values retrieved from "A2:A53".
Delete all files in importXLSXfolder.
I understood that from your question, the filenames of column "A2:A53" of the active Spreadsheet are the same with the filenames of Google Spreadsheets which were put in the folders of folder IDs of the column "B2:B53".
I understood that the number of all files is less than 100.
I understand like above. If my understanding is correct, how about this modification? In my modification, I used the Batch request of Drive API and the fetchAll method of UrlFetchApp with the type of multipart/form-data for your situation. The batch request and fetchAll method can work with the asynchronous process. By this, I thought that your process cost might be reduced.
In order to use these methods, I used 2 GAS libraries. Before you run the script, please install these 2 libraries for your script. You can see how to install the library as follows.
Install a library for running the fetchAll method of UrlFetchApp with the type of multipart/form-data.
Install a library for running batch request.
Modification points:
collectAndExportXLS()
File IDs in each folder are retrieved by the batch request.
Blobs (XLSX format) from each file ID are retrieved by the fetchAll method of UrlFetchApp.
Files of XLSX format are created by FetchApp.
importXLSXtoGsheet()
File list is retrieved by the files.list method of Drive API.
Files of XLSX format are converted to Google Spreadsheet by the batch request.
sortGsheetFiles()
File list is retrieved by the files.list method of Drive API.
Files of Google Spreadsheet are moved to each folder ID retrieved from the column "B2:B53" of the active Spreadsheet using the batch request.
deleteFolder()
Files in the folder are deleted by the batch request.
When above points are reflected to your script, it becomes as follows.
Modified script:
After installed 2 libraries, please run the following script.
var gsheetFolder = '###';
var XLSXfolder = '###';
var importXLSXfolder = '###';
// Modified
function deleteFolder(folderId) {
var url = "https://www.googleapis.com/drive/v3/files?q='" + folderId + "'+in+parents+and+trashed%3Dfalse&fields=files%2Fid&access_token=" + ScriptApp.getOAuthToken();
var res = UrlFetchApp.fetch(url);
var obj = JSON.parse(res.getContentText());
var reqs = obj.files.map(function(e) {return {method: "DELETE", endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id}});
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
}
// Added
function deleteFiles(files) {
var reqs = files.map(function(e) {return {method: "DELETE", endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id}});
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
}
// Added
function getValuesFromSpreadsheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
return sheet.getRange("A2:B53").getValues();
}
// Modified
function sortGsheetFiles() {
var url = "https://www.googleapis.com/drive/v3/files?q='" + gsheetFolder + "'+in+parents+and+mimeType%3D'" + MimeType.GOOGLE_SHEETS + "'+and+trashed%3Dfalse&fields=files(id%2Cname)&access_token=" + ScriptApp.getOAuthToken();
var res = UrlFetchApp.fetch(url);
var obj = JSON.parse(res.getContentText());
var values = getValuesFromSpreadsheet();
var reqs = values.reduce(function(ar, e) {
for (var i = 0; i < obj.files.length; i++) {
if (obj.files[i].name == e[0]) {
ar.push({
method: "PATCH",
endpoint: "https://www.googleapis.com/drive/v3/files/" + obj.files[i].id + "?addParents=" + e[1] + "&removeParents=" + gsheetFolder,
});
break;
}
}
return ar;
}, []);
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
deleteFolder(importXLSXfolder);
}
// Modified
function importXLSXtoGsheet(){
deleteFolder(XLSXfolder);
var url = "https://www.googleapis.com/drive/v3/files?q='" + importXLSXfolder + "'+in+parents+and+mimeType%3D'" + MimeType.MICROSOFT_EXCEL + "'+and+trashed%3Dfalse&fields=files(id%2Cname)&access_token=" + ScriptApp.getOAuthToken();
var res = UrlFetchApp.fetch(url);
var obj = JSON.parse(res.getContentText());
var reqs = obj.files.map(function(e) {return {
method: "POST",
endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id + "/copy",
requestBody: {mimeType: MimeType.GOOGLE_SHEETS, name: e.name + ".xlsx", parents: [gsheetFolder]},
}
});
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
deleteFolder(importXLSXfolder);
}
// Modified
function ConvertBackToXLS(fileList) {
var token = ScriptApp.getOAuthToken();
var reqs1 = fileList.map(function(e) {return {
method: "GET",
url: "https://docs.google.com/spreadsheets/export?id=" + e.id + "&exportFormat=xlsx&access_token=" + token,
}
});
var res = UrlFetchApp.fetchAll(reqs1);
var reqs2 = res.map(function(e, i) {
var metadata = {name: fileList[i].name, parents: [XLSXfolder]};
var form = FetchApp.createFormData(); // Create form data
form.append("metadata", Utilities.newBlob(JSON.stringify(metadata), "application/json"));
form.append("file", e.getBlob());
var url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
return {url: url, method: "POST", headers: {Authorization: "Bearer " + token}, body: form};
});
FetchApp.fetchAll(reqs2);
}
// Modified
function collectAndExportXLS() {
deleteFolder(gsheetFolder);
var values = getValuesFromSpreadsheet();
var reqs1 = values.reduce(function(ar, e) {
if (e[0] && e[1]) {
ar.push({
method: "GET",
endpoint: "https://www.googleapis.com/drive/v3/files?q='" + e[1] + "'+in+parents+and+trashed%3Dfalse&fields=files(id%2Cname)",
});
}
return ar;
}, []);
var resForReq1 = BatchRequest.Do({batchPath: "batch/drive/v3", requests: reqs1});
var temp = resForReq1.getContentText().split("--batch");
var files = temp.slice(1, temp.length - 1).map(function(e) {return JSON.parse(e.match(/{[\S\s]+}/g)[0])});
var fileList = files.reduce(function(ar, e) {return ar.concat(e.files.map(function(f) {return f}))}, []);
ConvertBackToXLS(fileList);
deleteFiles(fileList);
}
Note:
In this modification, the error handling is not reflected, because I couldn't test your situation. So please add it, if you are required.
If the file size of XLSX files is large, the error might occur.
References:
Batch request of Drive API
BatchRequest
FetchApp

Prevent Renaming of Google Forms File Upload

I have a Google Form that uses the File Upload feature that is mentioned on the below site,
https://sites.google.com/site/scriptsexamples/home/announcements/google-forms-file-upload-feature
I am wondering 2 things:
Is there a way to prevent the renaming of the uploaded file. (IE: original_file_name - Name of Uploader)
Concerning the below quote:
If a respondent decides to upload a file directly from his Drive, a
copy will be made and the form owner will become owner of the copy.
Is it possible to identify the original file and remove it so that it does not junk up the uploaders root Drive folder.
function getCurrentResponses() {
var form = FormApp.openById('formID');
var formResponses = form.getResponses();
var numResponses = formResponses.length;
var lastResponse = formResponses[numResponses - 1];
var lastResponseItem = lastResponse.getItemResponses();
var emailAddress = lastResponseItem[0].getResponse();
Logger.log('emailAddress: ' + emailAddress);
var zone = lastResponseItem[1].getResponse();
Logger.log('zone: ' + zone);
var projectName = lastResponseItem[2].getResponse();
Logger.log('projectName: ' + projectName);
var igeURL = lastResponseItem[3].getResponse();
Logger.log('igeURL: ' + igeURL);
//Creating folder for submitted project
var DriveFolder = DriveApp.getFolderById("destinationFolder");
var folderName = projectName;
//create the folder
var folderpath = DriveFolder.createFolder(folderName).addEditor(emailAddress).getId();
//get the path to the folder
var pathtoemail = "https://drive.google.com/drive/folders/"+folderpath;
var file = DriveApp.getFileById(igeURL);
file.getParents().next().removeFile(file);
DriveApp.getFolderById(folderpath).addFile(file);
var fileName = file.getName();
//Create the message and subject of the email
var message = 'Thank you for submitting. Here is the link to your drive folder. Please use this folder to upload and receive related documentation. ' +pathtoemail ; //a custom message, feel free to change anything inside the quotes
var subject = "Form Related Documentation." ;
//send the email
MailApp.sendEmail(emailAddress, subject, message, {
// cc: 'email#email.com' // optional cc
});
/*
* Convert Excel file to Sheets
* https://gist.github.com/azadisaryev/ab57e95096203edc2741
* Retrieved 06/08/2017
*/
var xlsId = igeURL; // ID of Excel file to convert
var xlsFile = DriveApp.getFileById(xlsId); // File instance of Excel file
var xlsBlob = xlsFile.getBlob(); // Blob source of Excel file for conversion
var xlsFilename = xlsFile.getName(); // File name to give to converted file; defaults to same as source file
var destFolders = folderpath; // array of IDs of Drive folders to put converted file in; empty array = root folder
Logger.log("destFolders: " + destFolders);
var ss = convertExcel2Sheets(xlsBlob, xlsFilename, destFolders);
var ssID = ss.getId();
Logger.log(ss.getId());
var convertFile = DriveApp.getFileById(ssID);
convertFile.getParents().next().removeFile(convertFile);
DriveApp.getFolderById(folderpath).addFile(convertFile);
}
/**
* Convert Excel file to Sheets
* https://gist.github.com/azadisaryev/ab57e95096203edc2741
* Retrieved 06/08/2017
* #param {Blob} excelFile The Excel file blob data; Required
* #param {String} filename File name on uploading drive; Required
* #param {Array} arrParents Array of folder ids to put converted file in; Optional, will default to Drive root folder
* #return {Spreadsheet} Converted Google Spreadsheet instance
**/
function convertExcel2Sheets(excelFile, filename, arrParents) {
var parents = arrParents || []; // check if optional arrParents argument was provided, default to empty array if not
if ( !parents.isArray ) parents = []; // make sure parents is an array, reset to empty array if not
Logger.log("arrParents: " + arrParents);
// Parameters for Drive API Simple Upload request (see https://developers.google.com/drive/web/manage-uploads#simple)
var uploadParams = {
method:'post',
contentType: 'application/vnd.ms-excel', // works for both .xls and .xlsx files
contentLength: excelFile.getBytes().length,
headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
payload: excelFile.getBytes()
};
// Upload file to Drive root folder and convert to Sheets
var uploadResponse = UrlFetchApp.fetch('https://www.googleapis.com/upload/drive/v2/files/?uploadType=media&convert=true', uploadParams);
// Parse upload&convert response data (need this to be able to get id of converted sheet)
var fileDataResponse = JSON.parse(uploadResponse.getContentText());
// Create payload (body) data for updating converted file's name and parent folder(s)
var payloadData = {
title: filename,
parents: []
};
if ( parents.length ) { // Add provided parent folder(s) id(s) to payloadData, if any
for ( var i=0; i<parents.length; i++ ) {
try {
var folder = DriveApp.getFolderById(parents[i]); // check that this folder id exists in drive and user can write to it
payloadData.parents.push({id: parents[i]});
}
catch(e){} // fail silently if no such folder id exists in Drive
}
}
// Parameters for Drive API File Update request (see https://developers.google.com/drive/v2/reference/files/update)
var updateParams = {
method:'put',
headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
contentType: 'application/json',
payload: JSON.stringify(payloadData)
};
// Update metadata (filename and parent folder(s)) of converted sheet
UrlFetchApp.fetch('https://www.googleapis.com/drive/v2/files/'+fileDataResponse.id, updateParams);
return SpreadsheetApp.openById(fileDataResponse.id);
}
I just wanted to post that I was able to create a work-around for the renaming of the file.
var form = FormApp.openById('formID');
var formResponses = form.getResponses();
var numResponses = formResponses.length;
var lastResponse = formResponses[numResponses - 1];
var lastResponseItem = lastResponse.getItemResponses();
var submittedID = lastResponseItem[3].getResponse();
var file = DriveApp.getFileById(submittedID);
var oldFileName = file.getName();
var indexOldFileName = oldFileName.indexOf("-");
var newFileName = oldFileName.slice(0,indexOldFileName - 1);
var indexOldFileExt = oldFileName.lastIndexOf(".");
var newFileExt = oldFileName.slice(indexOldFileExt);
var modName = newFileName + newFileExt;
file.setName(modName);
As for my second question, I still haven't been able to solve it. I will post if I find a solution.
I change your code a little bit so the name of the file is changed to its ID.
function changenametoid() {
var form = FormApp.openById('formID');
var formResponses = form.getResponses();
var numResponses = formResponses.length;
var lastResponse = formResponses[numResponses - 1];
var lastResponseItem = lastResponse.getItemResponses();
var submittedID = lastResponseItem[0].getResponse();
var file = DriveApp.getFileById(submittedID);
var oldFileName = file.getName();
var indexOldFileName = oldFileName.indexOf("-");
var newFileName = submittedID;
var indexOldFileExt = oldFileName.lastIndexOf(".");
var newFileExt = oldFileName.slice(indexOldFileExt);
var modName = newFileName + newFileExt;
file.setName(modName);
}