Sort checked rows to bottom - google-apps-script

I am using google sheets to sort school assignments. I am currently using the below coding to auto-sort the sheet by deadline. I have a checkbox in column F that will mark a row as "0" when it is done (when the box is checked). And "unfinished" when the box is not checked. I would like to include a piece in my auto-sort script that automatically puts rows marked "0" (box is checked) below all rows that are marked unfinished (box is not checked). The code below is all working but I am not sure how to go about adding this feature as I am quite new to coding. Any ideas?
(I've posted this before but it was taken down because it had too little detail, sorry if you saw the first one. This one is better)
function autoSort(e){
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName("School Assignments")
const range = ws.getRange(2,1,ws.getLastRow()-1,6)
range.sort({column: 5, ascending: true })
}
function onEdit(e){
const row = e.range.getRow()
const column = e.range.getColumn()
if(!(column === 5 && row >= 2)) return
autoSort(e)
}

Sorts checked items in column F to bottom
function onEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == "School Assignments" && e.range.columnStart == 6 && e.range.rowStart > 1 && e.value == "TRUE") {
sh.getRange(2,1,sh.getLastRow() -1,sh.getLastColumn()).sort({column:6,ascending:true});
}
}
This assume that the checked value is "TRUE" and the unchecked value is "FALSE"

Related

Check/Uncheck Boxes From a Dynamic Range Based On Condition

I have a to-do list with checkboxes for my employees in a spreadsheet with a dynamic number of rows that cannot exceed row 20. Because starting from row 20 another employee's to-do list is available.
I have a checkbox next to the name of the employee. Once I check/uncheck that checkbox, I want all below checkboxes to check or uncheck no matter how many rows are added or removed as long as it does not pass row number 20.
I have therefore named the range on row 20 so that even if it moves, apps script can locate it through named range. I have removed the named range and called it instead ('A20') in the script below to avoid confusion.
I thought a forloop could work but I must be doing something wrong because it is executing successfully but showing no results.
function Todolist() {
var spreadsheet = SpreadsheetApp.getActive();
var lianrange = spreadsheet.getRange('A20');
for (var i = 1 ; i<lianrange.length;i++){
if (spreadsheet.getCurrentCell().getValue() === 'check'){
spreadsheet.getRange[i].setValue('Y');
}
if (spreadsheet.getCurrentCell().getValue() === 'uncheck'){
spreadsheet.getRange[i].setValue('N');
}
}
};
Your help is much appreciated.
Check or uncheckall
function onEdit(e) {
//e.source.toast('Entry');
const sh = e.range.getSheet();
const rg = sh.getRange('stopRow');//stopRow is name of namedRange
const sr = rg.getRow();
//need to update name of sheet
if (sh.getName() == "Sheet0" && e.range.columnStart == 2 && e.range.rowStart < sr) {
//e.source.toast('Gate1');
const vs = sh.getRange(e.range.rowStart, e.range.columnStart, sr - e.range.rowStart + 1).getValues().flat();
const cv = sh.getRange(e.range.rowStart, e.range.columnStart).getValue();
let o = vs.map((e, i) => [cv])
sh.getRange(e.range.rowStart, e.range.columnStart, o.length).setValues(o);
}
}
demo:

How to delete a row as indicated in a cell in google app script?

What I want to do:
I write a row number in a cell, let's say F1, and the value is 9.
I want to add a button that calls a script that will delete the line as I wrote it into the cell, so in this example, line 9.
So I start with:
var s = SpreadsheetApp.getActive()
var sheet = s.getSheetByName('Books');
var row = sheet.getRange('F1');
However this:
sheet.deleteRow(row.getValue());
will give an out of bounds error. getDisplayValue does not work as well and putting it into an parseint doesn't work either.
The 9 hardcoded
sheet.deleteRow(9);
works of course.
I also debbuged and did a
sheet.getRange('G1').setValue(row.getValue());
to verify that the 9 is indeed there, which it is, the 9 will be copied to cell G1.
sheet.getRange('A'+row.getValue()+':J'+row.getValue()).clearContent();
meanwhile will have it treat it as a A:J and delete every line not just one. Doing toString after getValue did also not change anything.
What am I missing here to turn the cell value into a range?
Sheet.deleteRow(value of F1):
function onEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == "Your sheet name" && e.range.columnStart == 6 && e.range.rowStart == 1 && e.value) {
sh.deleteRow(e.value)
}
}
Cannot call this function from script editor must save in project and edit F1 of Your Sheet. You also need to edit line 3 and add the name of the appropriate sheet.
Using a checkbox for a button:
function onEdit(e) {
e.source.toast("Entry")
const sh = e.range.getSheet();
if(sh.getName() == "Sheet0" && e.range.columnStart == 1 && e.range.rowStart == 1 && e.value == "TRUE") {
e.source.toast("Gate1")
e.range.setValue("FALSE")
sh.deleteRow(sh.getRange("F1").getValue());
}
}
Demo:

Updating dropdown list picked values when the source data is changed at a later date

In the screenshot below, column C contains dropdown lists populated with col A source values. Let's consider the following scenario
A2 initial value is "choice B"
In C1, "choice B" is selected
A2 value is edited to "choice B - just modified"
Unfortunately, C1 value won't update and triggers a warning. How do I go about it so that dropdown list values get updated if their respective source cell gets modified?
Going further, I intend to be using it with IMPORTRANGE, to be able to use the same source values across multiple Google Sheets workbooks. So that needs to be accounted for.
Is that something that is at all possible, be it natively or using 3rd party plugins?
It could be done with something like this but I think it could get messed up pretty easily:
function ddd() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const rg = sh.getRange("A2:A");
let dv = SpreadsheetApp.newDataValidation().requireValueInRange(rg).setAllowInvalid(true).build();
sh.getRange("B2:B").setDataValidation(dv);
}
function onEdit(e) {
e.source.toast("Entry");
const sh = e.range.getSheet();
if(sh.getName() == "Sheet0" && e.range.columnStart == 1 && e.range.rowStart > 1 ) {
e.source.toast("Gate1");
sh.getRange("B2:B" + sh.getLastRow()).getValues().flat().forEach((el,i) => {if(el == e.oldValue) {
sh.getRange(i + 2, 2).setValue(e.value);
}})
}
}

Hide columns based on checkbox value

I would like to implement a code to my production plan. Is there a way to hide column based on the checkbox true value? Lets say I added the checkboxes to the row 5, and I want to hide each column starting from M column separately upon ticking the checkbox. I implemented the code to hide the rows, but for columns it's getting tricky since I'm not experienced in google script.
Would it be perhaps also possible to add custom filter to show all hidden columns at once, lets say if I wanna make changes in one of them, and then hide all of them at once?
Hide columns starting with M
function onEdit(e) {
e.source.toast("Entry")
const sh = e.range.getSheet();
if (sh.getName() == "Enter Your Sheet Name" && e.range.columnStart > 12 && e.range.rowStart == 5 && e.value == "TRUE") {
e.source.toast("Flag1");
sh.hideColumns(e.range.columnStart);
e.range.setValue("FALSE");
}
}
Yes, these is! If you use an onEdit function, you can use e.range.isChecked() to see if a checkbox was checked. After that, you'd just need to run activeSheet.hideColumns(editedColumn, 1) to hide the column.
This code should do the trick:
function onEdit(e) {
var activeSheet = SpreadsheetApp.getActiveSheet();
var editedRange = e.range;
var editedRow = editedRange.getRow();
var editedColumn = editedRange.getColumn();
//If the checkbox isn't checked, return
if (!editedRange.isChecked()) return;
//If the edited row isn't in row 5, return
if (editedRow != 5) return;
//If the edited column is before M, return
if (editedColumn < 12) return;
//Hide the edited column
activeSheet.hideColumns(editedColumn, 1);
}

how do I move a row from one tab in a google sheet to another in the same sheet

I am super new (as in this is my first stab at anything code related) to this...
I've read a bunch of similar questions and I have watched several videos related to the specific thing I am trying to do. I thought it would be simple, but it keeps failing and I cannot figure out why!
I am trying to set it up so that when a checkbox in the row is checked (which currently automatically happens when a value is 0 in another cell), that entire row gets moved to bottom of the list in a different sheet tab within the same spreadsheet and deleted from the first sheet tab.
I know about filtering and every other simpler option, but for what we are doing, it won't work right. It needs to move.
The error I keep getting says: Error Message
TypeError: Cannot read property 'columnStart' of undefined
at onEdit(Move Row When Paid:4:51)
Here is what I have (pic also attached): Code
function onEdit(e) {
const src = e.source.getActiveSheet();
const r = e.range;
if (src.getName() != "Open Invoices" || r.range.columnStart != 11 || r.range.rowStart == 1) return;
const dest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Closed Invoices");
src.getRange(r.rowStart,1,1,12).moveTo(dest.getRange(dest.getLastRow()+1,1,1,12));
src.deleteRow(r.rowStart);
}
I can link the spreadsheet if needed! All help is appreciated for this noob :)
Try it this way:
function onEdit(e) {
//e.source.toast("Entry")
const sh = e.range.getSheet();
if (sh.getName() == "Open Invoices" && e.range.columnStart == 11 && e.range.rowStart > 4 && e.value == "TRUE") {
//e.source.toast('Flag1');
const dest = e.source.getSheetByName("Closed Invoices");
sh.getRange(e.range.rowStart, 1, 1, 12).moveTo(dest.getRange(dest.getLastRow() + 1, 1));
sh.deleteRow(e.range.rowStart);
}
}
Here's was my sheet looks like:
I don't have your headers so it does not work below line 5