I am trying to find a working code that will automatically hide a row if the checkbox in column F of that row is checked.
I have tried every script I have found and nothing seems to work. Unfortunately I am not code savvy and I am unable to find the issue.
This is what I currently have:
function onOpen() {
var s = SpreadsheetApp.getActive().getSheetByName("Checklists");
s.showRows(1, s.getMaxRows());
s.getRange('F2:F200')
.getValues()
.forEach( function (r, i) {
if (r[0] == "TRUE")
s.hideRows(i + 1);
});
}
The sheet I am working on is "Checklists" and the column that contains the checkbox is F. The value of the checkbox is either TRUE or FALSE. If the value is TRUE, I want that row to be hidden.
Can someone please help!!!
The quick test I was able to run was to set up a column of checkboxes in column F, then to create a function that catches each edit event on the sheet. This will immediately catch when the user checks a box and will then hide that row.
The trick with using the onEdit event is with determining which cell was actually changed. In your case, you only want to fully follow your logic if the change happens to a checkbox in column F. In my code, I've been using a function to make sure the change is in the desired range. The function looks like this:
function isInRange(checkRange, targetCell) {
//--- check the target cell's row and column against the given
// checkrange area and return True if the target cell is
// inside that range
var targetRow = targetCell.getRow();
if (targetRow < checkRange.getRow() || targetRow > checkRange.getLastRow()) return false;
var targetColumn = targetCell.getColumn();
if (targetColumn < checkRange.getColumn() || targetColumn > checkRange.getLastColumn()) return false;
//--- the target cell is in the range!
return true;
}
So then all your onEdit function has to do is to make a quick call when the edit event is fired to see if the change falls within the range you're looking for. In this case, I set up a variable with my range to check:
var thisSheet = SpreadsheetApp.getActiveSheet();
var checkRange = thisSheet.getRange("F2:F200");
if (isInRange(checkRange, eventObj.range)) {
After that, it's just a matter of picking the row number and hiding or showing. Here's the full example solution:
function isInRange(checkRange, targetCell) {
//--- check the target cell's row and column against the given
// checkrange area and return True if the target cell is
// inside that range
var targetRow = targetCell.getRow();
if (targetRow < checkRange.getRow() || targetRow > checkRange.getLastRow()) return false;
var targetColumn = targetCell.getColumn();
if (targetColumn < checkRange.getColumn() || targetColumn > checkRange.getLastColumn()) return false;
//--- the target cell is in the range!
return true;
}
function onEdit(eventObj) {
//--- you could set up a dynamic named range for this area to make it easier
var thisSheet = SpreadsheetApp.getActiveSheet();
var checkRange = thisSheet.getRange("F2:F200");
if (isInRange(checkRange, eventObj.range)) {
//--- so one of the checkboxes has changed its value, so hide or show
// that row
var checkbox = eventObj.range;
var rowIndex = checkbox.getRow();
Logger.log('detected change in checkbox at ' + checkbox.getA1Notation() + ', value is now ' + checkbox.getValue());
if (checkbox.getValue() == true) {
Logger.log('hiding the row');
thisSheet.hideRows(rowIndex, 1);
} else {
Logger.log('showing the row');
thisSheet.showRows(rowIndex, 1);
}
}
}
Related
I have a spreadsheet that tracks legal cases from start to finish. In that spreadsheet I used a script to create dependent dropdown menus on multiple rows (I'll share the script at the end). The main dropdown menu tells me what Department the case is in. The Departments are Transcription; Doctor; Scheduling; Records; QA; and Billing.
I also have a script that is supposed to moves an entire row of data to a separate tab labeled Billing when the department dropdown menu is set to Billing. I had this script working before I made the dependent dropdown menus and was just using data validation to create my dropdown menu.
Both of these scripts work separately but when I try to use them together the dependent dropdown menus quit working and when the department is set to Billing that row disappears like its supposed to except it doesn't show up on the Billing tab like its supposed to. I have no idea where it goes.
Can someone please tell me how to get both scripts to work at the same time? And, why the row of data disappears when the department is set to Billing but doesn't go to the Billing tab?
Dependent Dropdown Menu Script
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Database");
var wsOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("options");
var options = wsOptions.getRange(2,1,wsOptions.getLastRow()-1,2).getValues();
function myFunction() {
var list = ["a","b","c","f"];
var cell = ws.getRange("J2");
applyValidationToCell(list,cell);
}
function onEdit(event){
var activeCell = event.range;
var value = activeCell.getValue();
var row = activeCell.getRow();
var column = activeCell.getColumn();
var wsName = activeCell.getSheet().getName();
if(wsName == "Database" && column === 5 && row > 1){
if(value === ""){
ws.getRange(row,10).clearContent();
ws.getRange(row,10).clearValidations();
} else{
ws.getRange(row,10).clearContent();
var filteredOptions = options.filter(function(options){ return options[0] === value });
var listToApply = filteredOptions.map(function(options){ return options[1] });
Logger.log(listToApply);
var cell = ws.getRange(row,10);
applyValidationToCell(listToApply,cell);
}
}
}
function applyValidationToCell(list,cell){
var rule = SpreadsheetApp
.newDataValidation()
.requireValueInList(list)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule);
}
Billing Script
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Database");
var wsOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("options");
var options = wsOptions.getRange(2, 1,wsOptions.getLastRow()-1,2).getValues();
function myFunction() {
var list = ["a","b","g"];
var cell = ws.getRange("K2");
applyValidationToCell(list,cell);
}
function onEdit(e){
var activeCell = e.range;
var val = activeCell.getValue();
var r = activeCell.getRow();
var c = activeCell.getColumn();
var wsName = activeCell.getSheet().getName();
if(wsName == "Database" && c === 5 && r > 1){
var filteredOptions = options.filter(function(o){return o[0] === val});
var listToApply = filteredOptions.map(function(o){ return o[1]});
console.log(listToApply);
var cell = ws.getRange(r, 10);
applyValidationToCell(listToApply,cell);
}
}
function applyValidationToCell(list,cell){
var rule = SpreadsheetApp
.newDataValidation()
.requireValueInList(list)
.setAllowInvalid(false)
.build();
cell.setDataValidation(rule);
}
function onEdit(e) {
const src = e.source.getActiveSheet();
const r = e.range;
if (r.columnStart != 5|| r.rowStart == 2 || e.value == src.getName()) return;
const dest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(e.value);
src.getRange(r.rowStart,1,1,30).moveTo(dest.getRange(dest.getLastRow()+1,1,1,30));
src.deleteRow(r.rowStart);
}
All functions have to have a unique name and all functions have access to all sheets. onedit triggers are generated on every user edit and it's up to the onEdit function to route edits from the appropriate sheets using information gathered from the event object. Note: Sheet Name = e.range.getSheet().getName() where e is populated by the event object in the function declaration function onEdit(e) {}
The if statement below limits access to edits that occur on Sheet name "Database" and e.range.columnStart == 5 and rows greater than one
if(wsName == "Database" && column === 5 && row > 1){
if(value === ""){
ws.getRange(row,10).clearContent();
ws.getRange(row,10).clearValidations();
} else{
ws.getRange(row,10).clearContent();
var filteredOptions = options.filter(function(options){ return options[0] === value });
var listToApply = filteredOptions.map(function(options){ return options[1] });
Logger.log(listToApply);
var cell = ws.getRange(row,10);
applyValidationToCell(listToApply,cell);
}
}
if you require actions from other sheets then you must add more if statements or other conditional logic to route the appropriate edit traffic to the the correct processing statements.
I create a grid and a toolbar with Two Menu of menuCheckItem. When i check the menuCheckItem the grid filters even with multiple values and multiple columns.
This working fine, as I have created grid 1st and then the toolbar
this.up('') // Used Instead of Ext.getCmp()
Working FIDDLE - https://fiddle.sencha.com/#view/editor&fiddle/2lop
Now I am trying to create same toolbar along with Menu separately on top 1st and then create grid at below. But while doing this, nly Multiple values is working.
I am trying to filter grid with multiple values as well as multiple columns.
Few things i tried -
// Only Filters One Value at a time with each Columns
store.queryBy(function(record,id){
return (record.get('name') == someValue && record.get('phone') == otherValue);
});
and
// Filters Many Columns with Single Value
filter.add(
property : name, phone
value : "somevalue"
operator : "OR"
);
Is there any way to implement Toolbar 1st and then grid ? And Filter grid with many values and columns simultaneously ?
In this FIDDLE i remade a function(checkchange), which is universal , can be put separately and you'll be able to attach it to every menucheckitem you create. The only thing is that if you add new menucheckitem filter you should name the menucheckitem id with the name of the columnDataIndex-Menu and add this columnDataIndex in menuFilters and thats all.
checkchange: function (checkbox, checked, eOpts) {
var menuFilters = ['name', 'phone'];
var getChecked = function (m) {
var checkedItems = [];
m.items.items.forEach(function (c) {
if (c.checked) {
checkedItems.push(c.text);
}
});
return checkedItems;
};
//
var menus = new Map();
menuFilters.forEach(function (e) {
menus.set(e, Ext.getCmp(e + '-Menu'));
});
//
var fieldValues = [];
menuFilters.forEach(function (e) {
fieldValues.push([e, getChecked(menus.get(e))]);
});
//
var store = checkbox.up('grid').store;
store.clearFilter();
//
if (fieldValues.length > 0) {
store.filterBy(function (record) {
var fV = this.fieldValues;
for (var i = 0; i < fV.length; i++) {
if (fV[i][1].length > 0) {
if (fV[i][1].indexOf(record.get(fV[i][0])) === -1) {
return false;
}
}
}
return true;
}, {
fieldValues: fieldValues
});
}
}
I am trying to color format a row in a spreadsheet where I run a loop to check if any of the values is equal to 0 and if it is equal to 0 to color it red and if not color it red.
I know I can do it with conditional format but I need this to activate after I press a button included in the sheet, so I need a script added to the button.
I have managed to write this script but it seems it color only the last cell from the range.
Can you please tell me what am I doing wrong since I am new to coding.
function FormatColor() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Acontobetaling');
var range = sheet.getRange('D34:AA34');
var values = [];
var cell = [];
for (var i = 1; i <= 24; i=i+1)
cell = range.getCell(1, i)
values = cell.getValue();
if (values = '0') {
cell.setBackground('red');
} else {
cell.setBackground('green');
}
}
I made it work, if someone is having the same problem you can use this
Anyway if you can provide me with better or fast way to do it you are welcome to show me how :)
function CopyData() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Acontobetaling');
var rangeColor = sheet.getRange('D34:AA34');
var values = [];
var cell = [];
var colors = [];
for (var i = 1; i <= 24; i=i+1) {
cell = rangeColor.getCell(1, i);
values = cell.getValue();
if (values == '0') {
colors = cell.setBackground('red');
} else {
colors = cell.setBackground('green');
}
}
Hi this is my hotel project. But I'm having a problem with a filter.
I want to filter the data in the amenities column.
This is: my fiddle
It works if you select a single checkbox but it does not work if you select multiple checkboxes.
I suspect the problem arises from indexof instead of what I can use. What method should I follow?
How to change this line: indexOf(x);
This is my bad code:
//PROBLEM FILTER HERE
$scope.am_en = function()
{
//get input value
x = $(".hosting_amenities input:checkbox:checked").map(function(){return $(this).val();}).get();
//filter
$scope.ot_Filter = function (location) {
return location.amenities.indexOf(x) !== -1;
};
}
The problem is indeed caused by the function $scope.am_en, in the declaration of the inner function $scope.ot_Filter
When you select multiple checkboxes, your x variable is an array of objects, so you should do a loop and can create a variable to check whether the element should be shown or not. You can do it as follows:
$scope.ot_Filter = function (location) {
var shouldBeShown = false;
for (var i = 0; i < x.length; i++) {
if (location.amenities.indexOf(x[i]) !== -1) {
shouldBeShown = true;
break;
}
}
return shouldBeShown;
};
I modified your jsfiddle, so that you can see this solution working properly.
Is there a way to limit the number of selected items in ng-grid?
I did not find a setting to do that, so I am trying to prevent it using a watchCollection in gridOptions.selectedItems.
When the length of selectItems is greater than 5, I try to deselect the last selection but is not working as expected because the item row index seems to be different as rendered:
This is the watcher code:
$scope.$watchCollection('gridOptions.selectedItems', function (newVal, oldVal) {
if ($scope.gridOptions.selectedItems.length > 5) {
for (var i = 0; i < $scope.importableFilesData.length; i++) {
if ($scope.importableFilesData[i] === newVal[0]) {
$scope.gridOptions.selectRow(i, false);
}
}
}
Check your condition in this way. So, you don't have to search last selected row and you can deselect it directly. i've tested it and is working in this way.
$scope.yourGridApi.selection.on.rowSelectionChanged($scope,function(row){
if($scope.yourGrid.gridOptions.selectedItems.length>=5){
row.isSelected = false;
}
});
I have found a solution using beforeSelectionChange property. This property let you set callback that is triggered every time a row is selected. If your return false, the selection will be canceled.
$scope.gridOptions = {
// your grid options ...
beforeSelectionChange: function (row) {
if ($scope.gridOptions.selectedItems.length > 5) {
return false;
}
return true;
}
}