Get file ID by its folder and name - google-apps-script

I'm copying a specific file to a specific folder, here's the code:
var fileID = "123abc";
var folderID = "abc123";
var name = "Conferencia " + Utilities.formatDate(source.getRange(2,4).getValue(), "GMT", "dd-MM-yyyy");
var file = DriveApp.getFileById(fileID);
var folder = DriveApp.getFolderById(folderID);
var newFile = file.makeCopy(name,folder);
var newUrl = DocumentApp.openById(newFile.getId());
Logger.log(newUrl);
This code works perfectly, except by the var newUrl = DocumentApp.openById(newFile.getId());. This line should record the ID of the new file but it won't work.
How to make it work?

var newUrl = DocumentApp.openById(newFile.getId());
means that newUrl is now a Document object, pointing to your Google Document contained in that file (presumably it's a Google Document file, otherwise there's an error already). It's not an Id or URL or a string of any sort.
If you want to get the URL of the file, use the getUrl method:
var newUrl = newFile.getUrl();
If you want to get the Id (which is just the last part of the URL), then it's
var newId = newFile.getId();
These are strings which can later be used in DocumentApp.openByUrl or DocumentApp.openById if you want to use them; these methods will return a Document object.

Related

App Script to insert an image from google drive to a google doc

Have collected info through a google form to a google sheet. Part of that info is the path to an image stored on drive. I have an app script that replaces key words on a document with the data collected in the sheet. I can get it to replace a piece of text, {{image}} for example with the url stored but I cannot get it to actually put a copy of the image into the document.
Any suggestions.
Code below
// #ts-nocheck
function autoFillGoogleDocFromForm(e) {
//e.values is an array of form values
var timestamp = e.values[0];
var email = e.values[1];
var who = e.values[2];
var employeeorcon = e.values[3];
var location = e.values[4];
var roomorarea = e.values[5];
var type = e.values[6];
var dateofworks = e.values[7];
var imageofcompletedcon = e.values[8];
var checkedoffintext = e.values[9];
var checkname = e.values[10];
var checkco = e.values[11];
var checkeddate = e.values[12];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById("1WcYKvsRFbKK73J-ep66mR9drZyrkWap-x30rO-kVUcM");
//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("1MeU3-N3BMqOPvoaSGr2XassibR2XajdN")
var copy = file.makeCopy(roomorarea + '_' + timestamp, 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();
//Then we call all of our replaceText methods
body.replaceText('{{location}}', location);
body.replaceText('{{room}}', roomorarea);
body.replaceText('{{completedby}}', who);
body.replaceText('{{checkedby}}', checkname);
body.replaceText('{{checkeddate}}', checkeddate);
body.replaceText('{{insdate}}', dateofworks);
body.replaceText('{{Empcon}}', employeeorcon);
body.replaceText('{{Type}}', type);
body.replaceText('{{image}}', imageofcompletedcon);
body.replaceText('{{methchk}}', checkedoffintext);
body.replaceText('{{checker}}', checkname);
body.replaceText('{{cocheck}}', checkco);
body.replaceText('{{datecheck}}', checkeddate);
//Lastly we save and close the document to persist our changes
doc.saveAndClose();
}
New to this, but tried insertimage etc, but really a bit beyond me.

How to search a Specific File Name and File Type together in Google Drive folder from multiple sub folders using Google Script

In Google Drive, I'm searching for a specific file that contain words "Verification Visit" and "completed" where the file type need to be a spreadsheet(.xlsx) type file. The searching will go through a parent folder and then into sub folders. So the particular files will be stored in some of the sub folders (Google Drive -> Parent folder -> Sub folders).
Here is the code:
function getChildFolders(parentName, parent, sheet, voidFolder, excluded) {
var childFolders = parent.getFolders();
var folder = childFolders.next();
var failIter = folder.searchFiles('title contains "completed"');
while (failIter.hasNext()) {
var fail = failIter.next();
var failWithTitle = fail.getName();
var files = folder.getFilesByType(MimeType.MICROSOFT_EXCEL);
var output = [];
var path;
var Url;
var fileID;
while (files.hasNext()) {
var childFile = files.next();
var fileName = childFile.getName();
path = parentName + ' |--> ' + fileName;
fileID = childFile.getId();
Url = 'https://drive.google.com/open?id=' + fileID;
output.push([fileID, fileName, path, Url]);
}
if (output.length) {
var last_row = sheet.getLastRow();
sheet.getRange(last_row + 1, 1, output.length, 4).setValues(output);
}
getChildFolders(
parentName + ' |--> ' + fileName,
folder,
sheet,
voidFolder,
excluded
);
}
}
I have successfully implemented the two conditions (file that contains specific name and also the file type) in this function. The problem here is the searching process of the file in the sub folder only does on the first sub folder and it doesn't proceed searching into the next sub folder. It only list the files from the first sub folder but not from the other sub folders.
I am getting an error message telling "Exception: Cannot retrieve the next object: iterator has reached the end."
Issues:
You are not checking whether parent.getFolders() returns any folder, so when you reach the end of the hiearchy and there are no further subfolders on that level, childFolders.next(); fails with the error you are getting.
You are not iterating through the FolderIterator (for example, with while (folderIter.hasNext()) {), so you are only getting the first folder in the iterator.
You are iterating through the files that contain completed, but inside each file iteration you are iterating again with folder.getFilesByType to check the MIME type (check the available search query terms). That is to say, you are iterating through the files in that folder twice, which will most likely return duplicate results.
Suggested workflow:
For each folder, look for your desired files with Folder.searchFiles with the two conditions you want (title contains completed and mime type corresponds to MS Excel) and iterate through the results with FileIterator.hasNext() in a while loop.
For each folder, look for the corresponding subfolders via Folder.getFolders(), and loop through the results with FolderIterator.hasNext() and a while loop. For each of these subfolders, call your function recursively.
Use SpreadsheetApp.flush to make sure the sheet gets updated every time setValues is used, so that previous data is not overwritten.
Code sample:
function getChildFiles(folderName, folder, sheet) {
var fileIter = folder.searchFiles("title contains 'completed' and mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'");
var folderId = folder.getId();
var output = [];
while (fileIter.hasNext()) { // Iterate through files in folder
var file = fileIter.next();
var fileName = file.getName();
var path = folderName + ' |--> ' + fileName;
var fileID = file.getId();
var Url = 'https://drive.google.com/open?id=' + fileID;
output.push([fileID, fileName, path, Url, folderId]);
}
if (output.length) {
var last_row = sheet.getLastRow();
sheet.getRange(last_row + 1, 1, output.length, output[0].length).setValues(output);
SpreadsheetApp.flush();
}
var childFolders = folder.getFolders();
while (childFolders.hasNext()) { // Iterate through folders in folder
var childFolder = childFolders.next();
var childFolderName = childFolder.getName();
getChildFiles(
folderName + ' |--> ' + childFolderName,
childFolder,
sheet
);
}
}

Get external URL and save to Drive

I want to take a PDF URL and save it to Drive. The folder ID and URL are correct.
function uploadDoc(){
var folder = DriveApp.getFolderById('my_folder_id');
var url = 'my_url';
var blob = UrlFetchApp.fetch(url);
var blob2 = blob.getAs('appl‌​ication/pdf');
var newFile = folder.createFile('filename.pdf',blob2);
}
When I run this, I get:
Exception: Converting from binary/octet-stream to appl‌​ication/pdf is not supported.
You'll need to fix two things:
After UrlFetchApp.fetch(url) you need to use the getBlob() method. The getAs('appl‌​ication/pdf') method is not strictly required.
If you are using a blob, then you need to use the createFile(blob) method.
You are using the createFile(name, content) method and in this method, content is string not blob.
Then to name of the new file, you'll need the setName(name) method.
function uploadDoc() {
var url = 'https://www.gstatic.com/covid19/mobility/2021-02-21_AF_Mobility_Report_en.pdf';
var foID = 'my_folder_id';
var folder = DriveApp.getFolderById(foID);
var blob = UrlFetchApp.fetch(url).getBlob();
var newFile = folder.createFile(blob).setName('filename.pdf');
}

Drive Folder ID from file

after the renewal of DriveApp API I'm struggling to update my script.
It was able to find the Drive Folder ID starting from a file.
Basically starting from a Spreadsheet, I found what was the ID of the folder that contained the file.
Now if i try:
var thisFile =(the file I have)
var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents()[0];
var targetFolder = DriveApp.getFolderById(parentFold);
targetFolder.addFile(newFile);
The system sends an error at line 4 "No item with the given ID could be found, or you do not have permission to access it." (even if I open all the permissions).
Any suggestion?
Thanks!
The getParents() method returns a FolderIterator. It doesn't return the folder ID. You need to get the folder:
var folder = folders.next();
The code given assumes that there is only one parent folder to the file.
Updated Answer:
function copyToParent() {
var thisFile = DriveApp.getFileById('file ID');
//var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents();//Get all parents - normally just one parent
var folder = parentFold.next();//Get the first parent folder
//Logger.log('folder name: ' + folder.getName());//For testing - log folder name
folder.addFile(newFile);
}
Old Answer:
This answer has unneeded steps.
Then get the ID of the folder:
var theId = folder.getId();
Full code:
function copyToParent() {
var thisFile = DriveApp.getFileById('file ID');
//var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents();
var folder = parentFold.next();
var theId = folder.getId();
var targetFolder = DriveApp.getFolderById(theId);
Logger.log('targetFolder name: ' + targetFolder.getName());
targetFolder.addFile(newFile);
};

Check Google site if page name already exists when uploading folders

I am uploading folders to a created google site using appscript, but sometimes an error occures during which the code is uploading the filenames to the site as a parentpage and does not finish uploading all hte file names. So, when I restart the code it will throw an error saying that a page with that name already exists. Is there a way to do an if statement around the create page portion of code so that it checks to see if the name already exists. the code is provided below,
while (folders.hasNext()) {
var folder = folders.next();
if (folder.getName() == "Work_Orders(Evadale)3"){
Logger.log("I made it into the uploads folder");
var subFolders = folder.getFolders();
while(subFolders.hasNext()){
var subFolder = subFolders.next();
var files = subFolder.getFilesByType('text/html');
var stringChange = subFolder.getName();
var parentname = stringChange.replace(" ","-");
for (var c = 0; c<5; c++){
parentname = parentname.replace(" ","-");
parentname = parentname.replace("#","_");
parentname = parentname.replace("(","-");
parentname = parentname.replace(")","-");
parentname = parentname.replace("&","and");
}
Logger.log(parentname);
Logger.log("About to enter the if statement");
var pageParent = site.createWebPage(parentname, parentname, "");
var counter = 0;
while (files.hasNext()){
Logger.log(maxFiles);
var file = files.next();
var html = file.getBlob();
var datas = html.getAs('text/plain');
var infoString = datas.getDataAsString(); //this has a quota, see if this can be done some other way?
var name = file.getName();
Logger.log(name);
name = name.replace(".html","");
cache.put("parent"+maxFiles,parentname);
cache.put("child"+maxFiles, name);
cache.put("infoString"+maxFiles, infoString);
maxFiles++;
}
Logger.log("Counter"+counter);
Logger.log("maxFiles"+maxFiles);
Logger.log("Just exited the if statement");
cache.put("counter", counter);
}
}
cache.put("maxFiles", maxFiles);
cache.put("begin", begin);
cache.put("end",end);
}
Maybe you could use the getAllDescendants() method?
Google Documentation - getAllDescendants()
That would get you an array of descendant page names. Then you could use the JavaScript indexOf() method of the array name to check if the page name exists in the array.
JavaScript indexOf() method