I have replicated the google file picker in a web app.
My question is how would I tell the google picker to make a copy of the file when uploading it to google drive ?
Any help would be much appreciated.
I realised that google picker could not do what I needed so Google App Script to the rescue.
Firstly you need to create a new google spreadsheet
Under "Tools->Script Editor" add the following code
Thought trial an error I came up with the following.
function copyFiles() {
var dApp = DriveApp; // Get the drive app
var folderIter = dApp.getFoldersByName('parentFolder'); //Get folder my id
var folder = folderIter.next(); // Get the first folder
var fileIter = folder.getFiles(); // File iterator
var storageFolder = folder.getFoldersByName('childFolder').next(); // Get target folder
var subFolderIter = storageFolder.getFiles(); // sub folder File iterator
while(fileIter.hasNext()) {
var file = fileIter.next(); // Get the current File
var fileName = file.getName();
// Check if the current file exists in a coped folder
// If false make a copy else do noting
// This check prevents duplicate, Becasue makeCopy generates uniques ID everytime
if(!storageFolder.getFilesByName(fileName).hasNext()) {
//Logger.log('Files does NOT exists');
file.makeCopy(storageFolder);
} else {
//Logger.log('Files does exists');
}
}
}
Hope this helps anyone who might need.
Note: You will need to set up triggers for the script to run when required
Related
I have read 10+ questions about deleting items in Javascripts loops but they don't seem to apply to my situation.
I have this code
var childFolders = parent.getFolders();
// List folders inside the folder
while (childFolders.hasNext()) {
var childFolder = childFolders.next();
//processing childFolder
After this I want to delete the current item (childFolder) from the array childFolders. The reason is that I am doing some work in a Google Apps script but it often takes too long and times out so I need to be able to restart the loop and only have unprocessed items left in the array. To achieve this, in every loop, I copy the content of childFolders into a permanent storage that I can restore on the next run.
I believe your goal is as follows.
You want to stop the loop of the folder iterator, and when you run the script again, you want to start the folder iterator from the stopped iterator.
In this case, how about using "ContinuationToken"? When "ContinuationToken" is used, I thought that your goal might be able to be achieved by the native methods of Google Apps Script. When this is reflected in your script, how about the following script?
Sample script:
Please set var parent = DriveApp.getFolderById("###");.
// When you want to clear the token, please run this function.
function clearToken() {
PropertiesService.getScriptProperties().deleteProperty("token");
}
// This is the main function.
function main() {
var parent = DriveApp.getFolderById("###"); // Please set your parent folder.
var numberOfLoop = 2; // The folder iterator is run every this number.
var p = PropertiesService.getScriptProperties();
var token = p.getProperty("token");
var childFolders = token ? DriveApp.continueFolderIterator(token) : parent.getFolders();
var count = 0;
while (childFolders.hasNext()) {
count++;
var childFolder = childFolders.next();
//processing childFolder
console.log(childFolder.getName()); // This is a sample.
if (count == numberOfLoop) {
var token = childFolders.getContinuationToken();
p.setProperty("token", token);
break;
}
}
}
When you run main function, in this sample script, 2 folders are processed and the script is finished. When you run main again, the folder iterator is started from the continuation.
When you want to start from the 1st folder iterator, please run clearToken.
References:
getContinuationToken() of Class FolderIterator
continueFolderIterator(continuationToken) of Class DriveApp
Added:
From your following reply,
It is the script in step 3 here ourtechroom.com/fix/… I have problem with. I changed it to add all files to an array first and insert them into a sheet in a separate step at the end but that wasn't enough. Hence my question.
My issue is that your solution is a little too complicated for me. That is, I have a hard time applying your solution to the script in the link.
Do you want to retrieve the file metadata of all files in your Google Drive? If my understanding is correct, I think that the script in your link is a high process cost because appendRow is used in the loop. Ref I thought that this might be the reason for your actual situation. If my understanding is correct, how about the following sample script?
Usage:
1. Install Google Apps Script library.
You can see how to install Google Apps Script library of [FilesApp] at here.
2. Enable Drive API.
This modified script uses Drive API. So, please enable Drive API at Advanced Google services.
3. Sample script.
Please copy and paste the following script to the script editor of Spreadsheet. And, please set the top folder ID to folderId. If you use var folderId = "root";, all files in your Google Drive are retrieved.
function myFunction() {
var folderId = "###"; // Please set the top folder ID.
var header = ["parent", "folder", "name", "update", "Size", "URL", "ID", "description", "type"]; // This is from your script.
var obj = FilesApp.createTree(folderId, null, "files(name,modifiedTime,size,webViewLink,id,description,mimeType)");
var values = [header, ...obj.files.flatMap(({ folderTreeByName, filesInFolder }) => {
const f = [folderTreeByName.join("|"), folderTreeByName.pop()];
return filesInFolder.length == 0 ? [[...f, ...Array(7).fill(null)]] : filesInFolder.filter(({ mimeType }) => mimeType != MimeType.FOLDER).map(({ name, modifiedTime, size, webViewLink, id, description, mimeType }) => [...f, name || null, new Date(modifiedTime), size || 0, webViewLink, id, description || null, mimeType]);
})];
SpreadsheetApp.getActiveSheet().clear().getRange(1, 1, values.length, values[0].length).setValues(values);
}
References:
FilesApp of Google Apps Script library (Author me)
Files: list of Drive API v3
I am trying to upload pdf file to a single cell in google sheet just like we insert image in a google sheet cell. I've searched for quite some time now, but haven't been able to find any solutions to this. I have tried the following code:
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var menuEntries = [];
menuEntries.push({name: "File...", functionName: "doGet"});
ss.addMenu("Attach ...", menuEntries);
}
function doGet(e) {
var app = UiApp.createApplication().setTitle("upload attachment into Google Drive");
SpreadsheetApp.getActiveSpreadsheet().show(app);
var form = app.createFormPanel().setId('frm').setEncoding('multipart/form-data');
var formContent = app.createVerticalPanel();
form.add(formContent);
formContent.add(app.createFileUpload().setName('thefile'));
formContent.add(app.createHidden("activeCell", SpreadsheetApp.getActiveRange().getA1Notation()));
formContent.add(app.createHidden("activeSheet", SpreadsheetApp.getActiveSheet().getName()));
formContent.add(app.createHidden("activeSpreadsheet", SpreadsheetApp.getActiveSpreadsheet().getId()));
formContent.add(app.createSubmitButton('Submit'));
app.add(form);
SpreadsheetApp.getActiveSpreadsheet().show(app);
return app;
}
function doPost(e) {
var app = UiApp.getActiveApplication();
app.createLabel('saving...');
var fileBlob = e.parameter.thefile;
var doc = DriveApp.getFolderById('0B0uw1JCogWHuc29FWFJMWmc3Z1k').createFile(fileBlob);
var label = app.createLabel('file uploaded successfully');
var value = 'hyperlink("' + doc.getUrl() + '";"' + doc.getName() + '")'
var activeSpreadsheet = e.parameter.activeSpreadsheet;
var activeSheet = e.parameter.activeSheet;
var activeCell = e.parameter.activeCell;
var label = app.createLabel('file uploaded successfully');
app.add(label);
SpreadsheetApp.openById(activeSpreadsheet).getSheetByName(activeSheet).getRange(activeCell).setFormula(value);
app.close();
return app;
}
Since UiApp has been deprecated so it shows the error "UiApp has been deprecated. Please use HtmlService instead". I have tried the following line to avoid UiApp error but of no use:
var app = HtmlService.createHtmlOutput();
Is there any workaround that we can get to avoid this error? Thank you.
I believe your goal is as follows.
From your following comments,
I have pdf file in local pc, I would have a google sheet add-on with an option "file upload". I would click on that, it will upload file in the Drive folder which we have specified in script and the active google sheet cell will show the confirmation message.
I want to put the message in currently active cell of the sheet
You wanted to upload a PDF file on the local PC to Google Drive. And you want to put the confirmation message to a current active cell. You want to achieve this by a sidebar using HTML and Google Apps Script.
In this case, how about the following sample script?
Sample script:
Google Apps Script side: Code.gs
Please copy and paste the following script to the script editor of Google Spreadsheet as the script file and save the script.
const openSidebar = _ => SpreadsheetApp.getUi().showSidebar(HtmlService.createHtmlOutputFromFile("index"));
function upload(e){
const message = "sample confirmation message"; // Please set your confirmation message.
DriveApp.createFile(Utilities.newBlob(...e));
SpreadsheetApp.getActiveRange().setValue(message);
}
HTML&Javascript side: index.html
Please copy and paste the following script to the script editor of Google Spreadsheet as the HTML file and save the script.
<form>
<input type="file" name="file" onchange="upload(this.parentNode)" accept=".pdf,application/pdf" />
</form>
<script>
function upload(e){
const file = e.file.files[0];
const fr = new FileReader();
fr.onload = e => google.script.run.upload([[...new Int8Array(e.target.result)], file.type, file.name]);
fr.readAsArrayBuffer(file);
}
</script>
Testing:
When you run the function openSidebar, the sidebar is opened. And when you select the file from the input tag, the file is uploaded to the root folder of Google Drive, and the confirmation message is put to the active cell.
Note:
In this method, the maximum file size is 50 MB because of the specification of the Google Apps Script side. Please be careful about this.
This is a simple sample script for achieving the goal of your question. So please modify this for your actual situation.
Reference:
Dialogs and Sidebars in Google Workspace Documents
I am having trouble renaming a file in Google Drive. I am able to grab the file ok, but once i grab it i need to rename it if it contains a specific string.
I have tried both the .rename() and .setName() functions but Google Drive keeps saying the function can not be found. Any thoughts on how to rename a Google Spreadsheet / file in Google Drive?
/* Iterate over the spreadsheets over the folder */
while(spreadSheets.hasNext()) {
var sheet = spreadSheets.next();
/* Get the SpreadSheets Name and Rename it */
var newSSName = sheet.getName();
if(newSSName.search("Tr")>=0){
newSSName.setName("Sheet5");
} else if (newSSName.search("Params")>=0){
newSSName.setName("Sheet4");
} else if (newSSName.search("MrSummary")>=0){
newSSName.setName("Sheet3");
} else {
newSSName.setName("Sheet2");
};
You have a very simple problem. Let's see what you are trying to do:
newSSName.setName("Sheet5")
which we can see as per code is actually
var newSSName = sheet.getName();
which actually returns a string type. Instead what you need to do is
sheet.setName("Sheet5");
which you seem to have gotten right here
var sheet = spreadSheets.next();
/* Get the SpreadSheets Name and Rename it */
var newSSName = sheet.getName();
So you simply target the wrong variable. Please look up the Google Documentation about the setName() method
I have a Google Sheets file with an attached Script. The script does a number of things, one is it makes a clone of it self using makeCopy. This portion works. Now I want to be able to keep the same cloned Google file name and same Google file ID and just update the content which includes a Spreadsheet and the associated Google script.
if (!fileFound){
var file = masterSSFile.makeCopy(reportFileName, RepFolder);
} else {
oldFile.setContent(masterSSFile.getBlob());
}
When I use makeCopy with the same file name it creates a second file with the same name but with a different file ID.
The else portion fails because .setContent argument seems to just accept text. The result is the word "Blob" in the oldFile, everything else is gone.
I have other scripts that update the contents of a existing spreadsheet by overriding the contents of the various sheets, but I also want the associated script to also be included in the updated file keeping the same file ID.
I found this....
Overwrite an Image File with Google Apps Script
and tried using
var masterSpreadsheetID = SpreadsheetApp.getActiveSpreadsheet().getId();
var masterSpreadsheetFile = DriveApp.getFileById(masterSpreadsheetID);
var oldFileID = oldFile.getId();
var oldFileName = oldFile.getName();
var newBlob = masterSpreadsheetFile.getBlob();
var file = {
title: oldFileName,
mimeType: 'application/vnd.google-apps.spreadsheet'
};
var f = Drive.Files.update(file, oldFileID, newBlob);
I get error: "We're sorry, a server error occurred. Please wait a bit and try again. " on this line: "Drive.Files.update(file, oldFileID, newBlob);"
After reading this:
https://github.com/google/google-api-nodejs-client/issues/495
it looks like Drive.Files.update(), does not support bound scripts.
Anyone know how create a Spreadsheet file in a specific folder on Google Drive?
I have already tried the answer from this link.
EDIT - Tried this answer :-D :
//"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)
But the "correct answer" gives me the follow error "Uncaught TypeError: Cannot find function makeCopy in object Spreadsheet."
I saw other answers but none of them work. I have already tried enable "Drive API" from "Advanced Google Services", but it's kind of complicate to work with.
UPDATE!
Just to explain, my problem is that I was creating the Spreadsheet
var sheetId = SpreadsheetApp.create("filename").getId();
And then trying to makeCopy, or addFile in a folder. Something like that:
<someFolder>.addFile(sheet);
What I detect is that to work I have to get a File type, not a string like after. So I change to the code;
var sheetId = SpreadsheetApp.create("filename").getId();
var file = DriveApp.getFileById(sheet);
<someFolder>.addFile(file);
Instead of making a copy, why don't you just move it?
var file = DriveApp.getFileById(fileID),
folder = DriveApp.getFolderById(folderID),
parents = file.getParents();
folder.addFile(file);
while( parents.hasNext() )
parents.next().removeFile(file);