The problem I have is that the file is created in the root and I cannot find the right instruction to change to a named directory!
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create( invNo );
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
invtoSend.copyTo(newSpreadsheet);
just create the spreadSheet, get its ID and then use DriveApp to move it (and to remove it from root otherwise it will be available in both !)
var newSpreadsheet = SpreadsheetApp.create( invNo );
var file = DriveApp.getFileById(newSpreadsheet.getId());
DriveApp.getFolderById('0B3°°°°°°°1lXWkk').addFile( file );
DriveApp.getRootFolder().removeFile(file);
EDIT
I reallize that your question can be understood differently : you might want that the destination folder would be the "current spreadsheet" folder, in this case here is the appropriate code :
function xxxx(){
var newSpreadsheet = SpreadsheetApp.create( "invNo" );
var file = DriveApp.getFileById(newSpreadsheet.getId());
var folders = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getParents();
while(folders.hasNext()){ // a file might be in multiple folders, include it in all of them except root
var folder = folders.next();
if(folder.getName()!=DriveApp.getRootFolder().getName()){ // root folder name changes with user's locale
folder.addFile(file);
DriveApp.getRootFolder().removeFile(file);
Logger.log('destination folder name = '+folder.getName());
}
}
}
Related
I've found scripts that save a copy of a spread sheet, but so far I've not been able to figure out how to modify the following code to save my spreadsheet into the newly created/already existing folder.
//Create folder if it does not exist
function createFolder(folderID, folderName){
var parentFolder = DriveApp.getFolderById(folderID);
var subFolders = parentFolder.getFolders();
var doesntExist = true;
var newFolder = '';
// Check if folder already exists.
while(subFolders.hasNext()){
var folder = subFolders.next();
//If the folder exists return the id of the folder
if(folder.getName() === folderName){
doesntExist = false;
newFolder = folder;
return newFolder.getId();
};
};
//If the folder doesn't exist, then create a new folder
if(doesntExist == true){
//If the file doesn't exist
newFolder = parentFolder.createFolder(folderName);
return newFolder.getId();
};
};
function start(){
var FOLDER_ID = 'my folder id';
var NEW_FOLDER_NAME = SpreadsheetApp.getActiveSheet().getRange('A1').getValue();
var myFolderID = createFolder(FOLDER_ID, NEW_FOLDER_NAME);
};
Update:
My goal is to create a new folder based on the contents of cell A1 if that folder doesn't exist and save the file in that folder. If the folder already exists, then save the file in the existing folder. The file name will be in cell A2.
I want to save a copy, and leave the original file where it is.
Since September 30, 2020, Drive files cannot have multiple parent folders.
Therefore, you should either move your file to the new folder, or make a copy of the file. But you cannot have the same file in two different folders.
You should use either moveTo(destination), if you want to move the file to the new folder, or makeCopy(destination) if you want to copy your file to the new folder.
Update: You mentioned in comments that you want to make a copy the file (not move it) and specify the name of the copied file (corresponding to value in A2). Therefore, you should use makeCopy(name, destination).
Considering that you want to save the active spreadsheet, your main function could be like this:
function start(){
var PARENT_FOLDER_ID = 'my folder id';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var NEW_FOLDER_NAME = sheet.getRange('A1').getValue();
var FILE_NAME = sheet.getRange('A2').getValue();
var spreadsheetId = ss.getId();
var file = DriveApp.getFileById(spreadsheetId);
var folder = createFolder(PARENT_FOLDER_ID, NEW_FOLDER_NAME);
file.makeCopy(FILE_NAME, folder);
}
And the function createFolder could be greatly reduced in size, using Folder.getFoldersByName(name):
function createFolder(folderID, folderName){
var parentFolder = DriveApp.getFolderById(folderID);
var subFolders = parentFolder.getFoldersByName(folderName);
if (subFolders.hasNext()) return subFolders.next(); // Return existing folder
else return parentFolder.createFolder(folderName); // Return created folder
}
Notes:
Because of this behaviour change in Drive, methods like addFile(child) are deprecated.
Reference:
Single-parenting behavior changes
The script in your example creates a new folder. It doesn't save anything, as far as I can tell.
If you want just save your current spreadsheet in some already existing folder, here you go:
var id = SpreadsheetApp.getActiveSpreadsheet().getId();
var file = DriveApp.getFileById(id);
var folder = DriveApp.getFolderById("FOLDER_ID"); // <-- ID of the destination folder
folder.addFile(file);
Update. In case you know the name of destination folder and the folder shares the same parent folder with current spreadsheet file the script can look like this:
var ss = SpreadsheetApp.getActiveSheet();
var dest_folder_name = ss.getRange('A1').getValue();
var copy_name = ss.getRange('A2').getValue();
var dest_folder = "";
var file_id = SpreadsheetApp.getActiveSpreadsheet().getId();
var file = DriveApp.getFileById(file_id);
var parent_folder = file.getParents().next();
var sub_folders = parent_folder.getFolders();
// search a destination folder in current folder
while (sub_folders.hasNext()) {
dest_folder = sub_folders.next();
if (dest_folder.getName() === dest_folder_name) {
break;
}
dest_folder = "";
}
// create the destination folder if nothing was found
if (dest_folder === "") {
dest_folder = parent_folder.createFolder(dest_folder_name);
}
// copy the spreadsheet to the destination folder
file.makeCopy(copy_name, dest_folder);
The script tires to finds destination folder (the name taken from cell 'A1') inside current folder and creates the folder if nothing was found. After that it saves a copy of current spreadsheet (the name taken from cell 'A2').
NB. GoogleDrive allows files or subfolders with the same names inside one folder. So it's not unlikely to get many spreadsheets with identical names. Perhaps it makes sense to check names of existing files before the saving.
I have a script that pulls the ID of a file within a specific folder, then takes a copy and puts that into another folder then deletes it from the original folder.
However when the takes a copy it then copies any attached google forms and places them in the folder also.
Is there a way to only copy the sheet?
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Copies")
var folder = DriveApp.getFolderById('FOLDER_ID'); //Latest Copy ID
var list = [];
list.push(['Name','ID','Size']);
var files = folder.getFiles();
while (files.hasNext()){
file = files.next();
var row = []
row.push(file.getName(),file.getId(),file.getSize())
list.push(row);
}
sh.getRange(1,1,list.length,list[0].length).setValues(list);
var value = SpreadsheetApp.getActiveSheet().getRange(2, 2).getValue();
var archive = DriveApp.getFolderById("ARCHIVE_ID"); // Backup Folder
var file = DriveApp.getFileById(value);
var name = file.getName();
// makes copy of "file" with "name" at the "destination"
file.makeCopy(name, archive);
file.setTrashed(true); // sets the file in the trash of the user's Drive
}
Issue:
All files in your folder are found and processed, you're not checking for a specific file type.
Modifications:
Check the file type before you write to the array.
if (file.getMimeType() === 'application/vnd.google-apps.spreadsheet') {
var row = [];
row.push(file.getName(),file.getId(),file.getSize());
list.push(row);
}
Reference:
getMimeType()
This code works for me if I am importing two sheets:
={IMPORTRANGE("Sheet1Key","SheetName!A2:A500");IMPORTRANGE("Sheet2Key","SheetName!A2:A500")}
However, I have multiple sheets, all in the same folder, all with the data in the first sheet and all with the data in the same cells.
Is it possible to somehow either import from a folder or somehow add the IDs or names of all files within that folder automatically?
I am not sure what you mean by import all the files within that folder automatically. But what you could do is use the following code that I made a while ago. (You need to make it under scripts.google.com and you need to run the code)
The only thing you would need to change is the folder name where I wrote “type name of folder”
function listFolderContents() {
var foldername = 'type name of folder';
var folderlisting = 'URL listing for folder ' + foldername;
var folders = DriveApp.getFoldersByName(foldername)
var folder = folders.next();
var contents = folder.getFiles();
var ss = SpreadsheetApp.create(folderlisting);
var sheet = ss.getActiveSheet();
sheet.appendRow( ['name', 'link'] );
var file;
var name;
var link;
var row;
while(contents.hasNext()) {
file = contents.next();
name = file.getName();
link = file.getUrl();
sheet.appendRow( [name, link] );
}
};
It will create a google spreadsheet called “URL listing for folder (name of folder) located inside the folder you are trying to get the files for. The spreadsheet will contain an array of all the file URL’s. It should be relatively easier to create the import range given the URL’s. You may be able to pick my code apart and use parts that help you with your goal. Hope this helps.
You just need to use an array:
=query(arrayformula({importrange(sheet1!A1:Z100);importrange(sheet2!A1:Z100)}), "SELECT *",1)
This does assume that all data is structured the same.
after the renewal of DriveApp API I'm struggling to update my script.
It was able to find the Drive Folder ID starting from a file.
Basically starting from a Spreadsheet, I found what was the ID of the folder that contained the file.
Now if i try:
var thisFile =(the file I have)
var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents()[0];
var targetFolder = DriveApp.getFolderById(parentFold);
targetFolder.addFile(newFile);
The system sends an error at line 4 "No item with the given ID could be found, or you do not have permission to access it." (even if I open all the permissions).
Any suggestion?
Thanks!
The getParents() method returns a FolderIterator. It doesn't return the folder ID. You need to get the folder:
var folder = folders.next();
The code given assumes that there is only one parent folder to the file.
Updated Answer:
function copyToParent() {
var thisFile = DriveApp.getFileById('file ID');
//var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents();//Get all parents - normally just one parent
var folder = parentFold.next();//Get the first parent folder
//Logger.log('folder name: ' + folder.getName());//For testing - log folder name
folder.addFile(newFile);
}
Old Answer:
This answer has unneeded steps.
Then get the ID of the folder:
var theId = folder.getId();
Full code:
function copyToParent() {
var thisFile = DriveApp.getFileById('file ID');
//var newFile = (the file I want to add to the same folder)
var parentFold = thisFile.getParents();
var folder = parentFold.next();
var theId = folder.getId();
var targetFolder = DriveApp.getFolderById(theId);
Logger.log('targetFolder name: ' + targetFolder.getName());
targetFolder.addFile(newFile);
};
Can anybody help me out,
I want to create a Spreadsheet through App Script in a particular folder. How to do that.
Presently I am doing as follow:
var folder = DocsList.getFolder("MyFolder");
var sheet = SpreadsheetApp.create("MySheet");
var file = DocsList.getFileById(sheet.getId());
file.addToFolder(folder);
file.removeFromFolder(file.getParents()[0]);
It is not working.......
As suggested by #Joshua, it's possible to create a Spreadsheet (in a specific folder) with the Advanced Drive Service (you'll need to activate this if you haven't already, by going into Services +, find Drive API and click Add).
var name = 'your-spreadsheet-name'
var folderId = 'your-folder-id'
var resource = {
title: name,
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{ id: folderId }]
}
var fileJson = Drive.Files.insert(resource)
var fileId = fileJson.id
No need to move files around with this method !
folder = DriveApp.getFolderById("FOLDER_ID")
var ss = SpreadsheetApp.create("SPREADSHEET_NAME")
DriveApp.getFileById(ss.getId()).moveTo(folder);
You may use the above code to achieve the same without using advanced drive services
Since you can no longer create Google Docs (Docs or SpreadSheets) using DriveApp, nor use addToFolder because DocList is deprecated. There is only one way to create or "move" Google Docs or Google SpreadSheets..
//"Move" file to folder-------------------------------//
var fileID = '12123123213321'
var folderID = '21321312312'
var file = DriveApp.getFileById(fileID).getName()
var folder = DriveApp.getFolderById(folderID)
var newFile = file.makeCopy(file, folder)
//Remove file from root folder--------------------------------//
DriveApp.getFileById(fileID).setTrashed(true)
As you can see this DOES NOT move the file, it makes a copy with the same name in the folder you want and then moves the original file to the trash. I'm pretty sure there is no other way to do this.
The other answer is a bit short (and not very explicit).
While your approach is logic and should work if you replace
file.removeFromFolder(file.getParents()[0]);
with
file.removeFromFolder(DocsList.getRootFolder());
there is a better way to do the same job using the new Drive app and the Folder Class, Folder has a method to create a file and you can specify the file type using the mimeType enum.
Code goes like this :
function myFunction() {
var folders = DriveApp.getFoldersByName('YOUR FOLDER NAME'); // replace by the right folder name, assuming there is only one folder with this name
while (folders.hasNext()) {
var folder = folders.next();
}
folder.createFile('new Spreadsheet', '', MimeType.GOOGLE_SHEETS); // this creates the spreadsheet directly in the chosen folder
}
In July 27, 2020 there have been these updates:
The File class now has the following methods:
file.getTargetId(): Gets a shortcut's file ID.
file.getTargetMimeType(): Returns the mime type of the item a shortcut points to.
file.moveTo(destination): Moves a file to a specified destination folder.
The Folder class now has the following methods:
folder.createShortcut(targetId): Creates a shortcut to the provided Drive item ID, and returns it.
folder.moveTo(destination): Moves an item to the provided destination folder.
The following Folder class methods have been deprecated:
addFile(File)
addFolder(Folder)
removeFile(File)
removeFolder(Folder)
https://developers.google.com/apps-script/releases/#july_27_2020
So you can create a Spreadsheet file in a folder using file.moveTo(destination) method:
function createSpreadSheetInFolder(ss_new_name, folder_dest_id) {
var ss_new = SpreadsheetApp.create(ss_new_name);
var ss_new_id = ss_new.getId();
var newfile = DriveApp.getFileById(ss_new_id);
newfile.moveTo(DriveApp.getFolderById(folder_dest_id))
return ss_new_id;
}
var file_name = 'SPREADSHEET NAME';
var folder_id = 'DESTINATION FOLDER ID';
var new_ssId = createSpreadSheetInFolder(file_name, folder_id)
You can create a spreadSheet and then add it to the folder.
function createSpreadSheetInFolder(name,folder){
var ss = SpreadsheetApp.create(name);
var id = ss.getId();
var file = DriveApp.getFileById(id);
folder.addFile(file);
return ss;
}
folderId='your_folder_id'
name='my_new_ss'
folder=DriveApp.getFolderById(folderId)
createSpreadSheetInFolder(name,folder)
By using the folder.addFile method there's no need to use a temp file (no need to duplicate and remove file). Pretty straightforward !
I finally got the answer to my question. The following works
var file = DocsList.getFileById(sheet.getId());
var folder = DocsList.getFolder("MyFolder");
file.addToFolder(folder);
// remove document from the root folder
folder = DocsList.getRootFolder();
file.removeFromFolder(folder);
What is not working? Use getRootFolder in the last line.
Creating a new spreadsheet in a file can be done using this link as a reference.
createFile(name, content, mimeType)
Therefore using the enum MimeType we can do:
var folder = DriveApp.getFolderById("your-folder-id");
folder.createFile("My File Name","",MimeType.GOOGLE_SHEETS)