Copying sheets using appscript pulls through forms - google-apps-script

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()

Related

How can i remove the old converted file and replace with a new file using app script?

I am trying to replace the old converted files with the new file. This is because every time i run the script it keeps on duplicating and multiplying in the same folder.
Here is the code:
function ConvertFiles() {
var sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var r= 2;
for(r= 2;r < sheet.getLastRow(); r++){
var fileId= sheet.getRange(r,1).getValues();
var folderID = sheet.getRange(r,8).getValues();
Logger.log(fileId);
var files = DriveApp.getFileById(fileId);
var name = files.getName().split('.')[0];
var blob = files.getBlob();
var destinationFolderId = DriveApp.getFolderById(folderID);
Logger.log(folderID);
var newFile = {
title : name + '_converted', parents: [{id:
destinationFolderId.getId()}]};
Logger.log(newFile);
}
}
My goal is:
To replace/update the old converted file into the latest one everytime the script runs (if it has the same filename)
I would like to push back the converted fileId into the google sheet to be displayed.
How can i solve this issue?
I have added comments to show each part of the code. Kindly check the whole script below:
Script:
function ConvertFiles() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var r= 2;
for(r= 2;r < sheet.getLastRow(); r++){
// Use getValue instead of getValues
var fileId = sheet.getRange(r,1).getValue();
var folderID = sheet.getRange(r,8).getValue();
var files = DriveApp.getFileById(fileId);
var name = files.getName().split('.')[0];
var blob = files.getBlob();
var newFile = {
// Remove '_converted' from name if existing to avoid duplication of the string before adding '_converted'
// This will allow to have newly converted file "replace" the old converted file properly
title: name.replace('_converted','') + '_converted',
parents: [{
id: folderID
}]
};
var destinationFolderId = DriveApp.getFolderById(folderID);
var existingFiles = destinationFolderId.getFilesByName(newFile.title);
// GOAL #1: To replace/update the old converted file into the latest one everytime the script runs (if it has the same filename)
// Find the file with same name of the file to be converted
while(existingFiles.hasNext()) {
// ID of the file with same converted name
var oldConvertedFileWithSameNameID = existingFiles.next().getId();
// Delete before writing
Drive.Files.remove(oldConvertedFileWithSameNameID);
}
// Create new converted file then get ID
var newFileID = Drive.Files.insert(newFile, blob, {
convert: true
}).id;
// Goal #2: I would like to push back the converted fileId into the google sheet to be displayed.
// Add the ID of the converted file
sheet.getRange(r,9).setValue(newFileID);
}
}
Sample sheet:
Sample files:
First run (files):
First run (sheet):
Updated original files:
Run after updating original file (files):
Run after updating original file (sheet):
Note:
This will retain the original file, but will replace the existing converted file of it everytime the script is run.
I have used Drive services.

How can I modify this to save a spreadsheet into a new folder

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.

Google Script Question: Is there a way to create copies of files into multiple folders at once?

I have a spreadsheet from which I've written code to populate with the names of folders (column 1) and their IDs (column 2).
I would like to populate each of the folders listed in that spreadsheet with a copy of each of the documents contained a separate folder (a Shared Drive folder, if that matters). When I execute the code below, a copy of each document is created in the source folder (the Shared Drive folder) instead of in the destination folder (aka the folders whose IDs are captured in the spreadsheet). If it matters, each copy is labelled with a folderID from the spreadsheet. Can someone please tell me how I can get this code to create the copies inside the appropriate destination folders instead of in the source folder?
function CopiestoFolder() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getDataRange() //Get all non-blank cells
.getValues() //Get array of values
.splice(1); //Remove header line
//Define column numbers for data. Array starts at 0.
var NAME = 0;
var FOLDERID = 1;
//For each folder ID listed in spreadsheet, create a copy of
//each item in the Resume Resources folder.
for (var i = 0; i < data.length; i++) {
var name = data[i][NAME];
var folderId = data[i][FOLDERID];
var srcFolder = DriveApp.getFolderById("folder ID");
var dstFolder = folderId;
var files = srcFolder.getFiles();
while (files.hasNext()) {
var file = files.next();
var f = file.makeCopy(dstFolder);
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
dstFolder.addFile(file);
f.getParents().next().removeFile(file);
}
}
}
}
I had this problem with Script Files. Here's how I fixed. Or I should say here's how Tanaike fixed it. You will need to enable Drive API.
var res=file.makeCopy(copyName,subFldr);
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
Drive.Files.update({"parents": [{"id": subFldr.getId()}]}, res.getId(), null, {"supportsTeamDrives":true}); // Added
}
The file.makeCopy() method has 3 overloads:
//Accepts no parameters
file.makeCopy();
//Accepts a name parameter as a string
file.makeCopy(name);
//Accepts a destination parameter as an instance of a Folder class
file.makeCopy(destination);
//Accepts 2 parameters, the first of which is name (String) and the second one is destination (Folder).
file.makeCopy(name, destination);
You are trying to pass folder id instead of the actual folder, which gets interpreted as a folder name (not destination). Also, the following code means that your 'dstFolder' parameter is a string but you try to call the 'addFile()' method on it:
var folderId = data[i][FOLDERID];
var dstFolder = folderId;
dstFolder.addFile(file);
If you want to copy a file to another folder via makeCopy, you should pass a Folder as a parameter, not a folder id (a string). If you provide a string (your id) as a parameter, the script will interpret this id as the name you want the copied file to have. So you should first get the Folder out of its id, via getFolderById(id). So you should change this line:
var dstFolder = folderId;
To this one:
var dstFolder = DriveApp.getFolderById(folderId);
You are making a copy of the file before checking if the file is a Google Apps Script project. I assume you just want GAS projects to be copied, so this should be included inside the if block. Also, inside the if block you are using addFile which can also be used to copy a file to another folder (it adds the file to the desired folder). So you don't need to use both functions, they are doing basically the same (copying your file to the desired folder).
You are using removeFile, which is not necessary if you want to keep the original files in the original folders.
So the while block could be something like:
while (files.hasNext()) {
var file = files.next();
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
dstFolder.addFile(file);
}
}
Finally, your full code could be like:
function CopiestoFolder() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getDataRange() //Get all non-blank cells
.getValues() //Get array of values
.splice(1); //Remove header line
//Define column numbers for data. Array starts at 0.
var NAME = 0;
var FOLDERID = 1;
//For each folder ID listed in spreadsheet, create a copy of
//each item in the Resume Resources folder.
for (var i=0; i<data.length; i++) {
var name = data[i][NAME];
var folderId = data[i][FOLDERID];
var srcFolder = DriveApp.getFolderById("folder ID");
var dstFolder = DriveApp.getFolderById(folderId);
var files = srcFolder.getFiles();
while (files.hasNext()) {
var file = files.next();
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
dstFolder.addFile(file);
}
}
}
}
I hope this is of any help.

How to create a file in the active Directory

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());
}
}
}

Get the IDs of multiple files

I'm looking for a way I can list the ID's of multiple files inside a folder on my Google Drive. Can this be done via a script?
I am using a script in Sheets that will format them one by one and it is time consuming to open each file and copy the ID from the URL.
Thanks, got it to output to a spreadsheet with:
function listFilesInFolder(id) {
var folder = DriveApp.getFolderById('folderidgoeshere');
var contents = folder.getFiles();
var file;
var name;
var sheet = SpreadsheetApp.getActiveSheet();
var id;
sheet.clear();
sheet.appendRow(["Name", "ID"]);
while(contents.hasNext()) {
file = contents.next();
name = file.getName();
id = file.getId()
data = [name, id]
sheet.appendRow(data);
}
};