App Script + Forms: How to move upload files - javascript

I have a Form bound to a Sheet. That works fine. I need to move the uploads to the newFolder and delete them from the temp holding folder.
I have it split into 2 functions. They work independently but I can not get them to work together. I think I just don't know enough.
So I could use some help sorting this out.
Thanks
//this part works great
function autoFillForm(e) {
var timestamp = e.values[0];
var firstName = e.values[1];
var lastName = e.values[2];
var title = e.values[3];
//create new folder
var parentFolder = DriveApp.getFolderById('My Parent Folder ID');
var newFolder = parentFolder.createFolder(lastName + ' - ' + firstName);
//Get template
var file = DriveApp.getFileById('My Template ID');
//Copy template, name it, save to new folder
var copy = file.makeCopy(lastName + ',' + firstName + ' - ' + 'Template Name', newFolder);
//Open copied file
var doc = DocumentApp.openById(copy.getId());
//Get Template body
var body = doc.getBody();
//Replace text in template
body.replaceText('{{fName}}', firstName);
body.replaceText('{{lName}}', lastName);
body.replaceText('{{title}}', title);
//Save and close
doc.saveAndClose();
}
UPDATE
I was able to get this working and it moves the files but only in a stand alone script. I have been trying for hours to get it to work with the main scripts and I'm at a loss.
function movingFiles (e){
//get file names from source folder
var files = DriveApp.getFolderById(ID for Source Folder).getFiles();
while(files.hasNext())
{
var file = files.next();
}
//get file ID
var fileId = file.getId();
//move file, clean source folder
DriveApp.getFolderById(newFolder).addFile(file);
file
.getParents()
.next()
.removeFile(file);
}

TLDR:
this: DriveApp.getFolderById(newFolder).addFile(file);
to this: DriveApp.getFolderById(newFolder.getId()).addFile(file);
this: (newFolder)
to this: (newFolder.getId())
I feel kind of stupid because this was an easy answer in the end.
I am able to to do everything in the one function. No need for seperate functions of Global Variables.
//this part works great
function autoFillForm(e) {
var timestamp = e.values[0];
var firstName = e.values[1];
var lastName = e.values[2];
var title = e.values[3];
//create new folder
var parentFolder = DriveApp.getFolderById('My Parent Folder ID');
var newFolder = parentFolder.createFolder(lastName + ' - ' + firstName);
//Get template
var file = DriveApp.getFileById('My Template ID');
//Copy template, name it, save to new folder
var copy = file.makeCopy(lastName + ',' + firstName + ' - ' + 'Template Name',
newFolder);
//Open copied file
var doc = DocumentApp.openById(copy.getId());
//Get Template body
var body = doc.getBody();
//Replace text in template
body.replaceText('{{fName}}', firstName);
body.replaceText('{{lName}}', lastName);
body.replaceText('{{title}}', title);
//Save and close
doc.saveAndClose();
//get file names from source folder
var files = DriveApp.getFolderById(ID for Source Folder).getFiles();
while(files.hasNext())
{
var file = files.next();
}
//get file ID
var fileId = file.getId();
//error here
//move file, clean source folder
DriveApp.getFolderById(newFolder).addFile(file);
file
.getParents()
.next()
.removeFile(file);
//this is where I was making a mistake
//this: DriveApp.getFolderById(newFolder).addFile(file);
//to this: DriveApp.getFolderById(newFolder.getId()).addFile(file);
//I was failing to understand I needed to define the function to the var again
}

Related

I have an error code in my getBody() function and I dont know why

So I'm creating this code where the template is selected through a series of If statements. so it is a changing variable. I am simply trying to now replace text in the selected template and I keep getting the same error that getBody() is not a function. Any help is greatly appreciated!
var doc = DriveApp.getFileById(templateId);
var copy = doc.makeCopy();
var destination = DriveApp.getFolderById('1mGCx4yXX_NnLHsHsGWBGkzwAVhG-cTrc');
destination.addFile(copy);
copy.setName(regno + ' statistical analysis');
var copiedTemplateId = copy.getId();
var body = doc.getBody();
var header = doc.getHeader();
DriveApp.getFileById returns a File.
So, doc is of type File.
There is no "getBody" function for a File, at least it doesn't exist in the documentation: https://developers.google.com/apps-script/reference/drive/file
This works:
function myfunk() {
const regno = "test";
var file = DriveApp.getFileById("fileid");
var destination = DriveApp.getFolderById("folderid");
let name = regno + ' statistical analysis';
var copy = file.makeCopy(name, destination);
var copiedTemplateId = copy.getId();
let doc = DocumentApp.openById(copiedTemplateId);
var body = doc.getBody();
var header = doc.getHeader();
Logger.log('id: %s, body: %s, header: %s',copiedTemplateId,body,header);
}
File was a Google Document and a copied was created in the appropriate directory and renamed correctly.

Trying to get folder path through file id using appscript

I am pulling a drive activity report using GCP/GAMadv which gives me file IDs of various users in our workspace domain on a google sheet. My goal is to find the folder path of these files using file IDs. I am using appscript to get to that. Here is the code that I am running so far.
function getFolderPath(fileID, folderPath =""){
var sheetID = "1YfZgkLvAnPj7kOIQOVkcXeJgnh-KTecMn6er1a0elkk"
var sheet = SpreadsheetApp.openById(sheetID)
// var file = sheet.Files.get(fileID)
var parent = Drive.Files.get(fileID);
console.log(parent)
// console.log(file)
var parentElement = parent.items[0]
console.log(parentElement)
// var parentElement = parent[0]
var parentFile = Drive.Files.get(parent.id);
var parentPath = parentFile.title;
if (parent.isRoot)
return "/" + folderPath;
else {
return getFolderPath(
parentFile.id,
parentPath + "/" + folderPath
);
}
}
Looks like this is returning ALL the files we have in our drive rather than the ones on the sheet.
Help would be greatly appreciated! Thanks.
Folder Path from Id
function getFolderPathFromId(id="fileid") {
try {
var file = DriveApp.getFileById(id)
var pA = [];
pA.push(file.getName());
var folder = file.getParents();
while (folder.hasNext()) {
var f = folder.next();
pA.push(f.getName());
folder = f.getParents()
}
var r = pA.reverse().slice(0,-1).join(' / ');
}
catch (e) {
return e;
}
Logger.log(r);
return r;
}

How to change name new creating folder with the subfolders

i want creating new folder with new name from cell in the sheet, and i want copy to this folder files and folders with the sourcedestiny.
Could you help me to solve my problem.
It is possible change name newFolder witout change name folders and subfolders- after his creating?
function copyFolderass() {
const sourceFolder = DriveApp.getFolderById('');
const destinyFolder = DriveApp.getFolderById('');
copyFolder(sourceFolder, destinyFolder);
}
function copyFolderContents(source, target) {
const filesIterator = source.getFiles();
while (filesIterator.hasNext()) {
const file = filesIterator.next();
file.makeCopy(file.getName(), target);
}
}
function copyFolder(sourceFolder, destinyFolder) {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("nameFile");
var name = ss.getRange("F4").getValue();
const newFolder = destinyFolder.createFolder(sourceFolder.getName());
copyFolderContents(sourceFolder, newFolder);
const foldersIterator = sourceFolder.getFolders();
while (foldersIterator.hasNext()) {
const folder = foldersIterator.next();
copyFolder(folder, newFolder);
}
}
Create Folders and Copy Files
Reads a sheet to obtain FilesFolder Id FolderFolder Id and new FolderName
It creates the new folder and copies all of the files from the Files Folder to the newly created folder.
It records the new folder id in FolderId Column.
It records all of the file ids in the FileIds column.
It put the date in the created column.
It doesn't do anything for rows that have content in Created
//FilesFolder FolderFolder FolderName FolderId FileIds Created
function createFolderAndCopyFiles() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const shsr = 2;
let [hA, ...vs] = sh.getDataRange().getValues();
let idx = {};
let col = {};
hA.forEach((h, i) => { idx[h] = i; col[h] = i + 1; });
vs.forEach((r, i) => {
if (!r[idx["Created"]]) {
let dfldr = DriveApp.getFolderById(r[idx["FolderFolder"]]);
let fldr = dfldr.createFolder(r[idx["FolderName"]]);
let fldrid = fldr.getId();
sh.getRange(i + shsr, col["FolderId"]).setValue(fldrid);
let files = DriveApp.getFolderById(r[idx["FilesFolder"]]).getFiles();
let ids = [];
while (files.hasNext()) {
let file = files.next();
let fid = file.getId();
file.makeCopy(file.getName(), fldr);
ids.push(fid);
}
sh.getRange(i + shsr, col["FileIds"]).setValue(ids.join('\n'));
sh.getRange(i + shsr, col["Created"]).setValue(new Date());
}
});
}
Spreadsheet
You fill in the stuff in yellow the program fills in the rest and it won't make folders again if the Created Column not empty.
Thx Cooper for the answer,
but this is not that what i want to do.
on google drive i have a template of structure od catalogs.
my code is one of the part code of my main code. main code working like this
i click send email and then run my code with creating folder from temtlace
when is creating a have name of the template folder but i want just change one part of this line of my code.
instead of this line
const newFolder = destinyFolder.createFolder(sourceFolder.getName());
i want to just like this - the name of the creating folder is from cell F4.
the remaining names of the folders may stays like from template.
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("nameFile");
var name = ss.getRange("F4").getValue();
const newFolder = destinyFolder.createFolder(sourceFolder.setName(name));
but this line change ale name in subfolders i all structure catalog when is creating.

Search only files that I own

I need the script to recognize that it should only search for files I created, because I'm not allowed to delete other people's files in this Google Drive folder.
var files = folder.searchFiles('modifiedDate < "' + cutOffDate + '"');
I confess that I tried to adjust by myself, but in every way is giving error, something always goes wrong. That form was my last attempt, which also failed:
var files = folder.searchFiles('modifiedDate < "' + cutOffDate + '" and "me#gmail.com" in owners ');
This answer is working for me on a folder that I have shared with one other account.
function getMyFilesFromFolder() {
var myFolderId = "FolderId";
var files = DriveApp.getFolderById(myFolderId).getFilesByType(MimeType.GOOGLE_SHEETS);
var myFiles=[];
while(files.hasNext()) {
var file = files.next();
if(file.getOwner().getEmail()==Session.getActiveUser().getEmail()) {
myFiles.push({name:file.getName(),id:file.getId(),owner:file.getOwner().getEmail(),currentuser:Session.getActiveUser().getEmail()});
Logger.log(Utilities.formatString('Name: %s Id: %s Owner: %s CurrentUser: %s', file.getName(),file.getId(),file.getOwner().getEmail(),Session.getActiveUser().getEmail()));
}
}
}
Let me know if it works for you. It should only be Logging files that you own. So current user email and owner email should be the same.
I also tested this on a shared folder and it works. I didn't want to delete anything so a changed a few things and I was just searching for Google Sheets.
function getOldFileIDs() {
// Old date is 3 Hours
var oldDate = new Date().getTime() - 3600*1000*3;
var cutOffDate = new Date(oldDate).toISOString();
// Get folderID using the URL on google drive
var folder = DriveApp.getFolderById('1iJTAdlhCM13c1CB5xMAjtLZlkaPMIlPb');
var files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);//Just looking for Google Sheets
var obj = [];
while (files.hasNext()) {
var file = files.next();
obj.push({name: file.getName(),id: file.getId(), date: file.getDateCreated(), owner: file.getOwner().getEmail()}); // Modified
}
obj.sort(function(a, b) {
var a= new Date(a.date).valueOf();
var b= new Date(b.date).valueOf();
return b-a;
});
//obj.shift();//I wanted to log all of them
return obj; // Modified
};
function logFiles() {
var email = Session.getActiveUser().getEmail();// Added
var obj = getOldFileIDs(); // Modified
obj.forEach(function(e) { // Modified
if (e.owner == email) { // Added
//Drive.Files.remove(e.id); // Modified
Logger.log('FileName: %s,Owner Email: %s',e.name,e.owner);
}
});
};

email Google Doc as PDF attachment

abc#example.comAfter struggling for a while with this I am calling for help from the crowd.
I am trying to attach 2 Google Docs to an email as PDFs. I see many examples in regard to Google Sheets and have successfully been able to email copies of sheets as PDF, but I have not been able to port this over to Docs.
In multiple different scenarios, the PDF attachments are either a copy of my original template Doc or an image capture of "One Account. All of Google" sign in page. When I look at the links that are generated (Logger.log) and use them, a copy of the correct Doc is downloaded.
Below is an example of my scenario in which I am trying to create the email attachments. See function emailDocAsPDF() towards the bottom
Thanks in advance for any guidance on this issue.
function myFunctionUpdated() {
var testTemplateId = searchDriveFile('Test Template');
Logger.log('test template id = ' + testTemplateId);
var fileName = 'Copy of Test Template'
Logger.log(fileName);
DriveApp.getFileById(testTemplateId).makeCopy(fileName);
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = ss.getRange(1, 1, 3, 2).getValues();
var copyNewTemplateId = searchDriveFile(fileName);
var copyTemplate = DocumentApp.openById(copyNewTemplateId);
var copyTemplateBody = copyTemplate.getBody().editAsText();
for (i=0; i<range.length; i++) {
copyTemplateBody.replaceText(range[i][0], range[i][1]);
}
copyTemplate.saveAndClose();
emailDocAsPDF(fileName)
}
// Searched Google Drive for a file name and returns the file ID.
function searchDriveFile(fileName) {
var files = DriveApp.searchFiles(
'title = "'+ fileName +'"');
while (files.hasNext()) {
var file = files.next();
var id = file.getId();
return id;
}
}
// Send document in an email as PDF
function emailDocAsPDF(fileName) {
var staticDoc = 'FILE-ID';
var attachmentDoc = UrlFetchApp.fetch("https://docs.google.com/document/d/" + copyTemplateId + "/export?format=pdf");
Logger.log("https://docs.google.com/document/d/" + copyTemplateId + "/export?format=pdf");
var attachmentStaticDoc = UrlFetchApp.fetch("https://docs.google.com/document/d/" + staticDoc + "/export?format=pdf");
Logger.log("https://docs.google.com/document/d/" + staticDoc + "/export?format=pdf");
var fileBlob = [];
fileBlob[0] = attachmentDoc.getBlob().getAs('application/pdf');
fileBlob[1] = attachmentStaticDoc.getBlob().getAs('application/pdf');
var body = "Bird is the WORD!! <br>" +
"<a href='http://www.example.com'>Visit Example</a>";
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail("email#example.com", "Test Documents Email", body, {
htmlBody: body,
attachments:[fileBlob[0],fileBlob[1]]
});
}
EDIT -- Successful Updates with code provided by Sandwich.
// Send document in an email as PDF
function emailDocAsPDF(fileName) {
var staticDoc = 'FILE-ID';
var copyTemplateId = searchDriveFile(fileName);
var blobs = [];
var doc = DriveApp.getFileById(copyTemplateId);
blobs[0] = doc.getBlob().getAs('application/pdf').setName('MyAttachment1.pdf');
var doc = DriveApp.getFileById(staticDoc);
blobs[1] = doc.getBlob().getAs('application/pdf').setName('MyAttachment2.pdf');
var zipBlob = Utilities.zip(blobs).setName('Documents.zip');
var recipient = 'abc#example.com';
var subject = 'Test Email';
var body = 'Bird is the WORD';
MailApp.sendEmail(recipient, subject, body, {attachments: [zipBlob]});
}
To attach any kind of document as a PDF, call getBlob on the file, specify content type as with .getAs('application/pdf') and optionally set a name with setName. That's all:
var doc = DriveApp.getFileById('ID_HERE');
var blob = doc.getBlob().getAs('application/pdf').setName('MyAttachment.pdf');
var recipient = 'user#example.com';
var subject = 'Email subject';
var body = 'Text here';
MailApp.sendEmail(recipient, subject, body, {attachments: [blob]});
You were trying to use "export as PDF via URL query", which is a poorly documented feature that is sometimes useful for Sheets (setting the boundaries of exported region), but is unnecessary for Docs, if it even exists for them. The above method should work for any kind of content stored in Google Drive.
By the way, it is preferable to use MailApp instead of GmailApp when sending email, because it keeps the level of authorization to what you need: sending emails. With GmailApp, the script is also granted permission to access and delete all of your existing emails, which is unadvisable for scripts composed by trial, error, and copying code from the Internet.

Categories