Google Apps Script moving file to Team Drive folder - google-apps-script

Background:
At the core of the issue is I have an Alteryx job dropping files into my google drive. These files need, in actuality, in a Team Drive folder. Try as I might, nowhere have I found a way for Alteryx to do this. So hence the need for this script.
Actual problem:
So here is the criteria: I have the files being created with the same naming convention with only the date changing. I need these files to go from my drive to a team drive where they are eventually worked on.
Using the resources already here on stack I found wonderful solutions here: 1 and here 2 that I was able to cobble together a working script.
Understand I am a marginally functional python programmer for data analytics. So my JS and Google scripting are rudimentary at best. The first time I tested the script, it worked. Wonderfully, right up until it didn't.
It moved my first file with no problem. I then created a few copies of that same file in the drive to see how it handled multiple. I now get an error:
Exception: No item with the given ID could be found, or you do not
have permission to access it. (line 15, file "CodeA1")
Here is my code:
function SearchFiles() {
//searches based on naming criteria
var searchFor ='title contains "Reference Data Performance"'; //test file
var names =[];
var fileIds=[];
var files = DriveApp.searchFiles(searchFor);
while (files.hasNext()) {
var file = files.next();
var fileId = file.getId();// To get FileId of the file
fileIds.push(fileId);
var name = file.getName();
names.push(name);
}
var file = DriveApp.getFileById(fileIds);
supportsTeamDrives: true;
supportTeamDrives: true;
var targetFolder = DriveApp.getFolderById('TEAMDriveID');
targetFolder.addFile(file);
}

Exception: No item with the given ID could be found, or you do not
have permission to access it.
This error occurs most often if either
The TeamDriveId is not correct
The account from which you run the script is not member of the team drive
Also note:
supportsTeamDrives: true;
supportTeamDrives: true;
are parameters
for the Drive API, not to be confused with DriveApp

Update:
I ended up going with a simplified version of this script. I had Alteryx schedule the file creation (three different files) at hour increments. Then made a trigger in Google Apps to run the script at the times directly after each Alteryx scheduled drop. Simple? Yes. Inelegant? Maybe. Been running all week and files arrive at their destination for people to work on.
function SearchFiles() {
//searches based on naming criteria
var searchFor ='title contains "Reference Data Performance"'; //looks for file that matches requirements
var files = DriveApp.searchFiles(searchFor);
while (files.hasNext()) {
var file = files.next();
var fileId = file.getId();// To get FileId of the file
var file = DriveApp.getFileById(fileId); //grabs file ready to pass to google drive.
supportsTeamDrives: true;
supportTeamDrives: true;
var targetFolder = DriveApp.getFolderById('FOLDERID');
targetFolder.addFile(file);//good for getting a single file needs loop to grab multiple from Array
}
}

Related

google apps script. copy files to one drive

I would have files stored in google drive and I would like to copy (or move) those files to my OneDrive. I have managed to connect OneDrive to google drive and I can successfully create folders and upload files by file ID. I am trying to copy (or move) multiple files at once from google drive to OneDrive though without any luck yet. I am not good at programming just doing everything by tutorials only but yet could not find any working one. Maybe anyone could guide me how to do it? For the final idea I would like to achieve that files from google drive would be copied even to separate folders by the part of file title (name and surname, if to be exact). Currently I have "developed" such script:
function moveFiles(source, dest_folder) {
var source = DriveApp.getFolderById("1faFbaXJNziwIGyer2H2IPALQ8ahBfGMc");
var prop = PropertiesService.getScriptProperties();
var odapp = OnedriveApp.init(prop);
var files = DriveApp.getFiles();
while (files.hasNext()) {
var file = files.next();
var dest_folder =
OnedriveApp.init(PropertiesService.getScriptProperties()).uploadFile(files,
"/samplefolder");
}
}
I believe your current situation and your goal are as follows.
You are using OnedriveApp.
You have already been finished the authorization process. So you have already been had the access token and refresh token in the PropertiesServices.
You want to upload the files in a specific folder of Google Drive to a specific folder in OneDrive.
The number of files is 10 - 20.
The file size is small.
From your following reply
I have changed accordingly to: var files = file.getId(); but then I receive such error: TypeError: Cannot read property 'getId' of undefined moveFiles # srcpt.gs:5 If I use DriveApp.getFiles() or source.getFiles(), I receive such error: Exception: Unexpected error while getting the method or property getFileById on object DriveApp. convToMicrosoft # code.gs:629 OnedriveApp.uploadFile # code.gs:460 Appreciated for any help.
About var files = file.getId(); and If I use DriveApp.getFiles() or source.getFiles(), I receive such error:, unfortunately, I cannot understand it.
In this case, how about the following modification?
Modified script:
function myFunction() {
var prop = PropertiesService.getScriptProperties();
var odapp = OnedriveApp.init(prop);
var source = DriveApp.getFolderById("###"); // Please put your folder ID.
var files = source.getFiles();
while (files.hasNext()) {
var file = files.next();
odapp.uploadFile(file.getId(), "/samplefolder/"); // Please set the destination folder name. In this case, the folder name in OneDrive.
}
}
When "/samplefolder" is used, an error occurs. Please enclose the folder name by / like "/samplefolder/". Please be careful about this.
When this script is run, the files in the specific folder of Google Drive are copied to the destination folder of /samplefolder/ in OneDrive.
References:
OnedriveApp
getFolderById(id)
getFiles()

How do I retrieve and store files and folders structure in a google spreadsheet using apps script?

I know this question has been asked before, but I am trying to go a bit deeper in the problem. I have this apps script code I have taken online and I am using it in a google spreadsheet, to scan for a list of folders.
In short, I have a (shared) folder structure with most likely over 1000 sub-folders, which contain sub-subfolders, that looks similar to this:
MAIN FOLDER
FOLDER 1
FILE 1.1
SUBFOLDER 1.A
SUBFILE 1.A.2
SUBFILE 1.A.3
FOLDER 2
FILE 2.1
SUBFOLDER 2.A
SUBFILE 2.A.2
SUBFILE 2.A.3
FOLDER 3
FILE 3.1
SUBFOLDER 3.A
SUBFILE 3.A.2
SUBFILE 3.A.3
...
I am trying to fix 2 things:
1) My function obviously breaks when running because there are too many folders and files. I don't think it's due to the limit of rows in a spreadsheet. So, ideally, I would have to manually batch 200 folders in the main folder, run the function, and re-iterate. Any hints how to avoid that, and how to potentially, dump temporary results in a first spreadsheet and create a new spreadsheet if it's a caching problem?
2) I am not able to retrieve subfolders details and the details of the files it contains. Can anyone help adapt the code to go deeper in the folder hierarchy? Do I need some kind of loop function here?
With the code provided hereunder which I have used and tested a few times, I can only retrieve the folders 1,2,3 and files 1.1, 2.1, 3.1...but not subfolders or subfiles.
Fixing this function, would save me weeks of manual work. Any help is welcomed. Thanks in advance for your help.
function getAndListFilesInFolder() {
var arr,f,file,folderName,subFolders,id,mainFolder,name,own,sh,thisSubFolder,url;
sh = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
sh.getRange(1, 1, 100, 10).clear({contentsOnly: true})
id = "FOLDER ID HERE";
arr = [["FILE NAME", "URLs", "OWNER","FOLDER"]];
mainFolder = DriveApp.getFolderById(id);
subFolders = mainFolder.getFolders();
folderName = mainFolder.getName();
f = mainFolder.getFiles();
while (f.hasNext()) {
file = f.next();
name = file.getName()
url = file.getUrl()
own = file.getOwner().getName()
arr.push([name, url, own, folderName]);
};
while (subFolders.hasNext()) {
thisSubFolder = subFolders.next();
f = thisSubFolder.getFiles();
folderName = thisSubFolder.getName();
while (f.hasNext()) {
file = f.next();
name = file.getName()
url = file.getUrl()
own = file.getOwner().getName()
arr.push([name, url, own,folderName]);
};
};
sh.getRange(1,1, arr.length, arr[0].length).setValues(arr);
sh.getRange(2,1, arr.length, arr[0].length).sort(1);
//var second = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2")
//second.activate()
}
The reason you aren't seeing any of the subfolders is because you are not actually adding them to your array (arr) at any time.
What you really need here is is to write a recursive function, which receives a folder and returns itself plus it's file's details details in an array. When you encounter a folder, you pass that folder back to the same function.
Investigate recursion and recursive functions.
Here is a brief example you could expand, it'll need some tweaking since I'm writing this off the top of my head:
function getFilesFromFolder(folder){
var arr = [];
arr.push([folder.getName(),folder.getUrl(),folder.getOwner().getName()])
var subfolders = folder.getFolders();
var files = folder.getFiles():
while(files.hasNext()){
arr.push(/*file details*/);
}
//recurse into subfolders here.
while(subFolders.hasNext()){
arr.concat(getFilesFromFolder(subFolders.next()); //notice how we call the function from within itself.
}
return arr;
}

How to open a spreadsheet only by name of the corresponding file in Google Sheets?

I need a way to open a spreadsheet only by having the name of the corresponding file and the folder where the file is located. What I'm trying to do is creating a temporary copy of an active spreadsheet and reading information from the copy file rather than the active one. But unfortunately this copy file won't have a constant ID and URL as it's going to be erased every time after the script is done, and re-created with the next running of the script.
What I already tried is using the URL of the temporary file in order to open the spreadsheet itself, as you can see below.
But it's not useful for me, as I don't have a constant URL of this file (as it will be erased in the end of the script and have a new URL with the next script). But I have a constant name of the file, as well as this will be the only file in the respective folder.
What I also tried is looking for methods to open file only using its name (which is "temp_copy" in a 'temp_folder'). But I didn't find a working solution.
var report = SpreadsheetApp.getActiveSpreadsheet();
var temp_folder =
DriveApp.getFolderById("1EAsvVcFjIw5iGTeF_SxxQJLVlaLHl_pR");
DriveApp.getFileById(report.getId()).makeCopy("temp_copy", temp_folder);
var temp_copy = SpreadsheetApp.openByUrl(' ');
var hiddenSheet = temp_copy.getSheetByName('DATE');
var lastRow = hiddenSheet.getSheetValues(1,1,1,1);
var sheet = temp_copy.getSheetByName('forCSV');
var lastColumn = sheet.getLastColumn();
var activeRange = sheet.getRange(1,2,lastRow,lastColumn);
What I'm expecting as a result is to make the link between the 3rd line of the code (when making a copy of the basic file) and 5th line of the code onwards (when referencing specific range from the temporary file) only by using name of the file or respective folder. In theory it seems so easy, I should be missing something somewhere...
Many thanks in advance!
You can use DriveApp to get a FileIterator which contains the Sheet.
var file, files = DriveApp.getFilesByName("temp_copy");
if (files.hasNext ()){
file = files.next(); // Get first result for name
} else {
return "";
}
var sheet = SpreadsheetApp.openById(file.getId())

Google apps script: How to create a downloadable html file?

Starting with 'google apps script'. I've created a simple script that logs some information with 'Logger.log("message");' with this lines being in a loop, so the log message is quite large.
I'd like now to create an html file with that same information and either being able to download that file locally or have it downloaded to my google drive.
Any idea how that could be achieved? I've tried looking examples for a while but I cannot have anything working...
Many thanks!
Yes you can, you should read first. Have a look this documentation
function createMyHTMLlog()
{
var folders = DriveApp.getFoldersByName('ff');// ff:your folder name on drive
if (folders.hasNext())
{
var folder = folders.next(); //select the folder
folder.createFile('Log','<b> your message here </b>', MimeType.HTML); //create the file
}
}
Update: Add more content later
function logUpdate()
{
var children = folder.getFilesByName('Log');// log is the created file name
if (children.hasNext())
{
var file = children.next();
var logContent = file.getAs('text/plain').getDataAsString();// get available msg
logContent = logContent.concat('<br>your<b> updated message </b> here'); // combine with new msg
file.setContent(logContent);
}
}

Downloading multiple files from google addon

Hi I'm trying to download multiple files from a google folder as txt. I'm using the google script. So far my code will successfully download the first file from a folder but it stops and wont download the rest of the files in that folder. Thanks
function doGet() {
var folder = DriveApp.getFolderById('FolderKeyHere')
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName());
var id = file.getId();
var doc = DocumentApp.openById(id);
var string = doc.getBody().getText();
var output = ContentService.createTextOutput();
output.setMimeType(ContentService.MimeType.TEXT);
output.setContent(string);
output.downloadAsFile(file.getName());
return output;
};
};
This won't be possible like that, the return output; will actually "return" the app and of course exit the while loop.
I think you won't be able to loop this kind of process without user action.
You might build a small Ui that would have a button to download files one by one on each button click but I guess that's not what you are looking for.
Why not create all the files in your drive, compress all the files in a single zip file, download the zip and then delete the files and the zip from your drive ?
Slightly longer to write but -I think - the only useable workflow to get multiple files in a single download.