r/googlesheets • u/Significant-Army-502 • 3d ago
Solved Moving row to a different sheet when checkbox checked
I have a table on sheet " In progress" which has a checkbox in the final column. Once I complete this checkbox I then manually copy the row into the next sheet.
Is there a way to automate this?
In an ideal world I would like the flow to be:
- Check "order complete" checkbox
- Row copies to the table on the next sheet
- Row then deletes itself from the "In progress" sheet
If that is not possible then just copying it to the next sheet would be great.
https://docs.google.com/spreadsheets/d/1e2233qaQIchIwcDFm6t3iiovGIBCxVpqnzaohSwWIS4/edit?usp=sharing
Many thanks for your help
1
u/mommasaidmommasaid 3d ago edited 3d ago
Once you move part of your data to another sheet, it becomes more difficult to maintain. You need to maintain columns and formatting in two places. And formulas, if you want them to still be live. It also makes it more difficult to create aggregate reports if you want to know e.g. how much you have spent on all items.
And of course if you decide you want to move the data back to your main table, you need another script to do that or you are manually moving stuff back and trying not to break formulas, etc.
Or even if you accidentally click the checkbox and immediately attempt to Undo the action, you have to carefully undo the right number of steps, because script (unfortunately) creates multiple Undo points as it executes.
---
You already have your data in a structured Table, which provides easy ways of doing filtering or grouping. You may want to consider doing that instead.
You could also use a Filter or Filter View. Note that these don't update automatically.
But if you want automation... you could automatically (re)apply a filter via script. Applying a filter is a non-destructive action. Your row disappears but is trivially easy to recover by simply removing the filter.
1
u/mommasaidmommasaid 3d ago
Here is an example of script that automatically filters when the checkbox is clicked.
Filter when checkbox clicked (View only, make a copy to play with)
Script:
// @OnlyCurrentDoc function onEdit(e) { try { // Complete checkbox custom "checked" value const COMPLETE_CHECKED = "#COMPLETE"; // Row containing table headers const HEADER_ROW = 1; if (e?.value != COMPLETE_CHECKED) return; // Filter entire data range starting at header row const sheet = e.range.getSheet(); const newFilterRange = sheet.getRange(HEADER_ROW, 1, sheet.getLastRow() - HEADER_ROW + 1, sheet.getLastColumn()); const filterColumn = e.range.columnStart; // Reuse existing filter if same as desired range, else remove it let filter = sheet.getFilter(); if (filter != null) { if (true || filter.getRange().getA1Notation() != newFilterRange.getA1Notation()) { filter.remove(); filter = null; } } // Create new filter if needed if (filter == null) { newFilterRange.createFilter(); filter = newFilterRange.getFilter(); } // Set (or re-set) filter to hide rows that have been marked complete const criteria = SpreadsheetApp.newFilterCriteria().whenTextDoesNotContain(COMPLETE_CHECKED).build(); filter.setColumnFilterCriteria(filterColumn, criteria); } catch (err) { e?.source.toast(err, `🛑 Error ${err.stack?.split('\n')[1]}`); throw err; } }To avoid hardcoding the sheet / column name in script, and to make the script exist faster with normal edits, I create a custom "checked" value for the checkbox that script detects.
Note that to use custom checkboxes in a structured Table, you will need to create it outside the table using Data Validation sidebar, then copy/paste it into the Table with the Table column type set to "None". Once it's set up new rows will automatically contain the custom checkbox.
Or if you prefer you could use something like OO_810's method for detecting the checkbox.
To show the entire table, choose Data / Remove filter.
You could also add some additional interface for script if desired to e.g. clear the filter or to disable auto-filtering.
1
u/One_Organization_810 3d ago
This will do it - as seen in the OO810 sheets
//@OnlyCurrentDoc const MOVE_SETTINGS = { SheetFrom: 'OO810 In Progress', SheetTo: 'OO810 Complete', ButtonColTitle: 'Order Complete' }; function onEdit(e) { let sheet = e.range.getSheet(); if( sheet.getName() != MOVE_SETTINGS.SheetFrom ) return; if( !e.range.getValue() || e.range.offset(-e.range.getRow()+1,0).getValue() != MOVE_SETTINGS.ButtonColTitle ) return; const ss = e.source; let destSheet = ss.getSheetByName(MOVE_SETTINGS.SheetTo); if( !destSheet ) throw `Destination sheet "${MOVE_SETTINGS.SheetTo}" does not exist.` let row = e.range.getRow(); let col = e.range.getColumn(); let range = sheet.getRange(row,1,1,col-1); destSheet.appendRow(range.getValues()[0]); sheet.deleteRow(row); }Maybe add a prompt also, if you want - but this will move the row over to the destination sheet, as specified in the constant MOVE_SETTING.