Undo ability not working after adding Script - google-apps-script

I have a script to hide or show Rows with a specific value, it is working well, only I have problem that if I do change the value of any cell in the Spreadsheet even in other sheet like (sheet2) and I want to Undo that change, the Undo ability not working till I repeat it more than 30 times!!! And If I delete the script, it works normally.
Do I have to add, change or delete any code of this script to make Undo Ability working normally as before adding script?
Thank you
I tried to changed this line: var ss = SpreadsheetApp.getActiveSpreadsheet();
to let Undo working normally
or to make it atleast be affecting in specific sheet but I could't.
Here is the full script...
function myShowHide() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
var lastRow = sheet.getLastRow();
for (i = 4; i <= lastRow; i++) {
var status = sheet.getRange("J" + i).getValues();
if (status == "X") {
sheet.showRows(i);
}
}
var sheet = ss.getSheetByName("sheet1");
var lastRow = sheet.getLastRow();
for (i = 4; i <= lastRow; i++) {
var status = sheet.getRange("J" + i).getValues();
if (status != "X") {
sheet.hideRows(i);
}
}
}

Assuming that you are running this with an installable onEdit() trigger then this will solve the problem of interacting with other sheets.
function myShowHide(e) {
var sh=e.range.getSheet();
var rg=sh.getRange(4,10,sh.getLastRow(),1);
var sA=rg.getValues();
for(var i=0;i<sA.length;i++) {
if(sA[i][0]=="X") {
sh.showRows(i+4);
}else{
sh.hideRows(i+4);
}
}
}
I setup an installable onEdit trigger for this function.
function myNewShowHide(e) {
var sh=e.range.getSheet();
if(sh.getName()!="Sheet1")return;
myShowHide(e);
}
But solving the problem on Sheet1 depends upon how you want the sheet to run. If you run it with an edit trigger then anytime your editing anywhere on the sheet it runs. You could limit the edit range but that requires knowing what you want to do with the sheet and I don't know that.
My recommendation is not to run this kind of function with an onEdit() trigger. This one will run much faster because I get all of the data at one time but the rows are still shown or hidden one at a time.

Related

Use app script to insert more than one row into a sheet on button click

I have a code written to insert a single row into a google sheet below a keyword (a little clunky but I don't mind, unless anyone has a fix for it off the top of their head). Problem is, I want to add 250 rows beneath that and, being new to app scripts, I'm not sure where to specify the number of rows I want it adding for me.
Here's what the code I've got looks like:
function addRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var EditSheet = ss.getSheetByName("Testing"); //source sheet
var LastRowEdit = ss.getLastRow();
for(var i = 1; i <= LastRowEdit; i++)
{
if(EditSheet.getRange(i,1).getValue() == 'add') //keyword
{
EditSheet.insertRowAfter(i);
}
}
}
I would love to hear your suggestions for how I can adjust this to match my goals.
Thank you, guys!
In your situation, how about using insertRowsAfter(afterPosition, howMany) instead of insertRowAfter(afterPosition)? So, how about the following modifcation?
From:
EditSheet.insertRowAfter(i);
To:
EditSheet.insertRowsAfter(i, 250);
By the way, in your script, getValue() is used in a loop. In this case, the process cost becomes high. In order to reduce the cost, how about the following modification?
Modified script:
function addRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var EditSheet = ss.getSheetByName("Testing");
var LastRowEdit = ss.getLastRow();
var row = EditSheet.getRange("A1:A" + LastRowEdit).getValues().map(([a]) => a).indexOf("add");
if (row != -1) {
EditSheet.insertRowsAfter(row + 1, 250);
}
}
Reference:
insertRowsAfter(afterPosition, howMany)

User/Email stamp with onEdit Google Sheets

What I want to do is to place the user's email who is clicking the checkbox to true in the cell directly next to the checkbox that they're clicking on. I've got the code so that I can place my own email there. I've even played with it to the point where it will remove the "#gmail.com," but I cannot get this to show for other users.
I had it, at one point, placing the current users emails in the box, but then it would quickly change to my own. However, I don't remember the state of the code as it was then, and haven't been able to replicate it.
I've tried everything suggested here.
I've also referenced this post here.
Here is my code:
function createTrigger(){
ScriptApp.newTrigger('myFunction').forSpreadsheet(SpreadsheetApp.openById('1Y0-bpAhGzPSS5DIPnoZH4OcY2b9IL8LhvBfc2is0zVU')).onEdit().create();
}
function myFunction(e) {
var groupOneCheck = 3;
var groupTwoCheck = 7;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var checkCell = ss.getActiveCell();
if (checkCell.getColumn() == groupOneCheck) {
var dateTimeCell = checkCell.offset(0,2);
var userCell = checkCell.offset(0,1);
dateTimeCell.setValue(new Date());
userCell.setValue([Session.getEffectiveUser().getEmail()]);
}
if (checkCell.getColumn() == groupTwoCheck) {
var dateTimeCell = checkCell.offset(0,2);
var userCell = checkCell.offset(0,1);
dateTimeCell.setValue(new Date());
userCell.setValue([Session.getEffectiveUser().getEmail()]);
}
}
I want to do the same thing for both of the if statements because they correspond to different columns.
Here is a link to the sheet that I am currently testing with.
It works for me if I use an installable trigger because simple triggers cannot perform functions that require permission.

Protect row when drop down menu changes to "Locked" using app scripts

I am trying to simply protect an entire row (add editors) when someone changes the drop-down menu to "Locked", even the drop-down menu should be protected that is on the same row. This is something that I want to implement in almost all rows of the sheet.
I have found multiple resources that help but I can't combine it properly, would be very thankful for any help!
Bellow are some helpful links I found.
Google sheets: protect cells conditionally?
Protecting Cells Based on Contents of Other Cells in Google Sheets
Protect ranges with google apps script
Add this code to your spreadsheet's script editor and set an onEdit trigger for the below mentioned function.
Replace the email#gmail.com string in code with your actual email
NOTE : This script assumes that first row of the sheet may have three option depending on which the protection of that range is controlled.
Lock : locks that particular column
Unlock : unlocks that particular column
blank : does nothing
function onEdit(e){
var x = [e.range.columnStart,e.range.rowStart,e.range.columnEnd,e.range.rowEnd]
if (x[0]==x[2] && x[1]==1 && x[3]==1){
var lockRangeStart = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1,x[0]).getA1Notation();
var lastCol = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getLastRow();
var lockRangeName = (lockRangeStart+":"+lockRangeStart.match(/(\D*)/)[1]+lastCol);
var lockRange = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(lockRangeName);
if(e.value == "Lock"){
var protection = lockRange.protect().setDescription('Locked Range');
protection.addEditor("email#gmail.com");
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
else if(e.value == "Unlock") {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
if (protection.canEdit() && protection.getRange().getA1Notation() == lockRangeName ) {
protection.remove();
}
}
}
}
}

Inserted formula not doing anything

I have put this little script together to insert an if(vlookup) formula into a spreadsheet but even though it is running it isn't inserting anything into the spreadsheet. Can anyone suggest what I have missed off or overlooked please?
Or is there an easier way to do this with an array? I'm still fairly new so not sure how I would execute that successfully.
function idSiteCoordinator(){
var SS = SpreadsheetApp.getActiveSpreadsheet();
var shLog = SS.getSheetByName("LOG");
//declare how many rows to interrogate (to the last row)
var lastRow = shLog.getLastRow();
var startRow = 2;
for (var i=startRow; i<lastRow+1; i++)
{
//Grab the values for LocationCodes
var siteCo = shLog.getRange([i],[12]).getValue();
//Enter formula
if(siteCo = ""){
siteCo.setFormula('=if(E'+[i]+'="08 - Maintenance Request System",LocationCodes!$E$33,vlookup(D'+[i]+',LocationCodes!$D$3:$E$32,2,false))');
}
}
}
You cannot apply the method setFormula to the value, but to the range. Change this on your method:
var siteCo = shLog.getRange([i],[12]);
if(siteCo.getValue() == ""){
siteCo.setFormula('=if(E'+[i]+'="08 - Maintenance Request System",LocationCodes!$E$33,vlookup(D'+[i]+',LocationCodes!$D$3:$E$32,2,false))');
}

Is it possible to let onEdit trigger for fontstylechanges? (line-through)

Got here two scripts that change the font color based on line-through, both are working.
- First one can be custom triggered,
- Second is onEdit.
The onEdit has my preference, as it automates things instantly, however onEdit does not see changes when a cell's value is getting line-through yes or no.
So is it possible to let onEdit trigger for fontstylechanges?
function colorlinethrough() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // Get spreadsheet
var sheet = ss.getSheets()[0]; // Get first Sheet
var range = sheet.getDataRange(); // Get cells
var data = range.getValues(); // Get the cell values
for (var i in data) {
var editrange = sheet.getRange(parseInt(i)+1,2);
if (editrange.getFontLine() == "line-through") {
editrange.setFontColor("#CCCCCC");
}
else {
editrange.setFontColor("#000000");
}
}
};
function onEdit(e) {
var ss = e.source; // Get spreadsheet
var range = ss.getActiveRange();
if (range.getFontLine() == "line-through") {
range.setFontColor("#CCCCCC");
}
else {
range.setFontColor("#000000");
}
};
also put this question on the g+ community https://plus.google.com/104787958270362345970/posts/GTdBoTZR3YF
Spreadsheets has an onChange event that might do the trick here. onEdit is when the data changes and onChange is when the spreadsheet UI itself changes. Give it a shot.
https://developers.google.com/apps-script/understanding_events