I'm trying to write a script that will sort large numbers of photos and videos on Google Drive into folders that make it easier for my wife to find what she's looking for. Unfortunately, she has to use Drive rather than Google Photos, so she doesn't have access to the much more robust sorting functionality that Photos would give her.
Warning: I'm not a programmer, so I really don't know what I'm doing. I think I'm telling the script what folder to look in and then telling it to search for files that meet certain criteria in terms of name of the file, but the script is returning null from its search results.
I have tried using both searchFiles (with "name contains [my string var]" as the param), and getFilesByName (with my string var as the param). In both cases, I'm getting named folders but no files.
var currDate = strMonth + strDay;
var photos = currFolder.getFilesByName(
"" + "2019" + currDate + "");
var activeFolder = currFolder.createFolder(currDate);
if (photos.hasNext()) {
myLog = Logger.log("HasNext");
} else {
myLog = Logger.log("Doesn't HasNext");
}
while ( photos.hasNext() ) {
var currPhoto = photos.next();
currPhoto.makeCopy(activeFolder);
myLog = Logger.log(currPhoto);
}
What I expect is that photos is a list of pictures the script has found, that can then be copied over to the folder I created. My debug logging always tells me hasNext() is FALSE, though, and this seems to agree with the fact that no files are getting copied into the folder.
Any help would be greatly appreciated. I'm sure I'm just doing something dumb. Thanks!
Here's an example that will display all of your JPEG files
function findJPEGFiles() {
var files=DriveApp.getFilesByType(MimeType.JPEG);
var html='<style>td,th{border:1px solid black;}</style><table><tr><th>Name</th><th>Id</th><th>Url</th></tr>';
while(files.hasNext()) {
var file=files.next();
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td></tr>',file.getName(),file.getId(),file.getUrl());
}
html+='</table>';
var userInterface=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Files');
}
Related
I'm trying to get a collection of files where user (let's use billyTheUser#gmail.com) is an editor.
I know this can be accomplished almost instantly on the front-end of google drive by doing a search for to:billyTheUser#gmail.com in the drive search bar.
I presume this is something that can be done in Google App Scripts, but maybe I'm wrong. I figured DriveApp.searchFiles would work, but I'm having trouble structuring the proper string syntax. I've looked at the Google SDK Documentation and am guessing I am doing something wrong with the usage of the in matched to the user string search? Below is the approaches I've taken, however if there's a different method to accomplishing the collection of files by user, I'd be happy to change my approach.
var files = DriveApp.searchFiles(
//I would expect this to work, but this doesn't return values
'writers in "billyTheUser#gmail.com"');
//Tried these just experimenting. None return values
'writers in "to:billyTheUser#gmail.com"');
'writers in "to:billyTheUser#gmail.com"');
'to:billyTheUser#gmail.com');
// this is just a test to confirm that some string searches successfully work
'modifiedDate > "2013-02-28" and title contains "untitled"');
Try flipping the operands within the in clause to read as:
var files = DriveApp.searchFiles('"billyTheUser#gmail.com" in writers');
Thanks #theAddonDepot! To illustrate specifically how the accepted answer is useful, I used it to assist in building a spreadsheet to help control files shared with various users. The source code for the full procedure is at the bottom of this post. It can be used directly within this this google sheet if you copy it.
The final result works rather nicely for listing out files by rows and properties in columns (i.e. last modified, security, descriptions... etc.).
The ultimate purpose is to be able to update large number of files without impacting other users. (use case scenario for sudden need to immediately revoke security... layoffs, acquisition, divorce, etc).
//code for looking up files by security
//Posted on stackoverlow here: https://stackoverflow.com/questions/62940196/return-collection-of-google-drive-files-shared-with-specific-user
//sample google File here: https://docs.google.com/spreadsheets/d/1jSl_ZxRVAIh9ULQLy-2e1FdnQpT6207JjFoDq60kj6Q/edit?usp=sharing
const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FileList");
const clearRange = true;
//const clearRange = SpreadsheetApp.getActiveSpreadsheet().getRangeByName("ClearRange").getValue();
//if you have the named range setup.
function runReport() {
//var theEmail= SpreadsheetApp.getActiveSpreadsheet().getRangeByName("emailFromExcel").getValue();
//or
var theEmail = 'billyTheUser#gmail.com';
findFilesByUser(theEmail);
}
function findFilesByUser(theUserEmail) {
if(clearRange){
ss.getDataRange().offset(1,0).deleteCells(SpreadsheetApp.Dimension.ROWS)
}
var someFiles = DriveApp.searchFiles('"' + theUserEmail + '" in writers');
var aListOfFiles = []
while(someFiles.hasNext()){
var aFile = someFiles.next();
aListOfFiles.push([aFile.getId()
,aFile.getName()
,aFile.getDescription()
,aFile.getSharingAccess()
,aFile.getSharingPermission()
,listEmails(aFile.getEditors())
,listEmails(aFile.getViewers())
,aFile.getMimeType().replace('application/','').replace('vnd.google-apps.','')
,aFile.getDateCreated()
,aFile.getLastUpdated()
,aFile.getSize()
,aFile.getUrl()
,aFile.getDownloadUrl()
])
}
if(aListOfFiles.length==0){
aListOfFiles.push("no files for " + theUserEmail);
}
ss.getRange(ss.getDataRange().getLastRow()+1,1, aListOfFiles.length, aListOfFiles[0].length).setValues(aListOfFiles);
}
function listEmails(thePeople){
var aList = thePeople;
for (var i = 0; i < aList.length;i++){
aList[i] = aList[i].getEmail();
}
return aList.toString();
}
I have hundreds of Google Docs, and lots of Google Folders. They share a common string in the filename. The Docs need to go into the corresponding Folder, and I'd like to automate this with some Script.
What I want to do is as follows:
I have hundreds of Google Docs which follow a similar pattern in the filename:
SURNAME, Forename_userID_fileName
So for instance,
DOE, Jane_jd5678_Document3
PUBLIC, Tom_tp9123_reportTPS
SMITH, John_js1234_finaldocument
and so on and so forth.
I also have corresponding Folders in a Google Team Drive, set up as follows:
SURNAME, Forename (userCode) (userID) - userType
So for instance,
DOE, Jane (145374578) (jd5678) - AET Full Time
PUBLIC, Tom (673468714) (tp9123) - NR Full Time
SMITH, John (874512456) (js1234) - AET Part Time
The common string between the files and the folder names is the userID string.
Currently I download all the Docs, and then upload drag-and-drop into each corresponding folder. Takes ages! I was hoping there is a bit of Apps Script that I can do to automate this but I really don't know where to start at all. Anyone have any pointers?
This StackOverflow question seems to want to do what I want to do, but as I'm such a beginner with Apps Script I can't really decipher the solution.
This is a basic example to point you in the right direction using the basic Google Apps Script DriveApp (as opposed to the advanced Script Services version or other Google Drive API methods). The main concern that comes to mind is the script timing out if this example takes too long to complete. If that happens, you'll need a more complex solution. You could also chunk it up by having the idRegex only work on, e.g., surnames A-D then E-G, etc. The example regular expression could match random files you have with underscores; you may want to find a more complicated regular expression if that is a concern.
function organizeFilesById() {
var idRegex = /_[A-z]+[0-9]+_/;
var files = DriveApp.getFiles();
while (files.hasNext()) {
var file = files.next();
var filename = file.getName();
var id = idRegex.exec(filename);
if (! id) {
continue;
} else {
id = id[0];
}
var query = "title contains '" + id + "'";
var folders = DriveApp.searchFolders(query);
if (folders.hasNext()) {
var folder = folders.next();
Logger.log("Will add %s to %s", filename, folder.getName());
//folder.addFile(file); // uncomment line to actually do it
} else {
Logger.log("No folder found for %s", filename);
// could create folder or just report "folder not found"
}
}
}
This question already has answers here:
How to get the file URL from file name in Google Sheets with correct Authorization via custom function/script
(3 answers)
Closed 4 years ago.
The code below generates the IMAGE function for the sheet to show thumbnails of all (PDF) files in a chosen folder, obtained with a URL and the file ID:
function scannedMail() {
var files, file, sheet;
sheet = SpreadsheetApp.getActive().getSheetByName('ScannedMail');
files = DriveApp.getFoldersByName("ScannedMail").next().searchFiles('');
var i = 1;
while (files.hasNext()) {
var file = files.next();
var ID = file.getId();
sheet.getRange('A' + i).setValue("=IMAGE(\"https://drive.google.com/thumbnail?authuser=0&sz=w320&id=" + ID + "\"\)");
sheet.getRange('B' + i).setValue(file.getName());
i=i+1;
}
}
Yet it does not show the thumbnails. I found out that it shows just the ones where I manually retrieved the ID from getting a "shareable link". Apparently this ensures the right share settings to get the thumbnails of my own files.
1) Is the previous assumption correct, and why do I need to adapt share settings somehow, where I have read other files without any issues?
2) How can I adapt the script to adapt the share settings, or make it work otherwise?
The script is meant to operate just within my own Google account, and to keep the files private.
I tried sharing the folder with myself, but that does not make a difference (or sense). Is the script somehow regarded as being another user than myself?
Following suggestions from #Rubén and #Cooper, I have tried using insertImage either based on a URL:
sheet.insertImage(file.thumbnailLink, 1, i)
or based on a blob:
sheet.insertImage(file.getThumbnail(), 1, i)
But the most I could get out of Google was "We're sorry, a server error occurred. Please wait a bit and try again", with the code below:
function ScannedMail() {
var files, file, , name, blob, sheet;
sheet = SpreadsheetApp.getActive().getSheetByName('ScannedMail');
files = DriveApp.getFoldersByName("ScannedMail").next().searchFiles('');
var i = 1;
while (files.hasNext()) {
file = files.next();
name = file.getName(); //not needed, just for debugging
blob = file.getThumbnail();
sheet.insertImage(blob, 1, i); // it runs up to here...
i = i + 1;
}
}
The code execution gets stuck on the first occurrence of insertImage().
So we have 3 approaches (IMAGE function in sheet, insertImage(URL,1,1), and insertImage(blob,1,1)) but all 3 do not make a thumbnail appear, apart from the first method when you make the file public (not a serious option).
I don't see a duplicate question and answer that helps me find out what is wrong with my code, or helps me to somehow get the required thumbnails in the spreadsheet. The kindly proposed solutions did not succeed in that yet.
Try something like this:
function imgArray() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('ImageArray');
if(!sh){
sh=ss.insertSheet('ImageArray');
}
var imgA=[];
var folder=DriveApp.getFolderById('folderid');
var files=folder.getFiles();
while(files.hasNext()){
var file=files.next();
var filename=file.getName();
imgA.push(file.getBlob());
}
for(var r=0;r<imgA.length;r++){
sh.insertImage(imgA[r],1,r+1);
}
}
This was adapted from an answer from #Tanaike.
I guess this is what you were looking for:
function ScannedMail() {
var sheet = SpreadsheetApp.getActive().getSheetByName('ScannedMail');
var files = DriveApp.getFoldersByName("ScannedMail").next().searchFiles('');
var i = 1;
while (files.hasNext()) {
var file = files.next();
var blob = file.getBlob();
sheet.insertImage(blob, 1, i); // it runs up to here...
i = i + 1;
}
}
Google Sheets IMAGE built-in function only is able to retrieve images that are publicly available, so, yes you should have to adapt the sharing settings to make the images viewable by anyone.
In order to keep the files private you should not use IMAGE built-in function, you could use one of the methods of Class Sheet to insert images like insertImage(blobSource,column,row). See answer to Adding Image to Sheet from Drive for an example.
NOTES:
As custom functions run anonymously they can't be used them either.
According to Mogsdad answer to InsertImage(url,x,y) doesn't work with Google Drive insertImage(url,row,column) can't be used to insert images from Google Drive
Related
Image function or .insertImage not working for Google Apps Script and Sheets
What is the right way to put a Drive image into a Sheets cell programmatically?
I'm hoping to make (what I hoped was) a very basic script, where you can type part of a document name into a Google Spreadsheet, and underneath will appear the files in your Drive that have that word in their title.
As an example, I have two files in my Drive called "Rome Adventure" and "London Adventure", and the idea would be that if you typed "Rome", "London", or "Adventure" into a cell, the file titles would appear below.
So far I've got this:
function onEdit(e){
// Gets the edited cell, turns it into string
var activeSheet = e.source.getActiveSheet();
var range = e.range;
var input = range.getCell(1,1).getValue();
var SearchString = 'title contains "' + input + '"';
// Searches Drive for files with titles containing whatever you typed
// and appends titles to the spreadsheet
var result = DriveApp.searchFiles(SearchString);
while (result.hasNext()) {
var file = result.next();
activeSheet.appendRow([file.getName()]);
}
}
But unfortunately nothing is appended, regardless of what I enter. I've tried "Rome", "London", and just about everything else I can think of. Thinking I might have stuffed up something in the first section, I added
range.setNote('Last modified: ' + new Date());
in between the two sections, and that worked. So it's definitely just the DriveApp.searchFiles that I've stuffed up. I thought I might have stuffed up the StringSearch bit, but changing the line to
var result = DriveApp.searchFiles('title contains "Rome"');
still doesn't return anything.
I'm only an enthusiast-level programmer, and this is the first time I've asked a question on here. So forgive me if this is a stupid question, or it's not possible. I'm just at my wit's end trying to get this to work.
Nothing is wrong with your function. It's failing because of an undocumented restriction using the onEdit trigger to search DriveApp. If you run the script as is and then go to View > Execution transcript, you'll see the failure message at the bottom.
You can call the function successfully from a custom menu. Instead of watching for the edited row, use .getActiveCell(). It will search the string inside the selected cell on the spreadsheet. A working example is below.
function onOpen() {
SpreadsheetApp.getUi().createMenu("Search").addItem("Run", "searchFiles").addToUi();
}
function searchFiles() {
var string = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getValue();
var result = DriveApp.searchFiles('title contains "' + string + '"');
while (result.hasNext()) {
var file = result.next();
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().appendRow([file.getName()]);
}
}
I hope I have searched good enough in order to ask this questions.
I have this code to clean up some default files in our team drive, if somebody got them in sync by accident...
In this case desktop.ini
function cleanup(){
var folderID = 'FOLDERID';
var search = 'title Contains "desktop.ini"';
var fileIDs = [];
var files = DriveApp.searchFiles(search);
while (files.hasNext()){
files.next().setTrashed(true);
}
Logger.log('fileIDs.length + ' files have been moved to trash');
}
Is there a way to add multiple hits in one search?
What if I would want to add other files like "thumbs.db" or from the mac guys ".DS_Store". Do I need to search for everything individually or is there a .gitignore way to solve it?
How about this? When you want to retrieve the files with the filenames which contained "desktop.ini", "thumbs.db" and ".DS_Store" in one search using DriveApp.searchFiles(), you can achieve it using or operator as follows.
var search = 'title contains "desktop.ini" or title contains "thumbs.db" or title contains ".DS_Store"';
Reference :
https://developers.google.com/drive/v3/web/search-parameters