Google App script: Overwrite existing csv file. Not create a copy using createFile - google-apps-script

Hi I've got this Google App script that needs to overwrite a file.
At the moment it creates a copy.
Is there a line or two that can check if it exists,then delete?
Or is there an alternative to createFile that overwrites?
DriveApp.getFolderById(fold).createFile(file.getName()+'-'+sheet+'.csv', csv);
Many thanks for looking!

Filenames are not unique on Google Drive - the uniqueness of files is determined by their ID. Whereas on a regular file system, creating a file with a similar filename would erase the old file, in this case you are creating a new unique file every time.
As far as I know, the easiest way would the be to move the existing file to the trash. You can keep you existing script but add to it. Assuming your file will always exist, this should work:
const folder = DriveApp.getFolderById(fold);
folder.getFilesByName(file.getName()+'-'+sheet+'.csv').next().setTrashed(true);
folder.createFile(file.getName()+'-'+sheet+'.csv', csv);
If you are unsure that a file with that name will exist, or if there might be multiple files with that name, you will have to iterate through all them:
const folder = DriveApp.getFolderById(fold);
const files = folder.getFilesByName(file.getName()+'-'+sheet+'.csv');
while(files.hasNext()){
let f = files.next();
f.setTrashed(true);
}
folder.createFile(file.getName()+'-'+sheet+'.csv', csv);
I haven't tested this code, but it should be pretty close to what you need.
Edit
Contrary to what I said, the method DriveApp.File.setContent(content) can overwrite the content of a file. The above solution still works and avoids potential data loss.

Related

Finding a .txt file on Google Drive by name and getting its contents

I want to find text files by their name and then get their contents and make them into a var.
I have tried to find the file by its name, but it doesn't seem to work. I'm clueless as to how to find the file contents though.
My code to find the file:
function testThing() {
var findquestions = DriveApp.getFilesByName('tempquestions.txt')
Logger.log(findquestions)
}
I want it to log what it found, but the output is nothing but: "FileIterator". I don't know what that means.
As you can see in the documentation, .getFilesByName return fileiterator. What's a file iterator? The documentation states
An iterator that allows scripts to iterate over a potentially large collection of files
There may be large amount of files with the same name. This iterator provides access to all those files.
What methods provide access to file from fileIterator? This method does.
How to get contents of such file? Get blob from file and getDataAsString from blob
Logger.log(DriveApp
.getFilesByName('tempquestions.txt') //fileIterator
.next() //file(first file with that name)
.getBlob() //blob
.getDataAsString() //string
)

Modify Google App Script - Gmail to Google Drive

I'm trying to modify this script found here:
https://github.com/ahochsteger/gmail2gdrive
I need the script to check if the file already exists on Google Drive and if not, create it. Currently, the script just creates the file into Google Drive, without checking to see if an existing file with the same name already exists or not.
I'm not a programmer, I know nothing about Google App Script (although I have managed to set it up and got it running) and I know nothing about JavaScript. I'm just wondering if someone could either point me in the right direction or help me code this one feature that I need?
From what I understand (I could be wrong), the attachment is created based on this line in the code:
var file = folder.createFile(attachment);
So then I tried add this before the createFile:
var file = folder.removeFile(attachment);
My logic here is that if the file exists in the folder, then remove it first before creating it (therefore avoiding duplicate files). But that didn't work.
From the script of GitHub in your question, it is found that attachment is blob. So how about using this filename? I think that there are several solutions for your situation. So please think of this as one of them. The flow of sample script is as follows.
Retrieve the filename of blob.
Retrieve FileIterator using getFilesByName().
If the FileIterator has values, it means that the file with the same filename has already been existing.
If the FileIterator has no values, it means that the file with the same filename is not existing.
The sample script is as follows.
Sample script 1:
If you want to create new file only when the file of same filename is not existing, you can use the following script.
var fileName = attachment.getName();
var f = folder.getFilesByName(fileName);
var file = f.hasNext() ? f.next() : folder.createFile(attachment);
Sample script 2:
If you want to do something when the file of same filename is existing, you can use the following script.
var fileName = attachment.getName();
var f = folder.getFilesByName(fileName);
var file;
if (f.hasNext()) {
// If the file has already been existing, you can do something here.
} else {
// If the file is not existing, you can do something here.
file = folder.createFile(attachment);
}
Note:
From your question, the file is searched from the folder. If you want to search the file from all files, please tell me.
References:
getName()
getFilesByName(name)
FileIterator
If this was not what you want, please tell me. I would like to modify it.

Delete or Trash specific file in Drive

I had a script that ran every day at 5 am, that would move a specific file (data.xls) to the trash. However, since DocsList has been retired, the script no longer functions, and I'm having trouble updating it.
I've seen a couple of delete/setTrashed scripts posted here, but they all seem to function for an array of files, and i only want one specific file deleted.
I'm not a coder, and self-taught myself most of the small amount i have, so i need it as simple as possible (sorry.)
Any and all help or guidance is very appreciated. Thank you.
function myFunction() {
var files = DriveApp.getFilesByName('data');
while (files.hasNext()) {
var file = files.next();
ID = file.getId(file)
Drive.Files.remove(ID);
}
}
I've seen a couple of delete/setTrashed scripts posted here, but they
all seem to function for an array of files, and i only want one
specific file deleted.
Simply put, to delete a single file you delete the first item in the list, what you are calling an array and what Google calls a file iterator.
Retrieving a file by name is going to return a list(iterator), even if it has only one file by that name, so you must treat the single item as the first item in the iterator and set that first item to trash.
Edit:
function myFunction() {
var files = DriveApp.getFilesByName('data');
while (files.hasNext()) {
files.next().setTrashed(true);
}
}
if you know that there is one and only one file by that name you could do something as simple as:
function myFunction() {
DriveApp.getFilesByName('data').next().setTrashed(true);
}
Since this is the first hit for Googling "apps script move file to trash", I found the following easy solution:
let file = DriveApp.getRootFolder().createFile('RIP file.txt', 'Good-bye, world ㅜㅜ');
file.setTrashed(true); // So the file is deleted after 30 days
File documentation
I have workaround using DriveApp removeFile. Note this does not delete or trash the file in the user archive, but is no longer visible in the named folder.
removeFile(child)
Removes the given file from the root of the user's Drive. This method
does not delete the file, but if a file is removed from all of its
parents, it cannot be seen in Drive except by searching for it or
using the "All items" view.
DriveApp.getFolderById(DriveApp.getFolderById(folderId)).removeFile(DriveApp.getFileById(fileId))

When adding a file to a folder, how to make it not default save in Google Drive?

In my script I have template docs in the main drive, but when the copy is created and populated with my excel data, I want it to be saved in a folder in drive. I have the script do that, but it has one copy of the file in the Main Google Drive, and the other in the folder I want it in. If I delete one of the copies, it deletes both.
Is there any way I can have it save automatically in the specified folder without also being in the main drive folder?
Folders in Google drive are not exactly like forders in a computer : having the file in your 'root' folder and in another folder doesn't mean there are 2 files, but rather 1 and only file with 2 labels... that's why you can't delete one without deleting the other !
The solution is simply to play with these labels in the script, here is how it works : (I commented each step to make it clear.)
function othertest(){
folder=DocsList.createFolder("MyFolder"); // or getFolderById or whatever other way to get your target folder
var file=DocsList.createFile('File2', 'Empty');// just an empty file for test but this would be your file copy that you want to "move"
file.addToFolder(folder);// put it in the folder
file.removeFromFolder(DocsList.getRootFolder());// and remove from the root
}
The other possible solution is to create the file directly in the target folder since the folder object supports the createFile method. (Not sure though that you can do it in your specific use case)
here is an example, you can see that the file is not in the root folder.
function createFileinFoldertest() {
var folder = DocsList.getFolder('test')
folder.createFile('Empty test fileName','nothing in there')
}

How do I copy & move a file to a folder in Google Apps Script?

Is there a way to copy and rename a file and move that copy to a particular folder without having a second copy in the root folder? I have used combinations of copy, rename, move in different order, but each time, I still end up with a copy of the renamed file the root drive. Is this by default? It is annoying to say the least.
In the new version of google apps script all you need to acheive your task is the following:
file.makeCopy("new name", folder);
EDIT : I had a look at your original question (before edit) and from there I understood the confusion you made about how files and folders work in Google Drive.
When you make a copy of a file you get a new file in the root folder, when you add this new file to another folder you have to consider that as sticking a label on this file without creating any new copy of it.
You can actually see the file in both the root and the other folder but it is the very same file with 2 different labels! (and you did notice that since you tried to delete it and saw it was deleted in both places)
The only thing you have to do to get the new file in its folder and not shown in the root it to remove the "root label".
That's how Google drive works. And when you think about it and compare to a local hard disk storage it gets logical : when you move a file from one folder to another on the same logical drive you don't move data (ie the bytes on the disk) but simply tell the disk operating system that this file is somewhere else on the map.
So consider Google Drive as a (very) large disk unit with billions on files that you can't move but on which you can stick as many labels as you want ;-) (the most important label being your Google account ID !)
And to play with these labels in the case you describe just try this simple function :
function copyAndMove(file,folder){
var newfile=file.makeCopy('copy of '+file.getName());// here you can define the copy name the way you want...
newfile.addToFolder(folder);// add the copy to the folder
newfile.removeFromFolder(DocsList.getRootFolder());// and remove it from your root folder
}
to test it just use the 2 required parameters : the file object anf the folder object that you can get from many different methods, see the DocsList documentation for details on how to get it if you need to but I guess you already know that ;-)
Yeah, it is a bit odd that Google does not provide a move method. But, considering how drive works and that a file can belong to multiple folders, it makes some sense that you have write your own moves. Here is a simple move function I wrote:
// Moves a file to a new folder by removing all current
// parent folders and then adding the new one.
function moveFileTo(fileObj, folderObj) {
// Attempt the move only if folderObj has a value.
// Otherwise, the file will be left without a folder.
// (Lost files can be found in the "All items" area.)
if (folderObj) {
var folders = fileObj.getParents();
for (var i = 0; i < folders.length; i++) {
fileObj.removeFromFolder(folders[i]);
}
fileObj.addToFolder(folderObj);
return true;
}
return false;
}
Basically, use it like this:
var file = DocsList.getFileById(fileID);
var folder = DocsList.getFolder('Some folder name');
// Make a backup copy.
var file2 = file.makeCopy('BACKUP ' + Utilities.formatDate(new Date(), Session.getTimeZone(), 'yyyy-MM-dd') + '.' + file.getName());
// Move the backup file.
if (moveFileTo(file2, folder)) {
...
I should note that this simple function is exactly that... simple. It assumes you are okay with whacking all parent folders -- owned or shared. This can have unexpected consequences with shared files in various shared folders of various users if you are not careful. It does not appear, however, to remove parent folders that are not shared with the user of this script -- which is good. Anyhow, one obvious alternative to control things better would be to specify the "from" folder as well as the "to" folder.