I am working on a script that I can't get quite right. I need to get a script that will allow me to insert an empty row above the previous top row.
So, row 2 is always the top, but when row 2 is edited, I want it to automatically create another row above it, taking its place as row 2. I was sort of able to achieve this by creating a column I've called "Key" and when I add the text "AUTOADD" to that column it will autoadd a row above. However, I would ideally like to not have to add that text to get it to work.
Here is what I have:
function onEdit(e) {
// get sheet
var sheet = SpreadsheetApp.getActive().getSheetByName("ChatAgenda");
// Get the edited range
var editedRange = e.range;
// check if cell A2 was edited
if (editedRange.getA1Notation() === "A2") {
// check if value is a desired value
if (editedRange.getValue() === "AUTOADD") {
// if yes to both, insert new row
sheet.insertRowBefore(2);
}
}
}
How about inserting a checkbox in A1 of ChatAgenda
Then use this code:
function onEdit(e) {
const sh = e.range.getSheet();
if (e.range.columnStart == 1 && e.range.rowStart == 1 && e.value == "TRUE") {
e.range.setValue("FALSE");//Reset the checkbox
sh.insertRowBefore(2);
}
}
When you check the checkbox it adds and row and resets the checkbox
Related
I'm trying to write script that will achieve the following logic:
If cell J1 has a value of 1, show columns 1-10. If cell J1 has a value of 2, show columns 1-18. If cell J1 has a value of 3, show columns 1-26. If cell J1 has a value of 4, show columns 1-36.
Here' what I have so far:
function onOpen(e) {
hideVersions_(e);
}
function hideVersions_() {
// get current sheet
var sheet = e.source.getActiveSheet();
// get row and column of edited cell
var row = e.range.getRow();
var col = e.range.getColumn();
if (col == 10 && row == 1 && sheet.getSheetName() == 'Design') {
if (e.value === "2") {
sheet.hideColumns(19, 17); // hide column 19-36 (S-AJ)
sheet.showColumns(1,17); // show column 1-18 (A-R)
}
if (e.value === "3") {
sheet.hideColumns(27, 9); // hide column 27-36 (AB-AJ)
sheet.showColumns(1,25); // show column 1-26 (A-AA)
}
if (e.value === "4")
sheet.showColumns(1,35); // show column 1-36 (A-AJ)
}
else {
sheet.hideColumns(11, 25); // hide column 11-36 (K-AJ)
sheet.showColumns(1,9); // show column 1-10 (A-J)
}
}
As I tried to get this to work I noticed you had an Underscore on your Function Name
function hideVersions_() {
That kept me from running and testing that Function.
You also Passed e from the onOpen Event into the hideVersion Function, but did not declare e as a parameter.
Instead of the onOpen Event do you want to use the onChange Event? Even though you might be making other changes we can modify the script to only look at cell J1 on a specific sheet. You'll notice in the code below I added an if statement to check if e is Null, this allowed me to test the file in the editor with out the triggering event.
I think your logic in your if statement can be simplified, not sure why you are checking if the sheet is a certain sheet of the spreadsheet. I also tend to grab the Value I want instead of letting the e event be the most recently edited cell. This is why I removed the row and col check from your first if statement.
In your if statements you "stringed" your values, but I am assuming you are putting numbers into the cell, and therefore your === is expecting numbers on both sides. Removing the quotes fixed that issue.
In your if statements you hide the new cells and then show cells, I think this can be simplified by Showing all cells and then hiding the new cells.
Below is the code that I got to work that completes what you asked for:
function onOpen(e)
{
hideVersions(e);
}
function hideVersions(e)
{
// get current sheet
if ( e == null) // When you run this Function in Editor
{
var sheet = SpreadsheetApp.getActiveSheet();
}
else
{
var sheet = e.source.getActiveSheet();
}
// get Control Cell J1
var controlValue = sheet.getRange(1,10).getValue(); // J1 is Row 1 Col 10
Logger.log(controlValue);
var lastColumn = sheet.getLastColumn();
if (sheet.getSheetName() == 'Design')
{ //since we grabed the cell explicitly, only Need to check SheetName
if (controlValue === 2)
{
Logger.log("Hiding s-AJ");
sheet.showColumns(1, lastColumn); // show All
sheet.hideColumns(19, 17); // hide column 19-36 (S-AJ)
}
if (controlValue === 3)
{
Logger.log("Hiding AB-AJ");
sheet.showColumns(1, lastColumn) //Show All
sheet.hideColumns(27, 9); // hide column 27-36 (AB-AJ)
}
if (controlValue === 4)
{
Logger.log("Showing all");
sheet.showColumns(1,lastColumn); // show all
}
else
{
Logger.log("Hiding K-AJ");
sheet.showColumns(1, lastColumn); // Show All
sheet.hideColumns(11, 25); // hide column 11-36 (K-AJ)
}
}
}
This is what the onOpen() event object looks like:
{"authMode":"LIMITED","range":{"columnEnd":1,"columnStart":1,"rowEnd":1,"rowStart":1},"user":{"email":"redacted","nickname":"redacted"},"source":{}}
Please note: no e.value
Using a spreadsheet to track issues for a department at work. Currently I have a script built where when you load the issue identifier (column C), column I auto fills with the current date and time to serve as a timestamp to document when the issue was added.
I also want to build a script where when you check the box in column M, the entire row the checkbox is in deletes itself. In other words, when the issue is resolved (complete) you check the box and the entire row containing the issue deletes itself.
Both scripts need to run on all sheets within the workbook.
Here is the script I have written so far, which works perfectly, to add the timestamp:
function onEdit () {
var s = SpreadsheetApp.getActiveSheet();
var r = s.getActiveCell();
if( r.getColumn() == 3 ) {
var nextCell = r.offset(0, 6);
if( nextCell.getValue() === '' )
nextCell.setValue(new Date()).setNumberFormat('MM/dd/yyyy HH:mm:ss');
}
}
SUGGESTION
In my understanding of your question, you are trying to:
Using an onEdit simple trigger, when a cell in column C gets updated, you are placing a timestamp (which already works).
On the same onEdit trigger, you are also trying to delete the row that is adjacent to a checkbox cell that gets checked on column M.
You need to use the deleteRow() method to delete a row. Perhaps you can try using this sample tweaked script below using JavaScript Function call() & Conditional (ternary) operator to have a cleaner & organized script flow.
Sample Script
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var r = s.getActiveCell();
var nextCell = r.offset(0, 6);
const ifColumnC = {
placeTimeStamp: function () {
return nextCell.getValue() === '' ? nextCell.setValue(new Date()).setNumberFormat('MM/dd/yyyy HH:mm:ss') : null;
}
}
const ifColumnM = {
deleteRow: function () {
return r.getValue() == true ? s.deleteRow(r.getRow()) : null;
}
}
/**If Column "C" gets edited call "placeTimeStamp" function
* otherwise if Column "M" checkbox cell gets checked, call the "deleteRow" function
*/
r.getColumn() == 3 ? ifColumnC.placeTimeStamp.call() :
r.getColumn() == 13 ? ifColumnM.deleteRow.call() : null;
}
Demo
NOTE: If there's anything else missing or have been misunderstood, feel free to comment.
This question already has answers here:
How to show/hide rows in Google Sheet depending on whether check box is ticked
(1 answer)
Hide/unhide rows based on checkbox on Google sheet
(2 answers)
Hide Rows Based on Check Boxes - Google App Script
(2 answers)
Hide rows based on multiple checkbox values
(1 answer)
Closed 6 months ago.
Trying to create a script that will do the following:
Only operate for one specific worksheet within my workbook
Hide multiple non-sequential columns when a checkbox is checked
Unhide multiple non-sequential columns when a checkbox is unchecked
Incorporate three checkboxes total for three separate column groups
Here is what I'd like to set up:
When the checkbox within cell A25 is checked on worksheet 'Product Pricing', columns C,E,I,K,O,Q,U,W,AA,AC,AG,AI,AM,AO,AS,AU,AY,BA,BE,BG,BK,BM will hide.
When the checkbox within cell A25 is unchecked on the same worksheet, the same columns will unhide.
Then I need to repeat the above functions with two additional column sets.
I'm not a programmer by trade but can create some pretty robust spreadsheets using scripts, functions and conditional formatting. I appreciate anyone willing to help me learn something new that I can apply to this project as well as future projects.
Thanks so much!!
It can be something like this:
function onEdit(e) {
const name = e.source.getActiveSheet().getName();
if (name != 'Sheet1') return; // if not Sheet1 do nothing
const col = e.range.columnStart;
if (col != 1) return; // if not column A do nothing
const row = e.range.rowStart;
switch (row) {
case 1: var ranges = ['d','e']; break; // checkbox on row 1
case 2: var ranges = ['f','g']; break; // checkbox on row 2
case 3: var ranges = ['h','i']; break; // checkbox on row 3
default: return;
}
const value = e.value;
if (value == 'TRUE') hide_cols(ranges); // if check --> hide
else unhide_cols(ranges); // if uncheck --> unhide
}
function hide_cols(ranges) {
var sheet = SpreadsheetApp.getActiveSheet();
ranges.forEach(r => sheet.hideColumn(sheet.getRange(r+'1')));
}
function unhide_cols(ranges) {
var sheet = SpreadsheetApp.getActiveSheet();
ranges.forEach(r => sheet.unhideColumn(sheet.getRange(r+'1')));
}
Here is my sheet.
Try this:
function onEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == "Sheet0" && e.range.columnStart == 1 && e.range.rowStart == 25 && e.value == "TRUE") {
[1,5,9,11,17,21,23,27,29].forEach(c => sh.hideColumns(c));
}
if(sh.getName() == "Sheet0" && e.range.columnStart == 1 && e.range.rowStart == 25 && e.value == "FALSE") {
[1,5,9,11,17,21,23,27,29].forEach(c => sh.showColumns(c));
}
}
You will need to add the rest of the column numbers I got tired of adding them.
Also this may take longer than 30 seconds so you may require an installable onEdit trigger
I am trying to hide columns based on the selection in A2.
Here is the code I am working with and I am hard stuck.
function onEdit(e) {
var myRange = SpreadsheetApp.getActiveSheet().getRange("A:J");
//Let's get the row & column indexes of the active cell
var row = e.range.getRow(1);
var col = e.range.getColumn(0);
//Check that your active cell is within your named range
if (col >= myRange.getColumn() && col <= myRange.getLastColumn() && row >= myRange.getRow() && row <= myRange.getLastRow()) {
if e.myRange === "Renewal" ? myRange.hideColumns(5)
}
}
If anyone could point me in the right direction it would be greatly appreciated.
Based on your code, I assume you want to hide column 5 (E) if dropdown in A2 is "Renewal". If that's what you want, then you got many issues in your script.
Code:
function onEdit(e) {
// get current sheet
var sheet = e.source.getActiveSheet();
// get row and column of edited cell
var row = e.range.getRow();
var col = e.range.getColumn();
// make sure to only hide/show column if edited cell is A2 in 'Sheet1'
if (col == 1 && row == 2 && sheet.getSheetName() == 'Sheet1') {
// if value of A2 in Sheet1 is Renewal, hide columns, if not Renewal, then show the same columns back
if (e.value === "Renewal") {
sheet.hideColumns(5, 2); // hide column 5-6 (E-F)
sheet.hideColumns(8, 1); // hide column 8 (H)
}
else {
sheet.showColumns(5, 2); // show column 5-6 (E-F)
sheet.showColumns(8, 1); // show column 8 (H)
}
}
}
Mistakes:
getRow() and getColumn() gets the current row and column of the range respectively. You don't pass a parameter here
You do not need to identify if your edited cell is within the range A:J, you only need to specify that row and column should be pointing to A2 (and a specific sheet if needed be which is considered in )
Ternary operators do not need if statement before it and it always need the else part. Thus I added showColumns to show the hidden column if A2 is not Renewal.
hideColumns() is a sheet method, not range, thus you need to get the sheet you currently edit. Additionally, it accepts 2 parameters, the index where it starts hiding a column and how many columns you need hidden.
Output:
Resources:
getRow/getColumn
hideColumns/showColumns
Ternary operators
Here is my test sheet.
Goal: whenever I click on cells A5:A10 in 'Sheet 1', I want the value of A1 to change to B5:B10.
For example: if I click A7, A1 = B7.
Note: I don't want this script to run for any other sheet or document.
Can you please help me create a script to run automatically for this purpose?
Explanation:
Indeed, the onSelectionChange(e) trigger is what you are looking for.
You just need to take advantage of the event object to capture information of the selected cell.
When you click on a particular cell in range A5:A10 of Sheet1 the following script will update the value of cell A1 to the corresponding value of B5:B10.
What is important here is to understand the if condition I used:
if (as.getName() == 'Sheet1' && row>4 && row<11 && col==1)
Essentially, I am asking for selections only in Sheet1, after row 4 and before row 11 and column 1. That is basically the range A5:A10.
Solution:
function onSelectionChange(e) {
const as = e.source.getActiveSheet();
const row = e.range.getRow();
const col = e.range.getColumn();
if (as.getName() == 'Sheet1' && row>4 && row<11 && col==1){
as.getRange('A1').setValue(as.getRange(row,2).getValue());
}
}
You could also use offset to get the value of the next column instead of hardcopying the number 2.
Replace:
as.getRange('A1').setValue(as.getRange(row,2).getValue());
with:
as.getRange('A1').setValue(e.range.offset(0,1).getValue());
but both approaches work just as fine.
As an alternative to what Marios suggests, I prefer exiting as early as possible (since the onSelectionChange can fire very rapidly, I find it somewhat more performant). So, you can move your check to the top of the function (the rest still apply):
function onSelectionChange({ range }) {
const sh = range.getSheet();
const shname = sh.getSheetName();
if( shname !== "<sheet name here>" ) { return; }
//continue if ok
}
Note that usually, it is better to put the sheet name in a configuration object (or, even better, in a function that returns a configuration object) for easy maintenance.
Also, since each sheet has a unique Id (you can visually find it in the gid anchor of the open spreadsheet URL or programmatically with the method mentioned below), you could save you some trouble if the sheet gets renamed and check for id match instead with getSheetId:
function onSelectionChange({ range }) {
const sh = range.getSheet();
const id = sh.getSheetId();
if( id !== 123456789 ) { return; }
//continue if ok
}