I'm new to using Google Apps Script, I still need to read the documentation.
I have a list of sheets that are inside a folder, in this list (all Excel files), and these fields (GDrive_ID, File_Name, Full_Path, URL), I would like a function to read either the ID of the file or URL and count the number of sheets within each Google Workbook.
I found this code on a forum and it served, only for the current worksheet, it would be possible to adapt it to search for this data inside the cell (which is actually the address for the worksheets), having with reference the ID, URL or name of the worksheet source?
I'm using this code in current file:
function getNumSheets() {
return SpreadsheetApp.getActiveSpreadsheet().getSheets().length;
}
Count Sheets and Sheets
Convert All Files to Google Sheets: https://stackoverflow.com/a/56073634/7215091
function countSheetsAndSheets() {
const folder = DriveApp.getFolderById("folderid");
const files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
const shts = [];
while (files.hasNext()) {
let file = files.next();
let ss = SpreadsheetApp.openById(file.getId());
shts.push({ "name": file.getName(), "id": file.getId, "sheets": ss.getSheets().length })
}
//Logger.log(JSON.stringify(shts));
return JSON.stringify(shts);
}
Related
I know it is possible to convert excel files to Google Sheets using script and drive API, but I'm looking for script to convert the excel sheet and move the converted file to a different folder.
So the required steps are as follows:
Convert excel (.xls/.xlsx) to Google Sheet from FolderA.
Move converted file from FoldarA to FolderB.
Delete original excel file from FolderA
Hopefully step 3 avoids this, but avoid duplicating already converted file.
The excel files are being pasted into a local folder that is being synced to google drive, and the files are no larger than 3mb. The current script is as follows. This is converting the files but placing them in the root folder, and will duplicate the conversion when the script runs again.
function importXLS(){
var files = DriveApp.getFolderById('1hjvNIPgKhp2ZKIC7K2kxvJjfIeEYw4BP').searchFiles('title != "nothing"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = { title : name+'_converted',
key : ID
}
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
}
}
}
You want to create the converted Google Spreadsheet files to "FolderB".
You want to delete the XLSX files in "FolderA" after the files were converted.
You want to achieve above using Google Apps Script.
If my understanding correct, how about this modification? In this modification, I modified your script.
Modification points:
You can directly create the file to the specific folder using the property of parents in the request body.
You can delete the file using Drive.Files.remove(fileId).
Modified script:
Before you use this script, please enable Drive API at Advanced Google services.
function importXLS(){
var folderBId = "###"; // Added // Please set the folder ID of "FolderB".
var files = DriveApp.getFolderById('1hjvNIPgKhp2ZKIC7K2kxvJjfIeEYw4BP').searchFiles('title != "nothing"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name+'_converted',
parents: [{id: folderBId}] // Added
};
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
// Drive.Files.remove(ID); // Added // If this line is run, the original XLSX file is removed. So please be careful this.
}
}
}
Note:
If the number of XLSX files is large, the execution time might be over 6 minutes.
About // Drive.Files.remove(ID);, when you run this script, please be careful. Because the original XLSX files are completely deleted when the script is run. So I commented this. At first, please test the script using sample files.
References:
Files: insert
Files: delete
I have some code below that takes all the tabs (excluding 2 of them) in a Google Sheets file and creates independent Google Sheets files for each of them. Right now, they are saving by default in root folder (My Drive), but I would like them to be created in the same active folder as the file from which I call my Google Apps Script. Does anyone know how I can do that with the below code? I also want to avoid scenarios where it's created first in My Drive and then moved to the Shared Drive. The reason for this is because other people may run this code and I want to avoid an instance where the folder in My Drive needs to be updated in the code based on who runs this script.
The simplified version of my above paragraph for brevity: How can I adapt the below code so that the Google Sheets files that are created show up in the active Google Shared Drive folder? I will enabling the Drive API.
My Current Code:
function copySheetsToSS(){
var ss = SpreadsheetApp.getActive();
for(var n in ss.getSheets()){
var sheet = ss.getSheets()[n];
var name = sheet.getName();
if(name != 'ControlTab' && name != 'RawData'){
var alreadyExist = DriveApp.getFilesByName(name);
while(alreadyExist.hasNext()){
alreadyExist.next().setTrashed(true);
}
var copy = SpreadsheetApp.create(name);
sheet.copyTo(copy).setName(name);
copy.deleteSheet(copy.getSheets()[0]);
}
}
}
In your situation, when your script is modified, how about the following modification?
Modified script:
In this modification, Drive API is used. So, please enable Drive API at Advanced Google services.
function copySheetsToSS() {
var ss = SpreadsheetApp.getActive();
var folderId = DriveApp.getFileById(ss.getId()).getParents().next().getId();
for (var n in ss.getSheets()) {
var sheet = ss.getSheets()[n];
var name = sheet.getName();
if (name != 'ControlTab' && name != 'RawData') {
var alreadyExist = DriveApp.getFilesByName(name);
while (alreadyExist.hasNext()) {
alreadyExist.next().setTrashed(true);
}
var newSS = Drive.Files.insert({ title: name, mimeType: MimeType.GOOGLE_SHEETS, parents: [{ id: folderId }] }, null, { supportsAllDrives: true });
var copy = SpreadsheetApp.openById(newSS.id);
sheet.copyTo(copy).setName(name);
copy.deleteSheet(copy.getSheets()[0]);
}
}
}
In this modification, first, the parent folder of Spreadsheet is retrieved. And, in the loop, the new Spreadsheet is created to the specific folder using Drive API.
Note:
In this case, it is required to have the write permission of the folder. Please be careful about this.
References:
getFileById(id)
getParents()
Files: insert
I am trying to list all the files I have in a shared drive in a spreadsheet with their name and the URL link.
I came across the following Google script
function findFilesInfo() {
const folderId = '1vNaHwTQ2WObU9Hil5GMqXdiokYp5wfDH'
const folder = DriveApp.getFolderById(folderId)
const files = folder.getFiles()
const source = SpreadsheetApp.getActiveSpreadsheet();
const sheet = source.getSheetByName('Sheet2');
const data = [];
while (files.hasNext()) {
const childFile = files.next();
var info = [
childFile.getName(),
childFile.getUrl(),
childFile.getLastUpdated(),
];
data.push(info);
}
sheet.getRange(2,1,data.length,data[0].length).setValues(data);
}
From the following question here
I tried to implement it and it's working for my own personal drive, but when I change the ID to a shared drive, it keeps giving me the following error:
TypeError: Cannot read property 'length' of undefined (line 20, file "get name")
I tried removing the data.length or set a specific number for the getRange function, it all gives me the same error.
Am I doing anything wrong here?
Replace
sheet.getRange(2,1,data.length,data[0].length).setValues(data);
by
if(data.length > 0) sheet.getRange(2,1,data.length,data[0].length).setValues(data);
The above because the error message will occur when the folder hasn't any file.
Related Q/A about working with subfolders
Iterate Through Folders/Subfolders/Files in Google Drive
I need to list all the files in subfolders using google script
How to list also files inside subfolders in google drive
How best to delete all files in a folder and its subfolders
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 have a google sheet file that needs to find the URL of another google sheet where only its name is known (I need its URL so I can retrieve the data externally through other apps).
To simplify this, I save both g-sheets files under the same folder in Google Drive. I understand I can do this within the same sheet as below, how can I do this when the "ss" refers to another google sheet file and I only know its name.
var ss = SpreadsheetApp.getActiveSpreadsheet();
Logger.log(ss.getUrl());
Ideally I want to do it through a cell formula but will be ok if I need to add a function to "script editor".
I got it working till here where it runs ok from the Script editor:
function listFiles() {
var baseFolderObject = DriveApp.getFolderById('0B38VWNq67cFHZVdWcE5KREZXS1U');
var results = [];
var types = [MimeType.GOOGLE_SHEETS]; //, MimeType.GOOGLE_DOCS];
for (var t in types) {
var files = baseFolderObject.getFilesByType(types[t]);
var file, data, sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow(["Name", "Date", "Size", "URL", "Download", "Description", "Type"]);
while (files.hasNext()) {
var file = files.next();
results.push(file);
data = [
file.getName(),
file.getDateCreated(),
file.getSize(),
file.getUrl(),
file.getId()
];
sheet.appendRow(data);
}
}
}
If you have the id of the folder both spreadsheets are in, why not run a query on the folder and filter out the file you are looking for by name.. Once you have that file, then grab it's id.. With the ID you can then parse it into a google spreadsheet URL. Hope this helps.