I want to allow editing of specific range to specific gmail id. For example A1 contains gmail id of Tom and I want to allow Tom to edit B1 to G1, and A2 contains gmail id of James and I want to allow James to edit B2 to G2. How Should I do that. There are 400 different gmail id of different persons I want to allow them to edit specific ranges according to the gmail id present in column A. How should I do that. Manually doing this is very time consuming.
How to protect specific cells on a spreadsheet
You can use the following sample code that protects the cells from A1 to B10.
// Protect range A1:B10, then remove all other users from the list of editors.
var ss = SpreadsheetApp.getActive();
var range = ss.getRange('A1:B10');
var protection = range.protect().setDescription('user name or ID just as a reference');
var me = Session.getEffectiveUser();
protection.addEditor(me);
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
Since you will have the list of IDs on the same spreadsheet, you can modify the code and use a loop to grab the ID from each user and set the protected range and user according to your needs.
Something really important for this to work is that if you run this script you need to be the owner of the spreadsheet, otherwise you may get an error.
You will also need to have the users' email address along with the ID to set them as editors.
Related
I need a simple sequential unique ID.
The UNIQUE_ID column must be unique, and needs to be filled in for new rows if they are added. New rows can be added anywhere in the sheet, and I do not want the unique ID of any of the previously existing rows to be changed, so it cannot simply be based on the row index.
If you want to try Google Script then you can try below:
function onEdit(){
uniqueId();
}
function uniqueId() {
const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1')//change sheet name per your requirement;
const lr = ss.getDataRange().getLastRow();
const idRange = ss.getRange(2,6,lr-1).getValues() //change range per your requirement;
const dataRange = ss.getRange(2,1,lr-1).getValues() //change range per your requirement;
for (i=0; i<dataRange.length; i++){
if(dataRange[i] !=''){
var maxId = Math.max.apply(null, ss.getRange(2,6,lr-1).getValues());
if(idRange[i] == '')
ss.getRange(i+2,6).setValue(maxId+1);
}
}
}
Remove the onEdit Function if you do want to run it on every edit
I constructed a mega-formula that applies various math to word lengths, ASCII codes at different positions and more:
=ArrayFormula(IF(A2:A="",,LEFT(TEXT(TRUNC((MMULT(IFERROR(CODE(SPLIT(LOWER(REGEXREPLACE(A2:A,"(.)","$1|"))&REPT("|",MAX(LEN(A2:A))-LEN(A2:A)),"|",1,0)),0),SEQUENCE(MAX(LEN(A2:A))+1,1,1,0))/CODE(MID(A2:A,1,1))*CODE(MID(A2:A&" ",2,1))-IFERROR(CODE(MID(A2:A,3,1))/(CODE(RIGHT(A2:A))-(CODE(LEFT(A2:A))/IFERROR(CODE(MID(A2:A,4,1)),13))-(CODE(LEFT(A2:A))/IFERROR(CODE(MID(A2:A,6,1)),17))),7)),10)*10^8,"0000000000"),8)))
Applying it against 5000 of the most common words in English plus your shortlist, I worked it out to where there were no duplicates (i.e., every word was assigned a unique code). NOTE: While the generated IDs are all unique, they are not sequential. If that is necessary, this approach will not work for your purposes (but I'm submitting it because it may address the needs of future site visitors).
As written, the word list is in A2:A. The formula would go in the Row-2 cell of the column where you want the codes.
See if that works for you.
SIDE NOTE: I find myself curious as to why one would need a unique code if the words themselves are all unique.
I'm working with google forms and google sheets. I'm trying to create a summary sheet that will automatically update as the form is being filled.
I've been able to pull the data from the other sheets using a FILTER function. Now I want to add a column that shows the name of a country to the filtered column. I tried using concatenate but it didn't work as well as I'd hoped. Can someone help me figure out how to solve this problem.
Please see here for an example of the problem.
Well this is a very inelegant brute force way, but I think it works. See Solution-GK in your sheet.
=QUERY({
{TRANSPOSE(SPLIT(REPT("Nigeria~",ROWS(UNIQUE(FILTER(NIGERIA!A:E,NIGERIA!C:C<TODAY(),NIGERIA!B:B="Charity Fundraiser")))),"~")),
UNIQUE(FILTER(NIGERIA!A:E,NIGERIA!C:C<TODAY(),NIGERIA!B:B="Charity Fundraiser"))};
{TRANSPOSE(SPLIT(REPT("Sierra Leone~",ROWS(UNIQUE(FILTER('SIERRA LEONE'!A:E,'SIERRA LEONE'!C:C<TODAY(),'SIERRA LEONE'!B:B="Charity Fundraiser")))),"~")),
UNIQUE(FILTER('SIERRA LEONE'!A:E,'SIERRA LEONE'!C:C<TODAY(),'SIERRA LEONE'!B:B="Charity Fundraiser"))}},
"select Col1,Col2,Col3,Col4, Col5 where Col2 is not null")
I've added a hard coded literal of the country name, repeated it the number of times needed for the matching data rows, and made it into the first column in your existing data array. I repeat this for the second array you have for the second country.
I'm sure there are far more elegant ways to do this, so we'll see what else is proposed. If you had a list somewhere in your sheet of your country names - ie. Nigeria and Sierra Leone, possibly many more - I'm sure an elegant solution would cycle through those names, pulling the name to build the concatenated data ranges, and also adding the name as the text for each row.
Without needing a list in the sheet, a little bit of code could find all of your tab names, and exclude the non data ones, eg. Solution Here and Summary, and process all of the rest as data.
Note: I'm not clear that you need your UNIQUE statements, unless you are expecting duplicates for some reason. Also, the outer QUERY doesn't seem to be necessary - the inner FILTERs seem to do everything you need.
You could do this with an Apps Script Custom Function.
First, open a bound script by selecting Tools > Script editor, and copy the following functions to the script (check inline comments for more details about the code):
// Copyright 2020 Google LLC.
// SPDX-License-Identifier: Apache-2.0
function SUMMARIZE_FUNDRAISING_EVENTS(sheetNames, ...ranges) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
sheetNames = sheetNames.split(","); // Comma-separated string to array of sheet names
const filteredData = sheetNames.map(sheetName => { // Iterate through each sheet name
const sheet = ss.getSheetByName(sheetName);
if (sheet) { // Check if sheet exists with this name
const sheetData = sheet.getRange(2,1,sheet.getLastRow()-1,4).getValues(); // Source sheet data
const filteredData = sheetData.filter(rowData => {
return rowData[1] === "Charity Fundraiser" && rowData[2] < new Date()
}); // Filter data according to date and type of event
filteredData.forEach(filteredRow => filteredRow.unshift(sheetName)); // Add sheet name to filtered data
return filteredData;
}
}).flat();
return filteredData;
}
Once it is defined, you can use the function SUMMARIZE_FUNDRAISING_EVENTS the same you would any sheets built-in function. This function would accept a series of parameters:
A comma-separated string with the names of the sheets whose data should be summarized (don't add blank spaces after the comma or similar).
The different source ranges (in your case, NIGERIA!A:E and 'SIERRA LEONE'!A:E).
Both of these are necessary, because, on the one side, specifying the source ranges as parameters makes sure that the function executes and updates the summarized data every time the source ranges are edited, and on the other side, when passed as parameters, these source ranges don't contain information about the sheet names, which the script will need when returning the summarized data.
Example of calling the function:
Reference:
Custom Functions in Google Sheets
I have a google sheet with all current staff information. I have a second sheet for when some piece of data needs changed. Last name, Location, job ect.
on second sheet I am looking to have someone:
Enter the user's first name in column B,
and or Last name in Column C,
I would like a drop down box generated in column D from the given info to contain all usernames found in the sheet with current information for all staff that have the given first and or last names provided.
Once a username has been selected, I can get all the pertinent data from that user with a vlookup from the sheet containing all staff info. For example if someone typed Scott in column B, I would like a drop down generated in column D with all staff that have a first name of Scott. Likewise if the last name was supplied and of course if both first and last was supplied.
Validation need to be done that's it,
1) Go to Staff Changes'!B2 and Data Validation> List from range & choose range from 'Staff Info'!B2:B
2) Select cell'Staff Changes'!D2 and Data Validation> List from range & range will be filter formula i.e 'Staffing Changes'N2:N.
Result
Few tweaks in vlookup:
I am not sure if you need username column twice if you don't need then change your vlookup formula from =vlookup(D2,'Staff Info'!A:K,10,0) to =VLOOKUP(D2,'Staff Info'!$G$1:$K,2,0)
Please provide access to trix in future so that changes & result can be shown in it.
UPDATE:
Use data validation as before & hide filter colum or use seperate sheet for filter formula & use query function in cell A3 =QUERY('Staff Info'!A:J,"select ' ',A,F,' ',' ',G,' ',I,' 'where A='"&A2&"' AND F = '"&B2&"' LABEL ' ''Date',' ''Current Last Name',' ''New Last Name',' ''New Building',' ''New Classification'",1) result wil be something like this
QUERY
I am trying to create a custom URL inside Google sheets that uses a predetermined URL + values from particular cells. What im trying to create is a formula to create urls with parameters at scale for an email campaign.
example
domain.net
data I have
A1 Email
B1 Fname
C1 Lname
This is the desired result
domain.net??Email=A1&Fname=B1&Lname=C1
domain.net??Email=emailaddress&Fname=firstname&Lname=lastname
I have a suspicion I am completely missing the point but offer:
=D$1&"??"&A$1&"="&A1&"&"&B$1&"="&B1&"&"&C$1&"="&C1
in case that helps to indicate what additional clarification may be useful.
I have tickets I'm selling for an event, and I have a google spreadsheet with a list of email addresses that should get a discount.
I'd like to check the google sheet once a user types in their email address in the form, and then if theirs is in our list, the discount gets applied.
I can't seem to figure out how to do this. The example code here: https://developers.google.com/sheets/api/quickstart/js requires users to allow access to their google drive, which isn't what I need. I just need to check my own spreadsheet.
How might I do this?
You can use Apps Script (since you're using Forms), if you want a handy solution. I don't know the complexity of your usecase but I'll just demo that this is doable:
So this is my spreadsheet, you can see the names on Column A:
name(0,0)
floyd(1,0)
conor(2,0)
john
carmack
borja
adam
I'm going to look for "adam"
function findPerson() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getSheets()[0].getRange("A1:A7").getValues();
for(var i = 0; i < range.length ; i++){
Logger.log(range[i]);
if( range[i] == "adam"){
Logger.log("FOUND YAH!");
}
}
}
And there, I found him! ;)
If that's a Google Form you're using, the next step would be learning how to Connect Spreadsheet to Google Forms