Move a shared file into My Drive using Google Script? - javascript

I am writing a script for my company that will automatically make a copy of a file in my own drive, then transfer ownership of the copy to a list of users from a spreadsheet. The script works completely except for that the file is created in the user's "All Files" and doesn't show up in their My Drive! Transferring ownership is not the problem I'm having, the problem is the location of the transferred file in the new owner's Drive.
I've tried sending it to their root folder but that didn't work, I'm not sure why? It sends it to My Drive for me, but it is copied into a folder that is already in My Drive for me (because I copy the file from a file that is in a folder in my drive already) but for anybody else on the list that the file is newly shared and transferred to, moving it to root does nothing and it remains in All Files without any labels on the file.
Does anybody have an idea how to move it automatically?
Here is the code that I've been using that works for my own My Drive but nobody else's on the list:
//Take new file out of parent folders
var folders = newDoc.getParents(); //get parents
for (var j = 0; i < folders.length; i++){ //loop through & delete parents
DocsList.getFileById(newDocId).removeFromFolder(folders[i]); //using DocsList
}
var root = DocsList.getRootFolder(); //Get root
DocsList.getFileById(newDocId).addToFolder(root); //add to my drive
edit: I was told that transferring ownership should automatically put it into the My Drive file but that isn't happening??
edit 2: I've tried using "addFile()" which SHOULD add it to My Drive folder in the user's folders, but it only adds it to the my drive of the person running the script and the rest of the users STILL get it only in their "All Items" folder. This is driving me nuts, someone please help ;C

So after a few days of driving myself INSANE and asking around literally everywhere I could think of we finally got word that this is an effect of the new Google Drive UI Rollout, so apparently right now it's just like THIS now, until google fixes it :C
WHAT AN UNSATISFYING ENDING.

Unfortunately, it's not going to be possible exactly the way you describe.
As you've found, the file ownership can be changed. That's because you own the file and the file is accessible by Script through the authorization you granted to your Drive account.
Placing a file into a location on a different user's Drive is not possible because the script has no privilege to set a location on a Drive it knows nothing about.
However, it would be possible to set the location by running a script under each user account, but obviously that's a little arduous to setup and maintain.
One other option: If you use GAM (Google Apps Manager) it IS possible to make changes across accounts. This is because GAM is run under admin user access. Example from the GAM site:
This example updates the "My Ramblings" file to be starred and placed under a folder called "Brilliant things I've said" (assumes a folder by that name already exists for the user)
gam user bsmith#acme.com update drivefile drivefilename "My Ramblings" starred true parentname 'Brilliant things I've said'

Related

Adapt GAS script functions from a Spreadsheet to a Web Application

I'm new to GAS and JavaScript in general, so I'd like some help adapting a script from a spreadsheet to a Web App.
Based on some scripts I found, I developed a code to work the way I need in a Google Spreadsheet, but after making it work exactly the way I need it, I realized that a Web App could be a better alternative, mainly because of how it works on Mobile .
The point is that I didn't have a very linear JavaScript learning curve, my learning was solving specific needs, so I have difficulty with some basic concepts... and to be quite honest, deeply understanding JavaScript is not my main focus, but this knowledge is missing me now...
Let's get straight to the point
My current spreadsheet is this one:
Google Sheet - Stack Demonstration
In the GAS linked to this worksheet there are 2 .gs files and one HTML.
GAS files
1 - CSV.gs | Contains 2 scripts
CheckForFiles - Checks the amount of files in a given Google Drive folder before releasing the execution of other scripts.
SheetToCSV - Creates a .csv file of the sheet in the parent folder of that sheet.
This script is applied to the spreadsheet's Submit button.
2 - Upload.gs | Contains some functions responsible for uploading files through the spreadsheet.
ShowDialog0101 - Basically it's a script to call the upload page through an HTML alert in the spreadsheet.
GetParent - Basically it's a script that discovers the ID of the spreadsheet's parent folder and passes this information to the HTML file. I created this function because that way I can use this worksheet's folder as a model folder, simply duplicating the entire content without having to edit the code to update the worksheet's folder ID.
CreateOrGetFolder - This is the main function of the upload script, it checks if there is a child folder that has the name "Video" inside the parent folder, if it exists, it takes the ID of that folder so that the file is uploaded in that folder, if it does not exist, it creates a folder called "Video" and takes the ID of the created folder.
This is the Web App that launches when the Video File button is clicked:
Web App - Stack Demonstration
HTML file
Basically contains the client-side upload functions, I adapted this script based on this one.
What i would like to do
As I commented initially, I would like to adapt these scripts to work in a Web App.
My idea is that instead of the person filling out the worksheet, they fill out a form.
For this I need to adapt mainly the SheetToCSV script to link with a Submit button in the Web App, the idea is that as soon as the form is completed and the file upload is completed, this button is released and then when clicking on it the SheetToCSV script be triggered by creating a .csv file in the spreadsheet's parent folder with all the form responses.
My main difficulty is in linking the .csv generation script with the Submit button, I've been racking my brains over this for days.
I'm already having nightmares with this programming, literally... if anyone can help me with this, I'd be very grateful!
EDIT
I'll try to explain in a little more detail here.
Currently, I have this google spreadsheet here:
This worksheet contains modified versions of 2 scripts created by Tanaike.
Script 1 - Generates a .csv file with the worksheet fields in the same folder as the worksheet.
Script 2 - It is a modified version of Tanaike's Resumable Upload for Web Apps script, it is called in the spreadsheet via html alert.
Resumable Upload for Web Apps via HTML Alert
CSV file generated by the worksheet
Everything works as expected in this worksheet, but now I would like to convert it to a Web App, like this example:
The issue is that I don't know how to convert Tanaike's .csv generation script to generate the files through this html form, what I need is to integrate it with the Submit button of the Web App and collect the form fields in a .csv file.
The Spreadsheet and the Web App can be viewed at these links:
Google Sheet
Web App Form
Thank you for replying. Can I ask you about your expected values for the CSV data? In this case,
I confirmed your expected result in this question as follows.
You want to retrieve 2 text values of "name01", "description", and 2 values from dropdown lists of "Option1" and "Option2". The total values are 4 values.
When the HTML form is submitted, you want to create a new CSV file for every submission.
In this case, how about the following modification? Unfortunately, in your question, your script is not shown. So, in this answer, I would like to propose a simple modification.
When I saw your sample Spreadsheet including your script, when the submit button is clicked, it seems that the function submitForm() is run. In this answer, this is used.
Modified script:
Javascript side:
Please modify submitForm() as follows.
function submitForm() {
// Added the below script.
var name = $('#name01').val();
var description = $('#description').val();
var option1 = $('#Option1').val();
var option2 = $('#Option2').val();
var data = [name, description, option1, option2].join(",");
google.script.run.saveDataAsCSV(data, uploadParentFolderId);
if ($('#submit-btn.disabled')[0]) return; // short circuit
Google Apps Script side:
Please add the following function. Please modify the filename of "sample.csv" to your actual situation.
const saveDataAsCSV = (data, folderId) => DriveApp.getFolderById(folderId).createFile("sample.csv", data);
By this modification, 4 values in HTML form are retrieved and save it as a CSV file to the folder of uploadParentFolderId.
If you want to save the file to other folder, please modify uploadParentFolderId of google.script.run.saveDataAsCSV(data, uploadParentFolderId).

Copy/download temporary files

I am not an HTML/JavaScript developer. I am having to modify some legacy code written by someone who has left.
We have a Python app which acts as a local server with an HTML/JavaScript front end that can be viewed in a browser.
The Python creates a temporary cache file. I would like to give the user the option to save a copy of this temp file to a location of their choice or at least download it to the downloads directory (Windows & Linux)
I've tried adapting some of the ideas from here: https://www.delftstack.com/howto/javascript/javascript-download/
E.g.
const saveAnalysisBtn = document.getElementById("saveAnalysisBtn");
saveAnalysisBtn.addEventListener('click', saveAnalysis);
function saveAnalysis(evt) {
function download(filename) {
var element = document.createElement('a');
// hardcode temp file name just for POC
element.setAttribute('href','file://C:\\tmp\\my_temp_cache.db');
element.setAttribute('download', filename);
document.body.appendChild(element);
element.click();
//document.body.removeChild(element);
}
var filename = "output.txt";
console.log(`Call Download`);
download(filename);
}
In Firefox this gives a security error:
Security Error: Content at
http://127.0.0.1:5000/replay/fapi_15_6_udi.bin may not load or link to
file:///C:/tmp/my_temp_cache.db
Which isn't terribly surprising. (Edge & Chrome give similar errors)
Is there a way to do this? Can be in HTML or JavaScript or Python (though I would like user to see evidence of download taking place in the browser).
Maybe I'm not understanding, but it looks like we're talking about just copying a file from one local location to a user specified location. The file you want to copy is on the machine the user is using? Couldn't you just provide the location in the web page and then just go there in a file explorer, finder, or command line tool to copy it however you want? It would solve the security issue.
But if you're required to create a link, you could create a download process that zips the file up to make a file like "my_temp_cache_db.zip" (or whatever compression tool/extension works best for you), and then provide the link for that. Zip files work through browsers better than some other types of files, and the user just has to unzip it wherever it ended up.
If that's not ideal, you could create a download process that makes a copy of the file and just changes the extension to something like "txt". The user downloads that file and then has to rename it to have the right extension.

Check to see if a user has "edit rights" to a Google Drive URL

I'm trying to figure out how to check a Google Drive URL to see if a specific Gmail account has 'edit rights' to it. Is this possible in Apps Script? If yes, any help is greatly appreciated.
I'm currently researching File.getEditors(), but not sure how to test this code:
// Log the email address of all users who have edit access to a file.
//https://developers.google.com/apps-script/reference/drive/user
var file = DriveApp.getFileById('1mgw9xYO7X99brzrIk4Uel8YzndQa8dpGGQCnrFn4suU');
var editors = file.getEditors();
for (var i = 0; i < editors.length; i++) {
Logger.log(editors[i].getEmail());
}
To test this code, you need to place the code inside a a function inside the Script Editor on Google Drive, then execute the function.
You can access the Script Editor in two ways, either from within a spreadsheet (under Tools->Script Editor), in which case your script will be bound to the Spreadsheet. Binding to a spreadsheet can be useful if you want the script to work with data from sheet, for example you might want to store some configuration settings in the sheet, in which case keeping the sheet and the code together as one file is convenient.
You can also create a stand alone Script by connecting the Google Apps Script app to your Google Drive (+New -> More -> Connect more apps), then creating a stand alone Google Apps Script file directly on drive.
Regardless of how you create the script, the behaviour of this script and the script editor will be exactly the same.
Once you are in the script editor, paste that code into a function (by default you will be given an empty function named "myFunction()". Then run it using the "Run" menu.
Finally, under the "View" menu, go to "Logs" to see the results of Logger.log().

Google Apps Script/ Drive API (Javascript) Remove from Shared With Me

Does anyone have any suggestions for how to remove a file from shared with me? I need to do this without actually revoking access, as the people are added via a contact group, so only removing 1 person will not work.
Things to note:
I know using this can find the file:
var files = DriveApp.searchFiles('sharedWithMe');
//then I set file = what I'm looking for.
However, this will not remove the file from shared with me:
DriveApp.removeFile(file);
I've also tried brute forcing by patching the metadata, except it was to no avail.
In addition, it is wrong to assume that shared with me is a folder, as when listing parent folders the file returns nothing.
Only DriveApp cannot completely remove files. So it is necessary to use Drive API. "removeFile()" is used for changing parent folder information. It cannot remove files. I prepared 2 samples for removing files. If you are owner of the file, you can remove it.
Move file to trash box and empty trash :
var file = DriveApp.getFilesByName("filename").next();
file.setTrashed(true)
Drive.Files.emptyTrash();
Remove directly file :
Drive.Files.remove("fileID");
It was confirmed that above script can remove file even if other users are using.
For using above script, it is necessary to enable Drive API at Advanced Google Services and Drive API at https://console.developers.google.com/ Developers Console Project.
Files without parent folder :
If you had used "removeFile()", files without the parent folder may be existing in your drive. You can confirm them following script. This can retrieve file name and file ID of files without the parent folder.
var result = [];
var files = DriveApp.getFiles();
while (files.hasNext()) {
file = files.next();
if (!file.getParents().hasNext()) {
result.push([file, file.getId()]);
}
}
Logger.log(result);

Open file by name then perform actions

I'm currently creating files using drive.makeCopy(Objects[i][1]); where Objects is the name of the various files I want to make from a template.
The script works fine in making these files from a template however after each one has been made I would like to open the new file, hide some sheets in it and to set its permissions. The addresses for the permissions are held in Objects[i][3] but I cannot work out how to open these new files, then make the changes accordingly and then close the file.
I'm assuming by drive.MakeCopy() you are referring to File.MakeCopy(). This is easy, the MakeCopy function returns the File object it has created. You can then set permission this File object using functions such as addEditor(), addViewer(), setSharing(), etc.
So if Objects[i][3] contained the email address of someone who should be able to edit the new file, then you could do:
var new_file = drive.makeCopy(Objects[i][1]);
new_file.addEditor(Objects[i][3]);
You don't really need to "Close" the file after working with it, Apps Script takes care of this automatically.
See:
https://developers.google.com/apps-script/reference/drive/file#addEditor(String)
https://developers.google.com/apps-script/reference/drive/file#setSharing(Access,Permission)
https://developers.google.com/apps-script/reference/drive/file

Categories