Get all the ID of the files - google-apps-script

I'm working on a folder per grade level with the same content. I used the IMPORT RANGE function to connect the spreadsheets. So I need to update the IDs every time I create another grade level. May I ask if it is possible for me to get all the IDs of all the files that I'm working on without editing or typing them one by one? Maybe a script that can make it easier?
Here's the picture of the list of IDs.
If it is possible, the flow I’m thinking of is to get the filename of the files and then get the id of it.

Explanation:
The following script will get all the file names in the range B3:B. Then forEach file name we use getFilesByName to get the files corresponding to that name. Make sure you don't have files with the same name, otherwise this process will return multiple IDs for the same name and therefore the logic won't work.
Finally we use getId to get the ID of each file and store it into an array. This array will be then pasted to column C starting from cell C3 as you indicate in the screenshot.
Solution:
function myFunction() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet1'); // change that to the name of your sheet
const filenames = sh.getRange('B3:B').getValues().flat().filter(r=>r!='');
const IDs = [];
const folderId = "put your folder id here";
const Folder=DriveApp.getFolderById(folderId);
filenames.forEach(fn=>{
let Files = Folder.getFilesByName(fn);
while(Files.hasNext()){
let file = Files.next();
IDs.push([file.getId()]);
}
});
sh.getRange(3,3,IDs.length,1).setValues(IDs);
}

Related

Get URL of a file in Google Drive thanks to its name

First of all, sorry for my English (I'm learning ^^).
I want to have a script to find a file's url thanks to the name of the file, and then put the URL in my sheet called 'Suivi-des-devis!' in the range 'O2'
The files are always called "FAC_quote number", and the quote number is in sheet 'DEVIS!' in 'E6'.
I really tried to create the script alone, but it doesn't work. Can someone help me to correct the script please ?
function testenregistrement() {
const doc = SpreadsheetApp.getActive();
var f2 = doc.getSheetByName('Suivi-des-devis');
var dossier2 = DriveApp.getFolderById("1WNyBdexfylgflnDeKtMcdIN-eS578dlH")
var nom = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('DEVIS').getRange('E6').getValue();
var files = dossier2.getFilesByName("FAC_" + nom).getUrl(); f2.getRange('O2').setValue(files);
}
The Folder.getFilesByName() method gets a FileIterator object. Use the FileIterator.next() method to get a file, like this:
var files = dossier2.getFilesByName("FAC_" + nom).next().getUrl();

How to open a spreadsheet only by name of the corresponding file in Google Sheets?

I need a way to open a spreadsheet only by having the name of the corresponding file and the folder where the file is located. What I'm trying to do is creating a temporary copy of an active spreadsheet and reading information from the copy file rather than the active one. But unfortunately this copy file won't have a constant ID and URL as it's going to be erased every time after the script is done, and re-created with the next running of the script.
What I already tried is using the URL of the temporary file in order to open the spreadsheet itself, as you can see below.
But it's not useful for me, as I don't have a constant URL of this file (as it will be erased in the end of the script and have a new URL with the next script). But I have a constant name of the file, as well as this will be the only file in the respective folder.
What I also tried is looking for methods to open file only using its name (which is "temp_copy" in a 'temp_folder'). But I didn't find a working solution.
var report = SpreadsheetApp.getActiveSpreadsheet();
var temp_folder =
DriveApp.getFolderById("1EAsvVcFjIw5iGTeF_SxxQJLVlaLHl_pR");
DriveApp.getFileById(report.getId()).makeCopy("temp_copy", temp_folder);
var temp_copy = SpreadsheetApp.openByUrl(' ');
var hiddenSheet = temp_copy.getSheetByName('DATE');
var lastRow = hiddenSheet.getSheetValues(1,1,1,1);
var sheet = temp_copy.getSheetByName('forCSV');
var lastColumn = sheet.getLastColumn();
var activeRange = sheet.getRange(1,2,lastRow,lastColumn);
What I'm expecting as a result is to make the link between the 3rd line of the code (when making a copy of the basic file) and 5th line of the code onwards (when referencing specific range from the temporary file) only by using name of the file or respective folder. In theory it seems so easy, I should be missing something somewhere...
Many thanks in advance!
You can use DriveApp to get a FileIterator which contains the Sheet.
var file, files = DriveApp.getFilesByName("temp_copy");
if (files.hasNext ()){
file = files.next(); // Get first result for name
} else {
return "";
}
var sheet = SpreadsheetApp.openById(file.getId())

Share Google Doc using a Google Script to set an array of emails (in Google Sheets) as editors

I basically am imagining commands that would change the sharing status of sheets it was allowed to edit. For example, I have a master document for a company (a "Roster" for keeping track of where employees are working and which other employees they are working with in that area) and other "Area Sheets" the employees use to keep track of progress. People move around quarterly, so I want to be able to update my Roster and then let the programming update the sharing status of their sheets instead of clicking on every sheet and copy-pasting emails.
As far as I know there is no current possible way to use google products to achieve this. Are there any other ways, barring a New Feature developed by Google?
I don't think I fully understand your requirements, so I'll start be rephrasing what I do understand.
For every employee, generate a list of who they're working with that quarter.
For a certain set of files owned by the employee, make those files editable to the employee's current co-workers.
For point 1, you already have the list built out in Google Sheets, so you can read the contents into arrays for processing. You can use Google Apps Script Spreadsheet Service for this. Example:
var roster = SpreadsheetApp.getActive(); //assuming the script is running within the Roster spreadsheet
var employeesSheet = roster.getSheetByName("Employees"); //assuming sheet name is "Employees"
var employeeEmails = employeesSheet.getRange("B2:B").getValues(); //assuming the emails are in column B with the first row as header
//In this next line I'm going to make a very big simplification.
//I will assume that the coworkers emails are listed as "coworker1#company.com;coworker2#company.com" in the cell.
//This is likely not the case, but you may already have this formatted in a way that works.
//If not, you can merge these values in Google Apps Script, but I'll consider that outside the scope of this question.
var coworkerEmails = employeesSheet.getRange("C2:C").getValues();
For point 2, I assume you already have a way of determining which files need to have their access permissions modified and that you have permission to make those modifications. You'll need to use the Drive Service for this part. In my example, I will assume that all relevant files are saved in a folder specific to each employee and that the folder ID is saved in column D.
var folderIds = employeesSheet.getRange("D2:D").getValues();
for (var i=0; i<employeeEmails.length; i++) {
var folder = DriveApp.getFolderById(folderIds[i][0]);
//At this point, you could give direct access to the entire folder,
//or just to the files within the folder, as I will do.
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
file.addEditors(coworkerEmails[i][0].split(";"));
}
}
Please note that in the above:
This is untested code and meant only to demonstrate how to achieve what I think you're looking for.
No access permissions are being revoked. This would be quite trivial to add, though.
The folder.getFiles() command only gets files that are children of the folder. So, if the folder has child folders, you'll need to traverse through those as well.
You may want to create a custom menu in your Roster spreadsheet to run this script
In the end, including the custom menu, your code could like:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Reset Permissions", functionName: "resetPermissions"});
ss.addMenu("Roster Actions", menuEntries);
}
function resetPermissions() {
var roster = SpreadsheetApp.getActive();
var employeesSheet = roster.getSheetByName("Employees");
var employeeEmails = employeesSheet.getRange("B2:B").getValues();
var coworkerEmails = employeesSheet.getRange("C2:C").getValues();
var folderIds = employeesSheet.getRange("D2:D").getValues();
for (var i=0; i<employeeEmails.length; i++) {
var folder = DriveApp.getFolderById(folderIds[i][0]);
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
file.addEditors(coworkerEmails[i][0].split(";"));
}
}
}
For reference, this is how I assumed the example "Employees" sheet in the "Roster" spreadsheet to look:

Iterate over sheet using GS while there is any data in columns

I need to do a small script, its basic idea is to have a sheet with names in one columns and some random info in another (to the right). The sheet has some count (unknown in advance) of such records, so they are like
John 39483984
George 3498349
Layla 23948
So that a user can enter any number of such simple records, my script must create a file for each name (file is of the same name) and write the number into that file. I managed to find how to create files (though still couldn't find out how to create file in the current folder, same as where the sheet is located - this is just a side question, but if you know how to do it, please tell me). The only real problem is iterating through the records. My idea was to go through them one by one and stop when there is an empty record - basic strategy, but I wasn't able to find how to implement it (yep!). There are range functions, but there I should know in advance the range; also there is a function to get selected cells but that will require a user to select the records, which is strange.
So please suggest me a solution if it exists in this frustration Google Script.
function createFilesForEachNameInSheet() {
// First, you connect to the spreadsheet, and store the connection into a variable
var ss = SpreadsheetApp.openById("SPREADSHEET_KEY_GOES_HERE"); // you do know how to get the spreadsheet key, right?
// Then, you take the sheet from that spreadsheet
var sheet = ss.getSheetByName("Sheet1");
// Then, the "problematic range". You get the ENTIRE range, from end to end, as such:
var wholeRange = sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn());
// Then, you fetch its values:
var rangeValues = wholeRange.getValues();
// At this point you have a bi-dimensional array, representing the rows and columns.
// Assuming you have 2 columns, in the first column you have the names, and in the second you have the unknown value
// You need to use the already known for loop, iterate over all the data, and store it first in an object, so that you create the file only ONCE.
var objectData = {};
for (var i=0;i<rangeValues.length;i++) {
var thisName = rangeValues[i][0];
var thisValue = rangeValues[i][1];
if (objectData.thisName == undefined) objectData.thisName = [];
objectData.thisName.push(thisValue);
}
// Now we have our values grouped by name.
// Let's create a file for each name.
for (var name in objectData) {
DriveApp.createFile(name, objectData.name.join("\n"));
}
// NOTE: if you want to create into a specific folder, you first target it, using the DriveApp:
var folders = DriveApp.getFoldersByName("the folder name goes here");
// folders variable is now an iterator, containing each folder with that name.
// we will iterate over it as follows, and select the one we want.
// the logic for it, you'll select one of your choice:
while (folders.hasNext()) {
var thisFolder = folders.next();
if (/* condition to check if we found the right folder */) {
thisFolder.createFile(name, objectData.name.join("\n"))
}
}
}

Google apps script: loop over tabs to save to separate worksheets

I would like to loop over all individual tabs of a certain worksheet (preferably skipping the ones of array that need to be excluded). For each individual tab I would like to save it as a separate worksheet in Google drive, with the title of the tab as the file name. If the file name already exists it should be overwritten.
Preferably I would like to be able to exclude an array of sheets (e.g. named 'master' and 'test') in the desired script.
Unfortunately my knowledge of Google Apps scripting is not sufficient enough to write it myself. Any working example is highly appreciated.
EDIT: here is how I solved it (suggestions for improvements are always welcome! :-) )
EDIT2: changed the deleteSheet line
function copySheetsToSS() {
var ss = SpreadsheetApp.getActive();
for(var n in ss.getSheets()){// loop over all tabs in the spreadsheet
var sheet = ss.getSheets()[n];// look at every sheet in spreadsheet
var name = sheet.getName();//get name
if(name != 'master' && name != 'test'){ // exclude some names
var alreadyExist = DriveApp.getFilesByName(name);// check if already there
while(alreadyExist.hasNext()){
alreadyExist.next().setTrashed(true);// delete all files with this name
}
var copy = SpreadsheetApp.create(name);// create the copy
sheet.copyTo(copy).setName(name); // rename copied sheet to same name as SS
copy.deleteSheet(copy.getSheets()[0]);// delete default Sheet1 from new copy
}
}
}
Your description is so accurate that it's quite easy to translate in code...
You should have tried and I'm sure the doc would have allowed you to get it working ... it would have been interesting and so rewarding to run a code you wrote yourself !
Here is the more frustrating (for you) solution of a working code ;-) with explanation in comments
function copySheetsToSS() {
var ss = SpreadsheetApp.getActive();
for(var n in ss.getSheets()){
var sheet = ss.getSheets()[n];// look at every sheet in spreadsheet
var name = sheet.getName();//get name
if(name != 'master' && name != 'test'){ // exclude some names
var alreadyExist = DriveApp.getFilesByName(name);// check if already there
while(alreadyExist.hasNext()){
alreadyExist.next().setTrashed(true);// delete all files with this name
}
var copy = SpreadsheetApp.create(name);// create the copy
sheet.copyTo(copy);// copy content
copy.deleteSheet(copy.getSheets()[0]);// remove original "Sheet1"
copy.getSheets()[0].setName(name);// rename first sheet to same name as SS
}
}
}