I am attempting to create a form in Google Spreadsheets which will pull an image file from my Drive based on the name of the file and insert it into a cell. I've read that you can't currently do this directly through Google Scripts, so I'm using setFormula() adn the =IMAGE() function in the target cell to insert the image. However, I need the URL of the image in order to do this. I need to use the name of the file to get the URL, since the form concatenates a unique numerical ID into a string to use the standardized naming convention for these files. My issue is that, when I use getFilesByName, it returns a File Iteration, and I need a File in order to use getUrl(). Below is an snippet of my code which currently returns the error "Cannot find function getUrl in object FileIterator."
var poNumber = entryFormSheet.getRange(2, 2);
var proofHorizontal = drive.getFilesByName('PO ' + poNumber + ' Proof Horizontal.png').getUrl();
packingInstructionsSheet.getRange(7, 1).setFormula('IMAGE(' + proofHorizontal + ')');
If you know the file name exactly, You can use DriveApp to search the file and getUrl()
function getFile(name) {
var files = DriveApp.getFilesByName(name);
while (files.hasNext()) {
var file = files.next();
//Logs all the files with the given name
Logger.log('Name:'+file.getName()+'\nUrl'+ file.getUrl());
}
}
If you don't know the name exactly, You can use DriveApp.searchFiles() method.
You're close - once you have the FileIterator, you need to advance it to obtain a File, i.e. call FileIterator.next().
If multiple files can have the same name, the file you want may not be the first one. I recommend checking this in your script, just in case:
var searchName = "PO + .....";
var results = DriveApp.getFilesByName(searchName);
var result = "No matching files";
while (results.hasNext()) {
var file = results.next();
if (file.getMimeType() == MimeType. /* pick your image type here */ ) {
result = "=IMAGE( .... " + file.getUrl() + ")");
if (results.hasNext()) console.warn("Multiple files found for search '%s'", searchName);
break;
}
}
sheet.getRange( ... ).setFormula(result);
You can view the available MimeTypes in documentation
Related
I'm trying to make a program where if a document doesn't exist yet, create it, but if it does, edit it.
I tried to do it like this:
if(check == false){
var doc = DocumentApp.create('Announcements for '+ data[0][2]);
}
else{
var doc = DocumentApp.openById('Announcements for '+ data[0][2]);
}
Here, 'check' is true when the file exists, and false if it doesn't.
I'm assuming that the problem is that I'm using 'openById' incorrectly.
What is the document id, and how can my code know what it is?
Thanks in advance!
(First-time user here, sorry for any formatting errors)
edit: I'll be making multiple docs, and all I know about the doc I need to open is its name
The parameter of openById() is the file id of the document you are trying to access. File id is the value between the "/d/" and the "/edit" of your Google Document URL.
Example: https://docs.google.com/document/d/12345/edit where 12345 is the id.
DocumentApp does not have method for opening documents using file name. The only available methods are openById() and openByUrl().
An alternative is to use DriveApp to get the name, id, and mimetype of the files inside your Drive or Drive folder.
Example:
The code below will open a document if it matches the fileName 'Announcement 1' :
Code:
function openByName() {
//open specific folder and get the files
var files = DriveApp.getFolderById('insert folder id here').getFiles();
var fileName = 'Announcement 1';
//The code below will search for Announcement 1 file and open it if found.
while (files.hasNext()) {
var file = files.next();
var fileType = file.getMimeType();
//Check if the filename matches 'Announcement 1' and the file type should be google-apps.document
if(file.getName() == fileName && fileType == 'application/vnd.google-apps.document'){
//Open document
DocumentApp.openById(file.getId());
}
}
}
Test Folder:
References:
Class DocumentApp
Class DriveApp
new to Google Scripts and I've looked through other posts on Stack Overflow as well but couldn't find a good answer.
I'm using data collected in Google Sheets to search for a file in Google Drive and transfer ownership of the file. I have google form that my users fill out, once submitted using an add-on I create a file based on the data that was submitted on the form. Now with the script, I'm trying to go gather certain information from sheets such as name, email, and company name -
Sample data image here.
What I have thus far:
function myFunction() {
//Get google sheets
var spreadsheetId = '1WvIIoYdmuIB5BQ3KgSYOOIiEn-K_GTzCkb7rITzRFck';
//get certain values from sheets
var rangeName = 'MDP Form!C25:E';
var values = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeName).values;
if (!values) {
Logger.log('No data found.');
} else {
Logger.log('Name, Email, Customer:');
for (var row = 0; row < values.length; row++) {
// Print columns C and E, which correspond to indices 0 and 4.
Logger.log('Name: %s, Email: %s, Company: %s', values[row][0], values[row][1], values[row][2]);
//Utilities.sleep(90000);
//Searching through google drive
var name = (values[row][0]);
var email = (values[row][1]);
Logger.log(email);
var company = (values[row][2]);
var fileName = ('Mutual Delivery Plan ' + company + ' - ' + name);
Logger.log(fileName);
//add a 1 minute delay
//Utilities.sleep(90000);
//search for target folder
var folder = DriveApp.getFolderById('1whvRupu9hWdyl2CqSF-KvdVj8VE6iiQu');
//search for file by name within folder
var mdpFile = folder.searchFiles(fileName);
//transfer ownership
mdpFile.setOwner(email);
}
}
}
Problem:
The script works for the most part except for the last line "setOwner" is not a function. I've tried creating a separate function for this, used some other suggestions on other posts but still cannot get this to work. If anyone has ideas around what might I be missing here or suggestions that would be super helpful. Thanks!
I believe your goal as follows.
You want to transfer the owner of the file when the file with fileName is found in folder.
For this, how about this answer?
Modification points:
Although you say The script works for the most part except for the last line "setOwner" is not a function., if your script in your question is the current script, how about the following modification?
In your script, fileName is 'Mutual Delivery Plan ' + company + ' - ' + name, and fileName is used with var mdpFile = folder.searchFiles(fileName);. In this case, an error occurs. Because params of searchFiles(params) is required to be the query string.
I think that in your case, it's "title='" + fileName + "'".
Also searchFiles(fileName) returns FileIterator. This has already mentioned by the existing answer. Because at Google Drive, the same filenames can be existing in the same folder and each files are managed by the unique ID. So here, it is required to be modified as follows.
I think that in your case, the following flow is useful.
Confirm whether the file is existing using hasNext().
When the file is existing and the owner is you, the owner of the file is changed to email.
When above points are reflected to your script, please modify as follows.
Modified script:
From:
var mdpFile = folder.searchFiles(fileName);
//transfer ownership
mdpFile.setOwner(email);
To:
var mdpFile = folder.searchFiles("title='" + fileName + "'");
while (mdpFile.hasNext()) {
var file = mdpFile.next();
if (file.getOwner().getEmail() == Session.getActiveUser().getEmail()) {
file.setOwner(email);
}
}
If you don't need to check whether the owner is you, please remove if (file.getOwner().getEmail() == Session.getActiveUser().getEmail()) {.
Note:
In this case, when the file with the filename of fileName is not existing in folder, the script in the if statement is not run. Please be careful this.
Also, when there are several files with the same filename in folder, the owner of those is changed to email.
References:
searchFiles(params)
FileIterator
hasNext()
next()
getActiveUser()
Folder.searchFiles() returns a fileIterator not a file. If it's the only file with that name then you can usually getaway with mdpFile.next();
File Iterator
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.
i use this code in upload form (google scripts):
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
however, i want to check if file exist with same name, then dont upload. How to do that?
Well that's simple enough. All you need to do is use the getFilesByName() and the use the hasNext() to see if any files were found:
var file = DriveApp.getFilesByName('name of file to upload')
var chk = file.hasNext()
if (chk === true) return 1
if a file with the name was found, then hasNext() will return true. That means that we need to stop the script. You can do throw instead of a return, but that is up to you. The whole thing can also be in one line
if DriveApp.getFilesByName('filename').hasNext() === true) return 1
Can I overwrite an image file with Google Apps Script? I've tried:
file.setContent(newBlobImage);
file.replace(newBlobImage);
Neither of those work. .setContent() will delete whatever data was in the file, and it looks like maybe it just writes the variable name as text, or something like that. I'm assuming that both .setContent() and .replace() are meant for text documents, and maybe that's why they don't work.
If it were a text file, or a spreadsheet, I might be able to clear it, then append new content.
I can trash the file, then create a new one, but I'd rather not if there is some other way.
If I write a file with the same name, it won't overwrite the existing file, it creates a another file with the same name.
The only way I've been able to trash the file is with DocsList and the only success I've had with creating an image file is with DriveApp. So I have to trash the file with DocsList, then create another file with DriveApp.
Well, I've figured out how to delete the file without sending it to the trash, so I won't need to clean out the trash later. The Google Drive SDK inside of Apps Script has a remove method that didn't send the file to trash, it's just gone.
var myFolder = DriveApp.getFolderById('3Bg2dKau456ySkhNBWB98W5sSTM');
thisFile = myFolder.getFilesByName(myFileName);
while (thisFile.hasNext()) {
var eachFile = thisFile.next();
var idToDLET = eachFile.getId();
Logger.log('idToDLET: ' + idToDLET);
var rtrnFromDLET = Drive.Files.remove(idToDLET);
};
So, I'm combining the DriveApp service and the DriveAPI to delete the file without sending it to the trash. The DriveAPI .remove needs the file ID, but I don't have the file ID, so the file gets looked up by name, then the file ID is retrieved, then the ID is used to delete the file. So, if I can't find a way to overwrite the file, I can at least delete the old file without it going to the trash.
I just noticed that the DriveAPI service has a Patch and an Update option.
.patch(resource, fileId, optionalArgs)
Google Documentation Patch Updates file metadata.
The resource arg is probably the metadata. The fileId is self explanatory. I'm guessing that the optionalArgs are parameters that follow the HTTP Request Patch semantics? I don't know.
It looks like both Patch and Update will update data. Update is a PUT request that will
clears previously set data if you don't supply optional parameters.
According to the documentation. So it's safer to use a Patch request because any parameters that are missing are simply ignored. I haven't tried it yet, but maybe this is the answer.
I'm getting an error with Patch, so I'll try Update:
.update(resource, fileId, mediaData)
That has a arg for mediaData in the form of a blob. And I think that is what I need. But I'm not sure what the resource parameter needs. So I'm stuck there.
An image file can be overwritten with Google Apps Script and the DriveAPI using the update() method:
.update(File resource, String fileId, Blob mediaData)
Where file resource is:
var myFileName = 'fileName' + '.jpg';
var file = {
title: myFileName,
mimeType: 'image/jpeg'
};
I'm getting the file ID with the DriveApp service, and the Blob is what was uploaded by the user.
In order to use DriveAPI, you need to add it through the Resources, Advanced Google Services menu. Set the Drive API to ON.
var allFilesByName,file,myFolder,myVar,theFileID,thisFile;
//Define var names without assigning a value
file = {
title: myFileName,
mimeType: 'image/jpeg'
};
myFolder = DriveApp.getFolderById('Folder ID');
allFilesByName = myFolder.getFilesByName(myFileName);
while (allFilesByName.hasNext()) {
thisFile = allFilesByName.next();
theFileID = thisFile.getId();
//Logger.log('theFileID: ' + theFileID);
myVar = Drive.Files.update(file, theFileID, uploadedBlob);
};
Thank you for this track !
This allowed me to find a solution to my problem : move a bound form after copying and moved his spreadsheet.
The Drive app advanced service must be activated in the "Resource Script Editor" to run this script.
function spreadsheetCopy() {
// Below is the file to be copied with a bound form.
var fileToCopy = DriveApp.getFileById("file_key"); // key is fileId
var saveFolder = DriveApp.getFolderById("folder_key"); // key is folderId
var currentFolder = "";
( fileToCopy.getParents().next() ) ? currentFolder = fileToCopy.getParents().next() : currentFolder = DriveApp.getRootFolder();
Logger.log(currentFolder)
var copyFile = fileToCopy.makeCopy(saveFolder),
copyName = copyFile.getName();
Utilities.sleep(30000);
moveFormCopy(currentFolder, saveFolder, copyName);
}
function moveFormCopy(currentFolder, saveFolder, copyName) {
var formsInFolder = currentFolder.getFilesByType(MimeType.GOOGLE_FORMS);
var form, copyForm, copyFormMimeType, copyFormName, copyFormId;
while ( formsInFolder.hasNext() ) {
form = formsInFolder.next();
if ( copyName === form.getName() ) {
copyForm = form;
copyFormMimeType = copyForm.getMimeType();
copyFormName = copyForm.getName();
copyFormId = copyForm.getId();
break;
}
};
var resource = {title: copyName, mimeType: copyFormMimeType};
Drive.Files.patch(resource, copyFormId, {addParents: saveFolder.getId(), removeParents: currentFolder.getId()})
}