Named ranges get deprotected when spreadsheet is copied - google-apps-script

Firstly, forgive my bad english and my little knowledge of GAS.
I have an SpreadSheet that will be programmatically copied about 500 times (one copy for each student).
Teachers will fill in the attendance of the students; and parents will be able to view and insert comments.
Deploying code is quite ready, but while testing I have found THIS ISSUE:
In the template, I have named and protected lots of ranges, in order to teachers not to spoil the sheets. If I share the template, solution works. But If I COPY the template, either manually or programmatically, the protection disappeares in the copies, although the named ranges are still there.
For my distress, I have read in another message that range protection cannot be set programmatically, so I will not be able to restore the protection that way.
Any suggestions?

You might want to check this out.
It sounds like you have to do a 2 step process: copy the template creating a new sheet and then copy the template permissions to the new sheet. Good luck

Related

How to add cell values across multiple separate Google Sheet files, when each file also has several worksheets?

To implement an exercise in my upcoming Winter Quarter course, to reduce the burden on students and myself, I need to be able to add the value of a given cell across every student's file and post the value in a separate (class aggregate) file.
Each student file will itself contain several worksheets, and one cell value I need to aggregate may be on the top worksheet, another might be on, say, the third worksheet.
I'm hoping someone can provide an example of how to reference a given cell across separate Google Sheet files, so I can achieve the above. Once I write the formula, I am assuming, that since as instructor I will be the owner of all the files, the aggregate file will be dynamically updated as a student file changes.
Without this feature I would have to restrict what students can do, just to make my own task of then constructing the resulting aggregate easier.
The toy example below assumes that 3 students, each maintain a 2-worksheet Google Sheets file, as in
https://docs.google.com/spreadsheets/d/1pn9D6s382lvnsY-GoMr92aFGFmL_11N2g4tci0tWyzQ/edit?usp=sharing
https://docs.google.com/spreadsheets/d/1aqrGEJQUFg8cdpJwOaj7ZO64iOm9op0U4kXsBn72JMI/edit?usp=sharing
https://docs.google.com/spreadsheets/d/18ixwhnSVesDDfba2AvSN7v-TPiemGEtavkAlw9GS02c/edit?usp=sharing
and I want to add up numbers in the second column of the first worksheet in
each Google Sheets file, to get a "class aggregate" file, as in
https://docs.google.com/spreadsheets/d/18XnZ7ZaVGfxOTiaT11FH_t5s5RWQQevfZFWrUWb9gPM/edit?usp=sharing
without having to do a manual copy and paste and add (which is what I did
above). Given that the
student-maintained Google Sheets are weblinks (and I'll be the owner of
those files as well as I'm the instructor), is there a simple way to use a
longer path name and dynamically update the class aggregate file.
I hope I have explained what I want to do. Please let me know if you have
any questions. Thank you for your time and attention.
How about this without knowing anything else about your spreadsheets:
function ttttttttt(obj) {
const ss = SpreadsheetApp.getActive();
ss.getSheets().forEach(sh => sh.getRange(obj.a1not).setValue(obj.value));
}
Both Cooper and Tanaike above have offered suggestions using scripting, which I realize are much better answers than what I got from pursuing a blog.google link that I was sent by a colleague. Clearly scripting offers more flexibility, and will let me do far more things. My immediate goal was to see whether I could generate the numbers in my Aggregate file without using manual copy and paste.
The link https://blog.google/products/g-suite/g-suite-pro-tips-how-sync-one-spreadsheet-another-google-sheets/ taught me how to reference a tab in a worksheet, and then I first tried the function SUM. That does not seem to work across separate Google Sheet files. Then I tried the same Importrange function shown in an example in the link, and that did work. So I achieved what I wanted by then doing what I really wanted to do by first using IMPORTRANGE, and then using SUM inside the same tab. I checked that it would dynamically update, by changing one number 10 in the Sheet_10 toy file to 12. And the aggregate also changed.
What I did is shown in https://docs.google.com/spreadsheets/d/18XnZ7ZaVGfxOTiaT11FH_t5s5RWQQevfZFWrUWb9gPM/edit#gid=0
Given my winter quarter will start soon, and I am definitely not clever in coding, to get ready for class I will probably go with the less elegant solution. This Google Sheets problem arose in the context of wanting each student to maintain his own portfolio, but to show them aggregate performance in addition to other information they find.
Google Sheets has 400+ functions, but only some work across different files. SUM does not, IMPORTRANGE does. I've learnt a lot today. As I find time, I will try to use the scripting suggestions given here. Thanks for your time, and your help.

How to solve the limitation of IMPORTRANGE formula in google sheet?

I have 50 google sheet files for 50 students. They need to key in their answers in their own google sheet file when they are asked to do so. I have a main google sheet to consolidate their data by using IMPORTRANGE formula. This is my formula:
=QUERY({IMPORTRANGE(...);IMPORTRANGE(...);IMPORTRANGE(...);...},"Select * where Col1 is not null")
I will have 50 IMPORTRANGE in the formula. So as expected, the main google sheet is very lag when the 50 students start to key in their answers at the same time. Sometimes, the formula will show #Value when all the students started to answer the questions at their own google sheet file. I need to keep refreshing the main google sheet so that the data will come out, but it will disappear again in a short while then I need to refresh it again (although it will settle down once most of the students finished answering the questions).
I know that using IMPORTRANGE is really not an efficient way to consolidate their answers in main google sheet file but I don't have other better way.
I tried to write a script so that they can send in their data by clicking the button assigned with the script. However, all the students need to go through the authorization process when they run the script for the first time. They don't know how to proceed when they saw the authorization process (not very good in using computer).
May I know is there any ways or tricks that I can use to solve the IMPORTRANGE issue? Or there are some way to write the script where we are not required to go through the authorization process when we run the script for the first time?
Hope to get some advice and help on this as I couldn't find a better way from Google already. Any help will be greatly appreciated!
If I understood correctly what you are looking is that your spreadsheet show in real-time the data being entered simultaneously on 50 different spreadsheets. I'm afraid that Google Sheets is not the right tool for what you are trying to do the way that you are trying to do it. Basically you have two options : change it or use a different tool.
It's not a good idea to have and array of multiple IMPORTRANGE functions that are being edited simultaneously because while the official docs says that IMPORTRANGE functions are updated every 30 minutes when the source and the spreadsheet having formula are opened at the same time the import is done practically immediately and could happen multiple times during the recalculation making causing it to start over an over again.
Replacing the above array by script might help only if you are open to not have the destination spreadsheet updated on real time as scripts are slow.
Replacing the above array by a program that uses the Google Sheets API also might help only if you are open to not have the destination spreadsheet updated on real time as the spreadsheet refresh.
Regarding running a script without requiring authorization that is only possible when using simple triggers and / or removing all the scopes that require authorization to run. Please bear in mind that you might create installable triggers to run other using the authorization of the user who creates them.
Related
Combining multiple spreadsheets in one using IMPORTRANGE
Why do two users sometimes see different values from importrange?
Multiple IMPORTRANGE
Using that many IMPORTRANGE formulas is definitely a bad idea. What I'd suggest you to do:
keep a list of all your student spreadsheet in your main document
write a script that will browse through all of the spreadsheets from that list and copy/paste values into your main document
create a time based trigger that will run the script every X minutes (or hours), depending on how accurate you want the results to be
This is a simple solution, but efficient. Depending on the amount of data and number of students/spreadsheets you may consider other solutions (like writing a cloud function that will do the same as the script) but I think this will work for your use case

How do I delete a container-bound script when a Google Sheet is pointing to multiple?

I have been put in charge to automate several Google Sheets for different teams throughout our organization.
It started out with 1 main template. Easy enough.
That template is copied each time a new project comes in.
Eventually a second template was born off of the original (the original is still used as well though)
Some changes were made to the UI of the sheet and I added additional automation based off of the new columns. All seemed well.
As of last week, when I go to the Script Editor of a sheet I get this window:
Let's say I select the first option. If I edit it and test the code, it doesn't work as expected because it's still pulling from the other 2 scripts!
I don't know when or how this happened.
How can I fix this?
You can manage you script by going to: Google Scripts

How to hide certain columns for a user?

On a shared Google spreadsheet:
I don't want a specific user in my domain to view columns with sensitive data, but this person should still be able to edit the rest of the spreadsheet.
I tried creating a 'master' spreadsheet and using importrange to bring the data into a 'shared' sheet, but once I edit any cell in the shared spreadsheet, importrange no longer works as the sheet is emptied out.
Is there a quick way to do this, maybe using scripting?
After some research and trying various different options, I was finally able to achieve what I want using the importrange function.
At first, I tried using a combination of hide columns & protect range, but this wouldn't work because a simple copy & paste would reveal the contents of the hidden columns.
Solution: The 'master' spreadsheet does not have any sensitive column data and can be shared with everyone in the organization... I then ADD the sensitive data to a new spreadsheet and use importrange to grab contents from the 'master'. (Previously I had the roles reversed, but this didn't work)
You may want to add unique keys per row entry so that sorting etc won't mess things up when you zip-up the sensitive data and the 'master' data.
I came here looking for a way to share only certain columns of a spreadsheet with a customer, but not all.
As noted in the other answer, using =IMPORTRANGE works well, but a clever customer could simply edit the function and see the other columns.
My solution was to first create a 'proxy' spreadsheet that imported only the columns I want the customer to see. This proxy spreadsheet is not shared.
Then, I created another spreadsheet that imported the columns from the proxy, and shared that spreadsheet with the customer. This way, even with edit privileges, it's impossible for him to see anything that isn't on the proxy spreadsheet.
A bit clunky to be sure, but it worked perfectly for my situation.

Google Apps Script - Is it possible to update a protected range from a script?

I want to use protected ranges to lock down the range, but by using a UI I want to enable users to make edits, insert new data, etc. I just want the edits to be deliberate.
I've thought of a few solutions but am unsure of how they would impact the load, and not sure which would be the best direction:
Unprotect the ranges and reprotect, give edit permissions and take them away. Use java script instead of the built in protected ranges functionality. It doesn't seem possible, but even if the scripts were ran from my account that would work (the workbooks are all working as designed from my account, but I have edit access to the protected ranges).
Any help would be much appreciated, thanks in advance.
Background on the scripts:
I have workbooks for specific projects within the company, and a master workbook, which sync two ways. There is a lookup key, simply the facility/feature specific title, and so I have a script that would allow both locations to be updated simultaneously. I also have a template for new features, or the facility specific projects each have their own templates, and I need users to be able to add a new sheet within these workbooks, and this data to update the master workbook "AllTasks" sheet used for various queries, but in both workbooks I need to have protected ranges.
Running scripts from your account will only work if you deploy the script as a web app. Users would go to a separate URL, fill out the form, submit, etc and as long as the script is being run under your account (there is an option for this when deploying as a web app), it will insert/update protected ranges since you have edit access. Users can still go into the workbook separately and add sheets to it (as long as they have edit rights), they just can't touch the protected ranges unless they have separate rights for those.
But if the users will run these scripts directly from the spreadsheet, I don't believe it is possible to run from your account. But I think the above would be the best solution. I don't see any scripts that can unprotect/protect ranges yet anyways, only sheets.
If it only needs to be protected against accidental editing you could set data validation rules. The Script for the UI can then adjust those data validation rules prior to editing.
var allowedText = "Yes"
var cell = SpreadsheetApp.getActive().getRange('A1');
var rule = SpreadsheetApp.newDataValidation().requireTextEqualTo(allowedText).build();
cell.setDataValidation(rule);
cell.setValue(allowedText);
This will not protect against malice, nor will it protect against hiding, unhiding, deleting or adding cells or deleting the contents of cells, but it will protect against accidental overwriting of the cell.