function copyFolderContents_(source, target) {
// Iterate files in source folder
const filesIterator = source.getFiles()
while (filesIterator.hasNext()) {
const file = filesIterator.next()
// Make a copy of the file keeping the same name
file.makeCopy(file.getName(), target) // need to find python function replacing THIS LINE!!!!!!!!!!!!!!!!!!
}
}
const toCopy = DriveApp.getFolderById('')
const copyInto = DriveApp.getFolderById('')
const newFolder = copyInto.createFolder(toCopy.getName())
copyFolderContents_(toCopy, newFolder)
I trying to rewrite this app script into python, which only copies the file but not the folder into another locatioN
is there any pydrive or vanilla HTTP restful API that could replace file.makeCopy(file.getName(), target) ?
After visiting ref , seems this restful API doesn't have a target that I could specified.
The parent[] parameter in the request body of Files:copy is the same as the destination in makeCopy(name, destination).
Example:
Here I have a folder named 68759008 which has the sample document:
and here is the destination folder I want my sample document to be copied.
Using API Explorer:
Request Parameter:
In the request parameter, I only inserted the file ID of the sample document
Request Body:
{
"parents": [
"Insert Destination folder ID here"
],
"name": "68759008_TEST_DOC_COPY"
}
Response:
Output:
There are two options to obtain the parent ID or the destination folder ID:
You can go to the destination folder and copy the string after the https://drive.google.com/drive/folders/
Use Files:list, find the file name and the mimeType should be application/vnd.google-apps.folder
Files:list Example:
Related
I am using this code to upload the heic file and finding a way to convert heic as jpg or png via apps script (not right click save as)
I have my code
function uploadMediaItems() {
const albumId = "AKwCquOrmWbEihvwEqIM7Jy_H8wrkM_dof1eIGwXq8YZV-uuj9jWvkMT5oWkG6P0a-w_w9VyTOxM"; // Please set the album ID.
var arrId =
[
"1ssNYJFSEdfRI55IUi_tte3iC_JcPLG-0"
];
const items = arrId.map(id => {
const file = DriveApp.getFileById(id);
return {blob: file.getBlob(), filename: file.getName()};
});
const res = GPhotoApp.uploadMediaItems({albumId: albumId, items: items});
console.log(JSON.stringify(res))
}
Source: Google Apps Scripts: import (upload) media from Google Drive to Google Photos?
I believe your goal is as follows.
You want to upload the HEIC file to Google Photos and export it as a Jpeg or PNG file using the sample script at this thread.
From your script, the HEIC file is put on your Google Drive.
I thought that in your goal, you might have wanted to convert the HEIC file to Jpeg or PNG file. In this case, how about the following sample scripts?
Sample script 1:
In this sample script, the sample script at this thread is used. So, in this case, a Google Apps Script library of GPhotoApp is used. Ref The sample script is as follows.
In this script, it supposes that your Google Apps Script project has already been linked with Cloud Platform Project, and Photos API has already been enabled, and also, the required scopes have already been added. Please be careful this.
function myFunction() {
const arrId = ["###"]; // Please set the file ID of your HEIC file.
const albumId = "###"; // Please set your albumn ID.
const items = arrId.map(id => {
const file = DriveApp.getFileById(id);
return { blob: file.getBlob(), filename: file.getName() };
});
const res1 = GPhotoApp.uploadMediaItems({ albumId: albumId, items: items });
const mediaItemId = res1.newMediaItemResults[0].mediaItem.id;
const res2 = GPhotoApp.getMediaItems({ mediaItemIds: [mediaItemId] });
const mediaItem = res2.mediaItemResults[0].mediaItem;
const blob = UrlFetchApp.fetch(mediaItem.baseUrl).getBlob();
DriveApp.createFile(blob.setName(mediaItem.filename.replace(".heic", ".png")));
}
When this script is run, the PNG file is created to the root folder.
Sample script 2:
The HEIC file is put on your Google Drive. And, you want to convert the HEIC file to Jpeg or PNG. In this case, I thought that this can be achieved using the following simple script. In this case, Photos API is not required to be used.
When you use this script, please enable Drive API at Advanced Google services.
function myFunction2() {
const fileId = "###"; // Please set the file ID of your HEIC file.
const obj = Drive.Files.get(fileId);
const blob = UrlFetchApp.fetch(obj.thumbnailLink.replace(/=s.+/, "=s2000")).getBlob();
DriveApp.createFile(blob.setName(obj.title.replace(".heic", ".png")));
}
When this script is run, the PNG file is created to the root folder.
References:
Photos Library API
GPhotoApp
Files: get
The issue I'm current facing is:
I created a main folder named "Parent" with the folder ID:eg abcde12345.
Within the Parent folder, there are 3 diff folders (eg. Folder A, Folder B, Folder C) with their own files.
The specific file I am looking for is: "File to be sent.pdf"
This file, I placed in Folder C for example.
However, the script I wrote below (with some details edited out) only search for the specific file in the Parent folder. The search does not go into Folder A,B or C to look for the file with the exact filename.
Is there a way to search for this specific file within the Parent + A + B + C without hardcode the Folder A,B,C IDs in the script?
Thank you!
Ps. The number of sub folders may grow more than A,B,C and in these sub folders, I am thinking of creating more layers.
function ReturnWork(){
var markedFolder = DriveApp.getFolderById("abcde12345");
var ws = SpreadsheetApp.getActiveSpreadsheet();
/*This section which I edited out to shorten this post contains variables example:
-emailAddress
-subject
-etc... all details needed for the mailApp below.*/
var docName = 'File to be sent.pdf';
var markedFiles = markedFolder.getFilesByName(docName);
if(markedFiles.hasNext()){
MailApp.sendEmail({
to: emailAddress,
subject: subjectMarked,
replyTo: centre_email,
htmlBody : markedHTML.evaluate().getContent(),
attachments: [markedFiles.next().getAs(MimeType.PDF)],
});
}
}
One option would be to recursively search the file in the target folder and its subfolders:
function searchFileTest() {
const targetFolderId = 'abc123';
const fileName = 'File to be sent.pdf';
const filesFound = searchFile(fileName, targetFolderId);
for (const file of filesFound) {
Logger.log('File found: ' + file.getUrl());
}
}
function searchFile(fileName, folderId) {
let files = [];
// Look for file in current folder
const folderFiles = DriveApp.getFolderById(folderId).getFiles();
while (folderFiles.hasNext()) {
const folderFile = folderFiles.next();
if (folderFile.getName() === fileName) {
files.push(folderFile);
}
}
// Recursively look for file in subfolders
const subfolders = DriveApp.getFolderById(folderId).getFolders();
while (subfolders.hasNext()) {
files = files.concat(searchFile(fileName, subfolders.next().getId()));
}
return files;
}
This will return an array with all the files that have that name in the folder you specify of its subfolders.
Related:
How to search contents of files in all folders and subfolders of google drive in Apps Scripts?
Google apps script - iterate folder and subfolder
assign hyperlink to cell in google sheets to google drive files using google app script
Basically this question is giving an answer for what I'd like to do:
Google script to create a folder and then create a Google Doc in that folder
But it's 5 years old, and I was wondering if there was an easier way now. In my case I have lots of existing folders and I want to create a particular file in each of them via a script that runs at intervals.
Thx.
EDIT:
Ok, the code below works fine (using a modified sample script 1 in the answer) when the folder 'test folder' is in a shared drive.
function testFunction() {
const notesFileName = 'test doc';
const folderName = 'test folder';
const query = "title = '" + folderName + "'";
// Find all folders that match the query.
var folders = DriveApp.searchFolders(query);
while (folders.hasNext()) {
// In all the sub-folders, of each found folder, create a file with the same name.
var folder = folders.next();
Logger.log("Found a folder: " + folder);
var subFolders = folder.getFolders();
while( subFolders.hasNext() ) {
var subFolder = subFolders.next();
Logger.log('Folder id: ' + subFolder.getId());
const doc = Drive.Files.insert({title: notesFileName, mimeType: MimeType.GOOGLE_DOCS, parents: [{id: subFolder.getId()}]}, null, {supportsAllDrives: true});
}
}
}
I believe your goal as follows.
You want to create new Google Document to the specific folders.
You have a lot of folders you want to create new Google Document. So you want to reduce the process cost of the script.
In this case, I would like to propose to create the new Google Document using Drive API. When Drive API is used, the creation of Google Document to each folder can run with the asynchronous process. The sample script is as follows.
Sample script 1:
Before you use this script, please enable Drive API at Advanced Google services. In this sample script, the new Google Documents are created to the specific folders in a loop.
function sample1() {
const titleOfDocument = "sample document";
const folderIds = ["### folder ID1 ###", "### folder ID 2 ###",,,];
const documentIds = folderIds.map(id => Drive.Files.insert({title: titleOfDocument, mimeType: MimeType.GOOGLE_DOCS, parents: [{id: id}]}).id);
console.log(documentIds)
}
In this script, the created Document IDs are returned.
If the process time of this script was long in your actual situation, please test the following sample script 2.
Sample script 2:
Before you use this script, please enable Drive API at Advanced Google services. In this sample script, the new Google Documents are created to the specific folders using the batch request of Drive API using a Google Apps Script library. By this, the tasks are run with the asynchronous process.
Please install the Google Apps Script library for using the batch request. Ref
function sample2() {
const titleOfDocument = "sample document";
const folderIds = ["### folder ID1 ###", "### folder ID 2 ###",,,];
const requests = {
batchPath: "batch/drive/v3",
requests: folderIds.map(id => ({
method: "POST",
endpoint: `https://www.googleapis.com/drive/v3/files`,
requestBody: {name: titleOfDocument, mimeType: MimeType.GOOGLE_DOCS, parents: [id]},
})),
accessToken: ScriptApp.getOAuthToken(),
};
const result = BatchRequest.EDo(requests); // Using GAS library
const documentIds = result.map(({id}) => id);
console.log(documentIds)
}
Note:
For above sample scripts, if you want to retrieve the folder IDs under the specific folder, you can also use for folderIds as follows.
const topFolderId = "### top folder ID ###";
const folders = DriveApp.getFolderById(topFolderId).getFolders();
const folderIds = [];
while (folders.hasNext()) {
folderIds.push(folders.next().getId());
}
By the way, in the current stage, in order to move the file, you can use moveTo(destination). Using this, the script of this can be modified as follows.
function createDoc(folderID, name) {
var folder = DriveApp.getFolderById(folderID);
var doc = DocumentApp.create(name);
DriveApp.getFileById(doc.getId()).moveTo(folder);
return doc;
}
References:
Files: insert of Drive API v2
Files: create of Drive API v3
BatchRequest
I'm getting an e-mail daily with an XLSX file that I need to then export over to a specific Google Sheet.
The code simply searches the GMAIL for a specific query, where it then gets the body (which contains a URL), which it then downloads with the doGet function, that uses the Url.FetchApp.fetch(url).getBlob()
After that, using the variable fileInfo, it defines, the title, mimeType of the file and the "parents" which is the ID of the folder where I need to deposit the converted file.
Then, I insert the file with the Drive.Files.insert(fileInfo, file, {convert: true}) which should convert my Excel file and deposit it in my folder.
The export works (a file is exported). If I append a .xlsx extension manually and try to open in Excel,it opens perfectly with all the required information.
But, the issue is that I don't need to open in an Excel file, so I'm trying to export it to a Google Sheet or even parse it as a CSV, but it doesn't work.
When trying to open this exported file by ID, it says that it is missing or don't have permissions, but it is there and I do have permissions.
When checking the mime type of the file, it says "application/x-zip".
Is there anyway for me to upload the file data to my Google Sheet with the ID "1HMXgJuuRFaGK11sfR38mKh6rk4ta_Qgtlljk6HBjLkE"?
function CostDSP() {
var sheetId="1HMXgJuuRFaGK11sfR38mKh6rk4ta_Qgtlljk6HBjLkE";
var threads = GmailApp.search("from:no-reply#amazon.com subject:Cost - DSP in:inbox newer_than:1d");
var message = threads[0].getMessages()[0];
var attachment = message.getPlainBody();
var regex= new RegExp("\<(.*)\>");
var url=regex.exec(attachment)[1];
Logger.log(url);
var file=doGet(url);
var fileInfo = {
title: "Cost - DSP",
mimeType: "MICROSOFT_EXCEL",
"parents": [{'id': "19jrt0DyfvsDz5WAdKhkekHkJ_wP7qP7f"}],
};
Drive.Files.insert(fileInfo, file, {convert: true});
var sourceFile = DriveApp.getFilesByName("Cost - DSP").next();
Logger.log(sourceFile.getMimeType());
Logger.log(sourceFile);
var source=SpreadsheetApp.openById("1lIVb9YM9IK7f8dKuC1RpXjP7nLnMNXm1");
var sheet = sourceFile.getSheets()[0];
var destination = SpreadsheetApp.openById("1HMXgJuuRFaGK11sfR38mKh6rk4ta_Qgtlljk6HBjLkE").getSheetByName('Data Intake');
sheet.copyTo(destination);
}
function doGet(e) {
// e.parameter["file"] //returns ?file=filelink.com/file.xlsx
var file = UrlFetchApp.fetch(e).getBlob();
return file;
}
It seems you need to use the correct mime type for import
mimeType:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
The next code works fine for me
var file = UrlFetchApp.fetch(
'https://ec.europa.eu/eurostat/statistics-explained/images/9/9f/Country_Codes_and_Names.xlsx'
);
var fileInfo = {
title: 'Cost - DSP',
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
parents: [{
id: 'root'
}],
};
Drive.Files.insert(fileInfo, file, {
convert: true
})
As #Raserhin said it works without the mimeType parameter.
var fileInfo = {
title: 'Cost - DSP',
// mimeType:
// 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
parents: [{ id: 'root' }],
}
;
Also you can't use doGet as you're using now. doGet is a reserved function.
Turns out I also had to set the mimetype in the doGet function to the xlsx mimetype for it to work.
As an optimization I also removed the mimetype specification in the file info variable.
I'm managing to use this doGet function despite it being reserved, so I guess I'll stick to it for now?
As for calling the drive api directly, I need to use the advanced service to be able to convert the xlsx file.
I'm using the .createFile method of the DriveApp Folder class. This is the syntax:
createFile(name, content, mimeType)
The documentation is here: createFile Google DriveApp Service
The example shows a mimeType setting of MimeType.HTML.
// Create an HTML file with the content "Hello, world!"
DriveApp.createFile('New HTML File', '<b>Hello, world!</b>', MimeType.HTML);
I can type in MimeType. and get a list of MimeTypes, one of them being GOOGLE_DOCS. So I entered MimeType.GOOGLE_DOCS. But I'm getting an execution error stating that one of the arguments is invalid. If I type in a Mime Type of 'text/plain', I get no error.
How do I create a file with the document type of a Google Type?
If I enter a Mime Type of 'GOOGLE_DOCS' as text, it creates a file, but it creates a file with a file type of application/octet-stream.
If I use a MimeType of MimeType.HTML, I don't get an error, and the file is viewable from my Google Drive.
You can use DocumentApp.create('File_Name') to create a fileType of GOOGLE_DOCS. DocumentApp service allows to create and manipulate Google Documents. For more details, you may check the reference.
References:
https://developers.google.com/apps-script/reference/document/document-app
In order to place the recently create Document in a Folder, you may use DriveApp. Here is a sample code.
function createandPlaceInFolder(){
//Create the document
var doc = DocumentApp.create('My new file');
//get it as a drive file
var file = DriveApp.getFileById(doc.getId());
//get the target folder
var targetFolder = DriveApp.getFolderById('MY_FOLDER_ID');//Change it to the folder_Id
//place the file in target folder
targetFolder.addFile(file);
}
I'm using this modified script for making sheet backups.Maybe it can be useful, it has fixed this same issue for me. It needs to enable Drive API before using it.
function makeCopy(fileSheetId, dstFolderId) {
var fileSheet = DriveApp.getFileById(fileSheetId);
var dstFolder = DriveApp.getFolderById(dstFolderId);
var f = fileSheet.makeCopy(dstFolder);
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
Drive.Files.update({"parents": [{"id": dstFolderId}]}, f.getId());
}
}
function run() {
var fileSheetId = "<Sheet ID>";
var dstFolderId = "<Destination folder ID>";
makeCopy(fileSheetId, dstFolderId);
}