Appending Array of data from one sheet to another - google-apps-script

I have a google sheet with a column full of checkboxes. My goal is to have a row of the selected adjacent columns of data (namedInsured, lineCoverage, etc.) append to a separate sheet when a checkbox is selected and True. This is what I currently have, and it does absolutely nothing.
function onEdit(e) {
const ss = e.range.getSheet();
var active_range = ss.getActiveRange();
var namedInsured = ss.getRange(active_range.getRowIndex(), 4).getValue();
var lineCoverage = ss.getRange(active_range.getRowIndex(), 5).getValue();
var effDate = ss.getRange(active_range.getRowIndex(), 6).getValue();
var assignedTo = ss.getRange(active_range.getRowIndex(), 15).getValue();
var data = [namedInsured, lineCoverage, effDate, assignedTo];
const destinationSheet = ss.getSheetByName("Sheet4");
if (ss.getName() != "Sheet4" && e.range.columnStart == 10 && e.value == "TRUE")
{
e.source.toast("Quote In Process Entered")
destinationSheet.appendRow(data);
}
}
[This is an example of the desired output]
<< If the first and fourth checkboxes were selected one after the other, this is how they should appear on the separate sheet

This works for me
function onEdit(e) {
e.source.toast('Entry')
const sh = e.range.getSheet();
if (sh.getName() == "Sheet0" && e.range.columnStart == 10 && e.value == "TRUE") {
e.source.toast('Flag1');
const [a,b,c] = sh.getRange(e.range.rowStart, 4,1,3).getValues()[0];
var d = sh.getRange(e.range.rowStart, 15).getValue();
var data = [a, b, c, d];
const dsh = e.source.getSheetByName("Sheet1");//modified from original
dsh.appendRow(data);
}
}
Demo:

Related

How do I define an IF statement for a cell contains a specific value in Apps Script?

I have a script that adds a timestamp to a cell when another cell in the row is initially filled in. What I would like to do is only timestamp when a cell contains the word "Completed". It doesn't seem to be working though.
var SHEET_NAME = 'Sheet 1';
var DATETIME_HEADER = 'datetime';
function getDatetimeCol(){
var headers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME).getDataRange().getValues().shift();
var colindex = headers.indexOf(DATETIME_HEADER);
return colindex+1;
}
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSheet();
var cell = ss.getActiveCell();
var datecell = ss.getRange(cell.getRowIndex(), getDatetimeCol());
//Here's the line where I added an "if the active cell is labelled completed then add a timestamp to the datetime column"
if (ss.getName() == SHEET_NAME && cell.getColumn() == 8 && !cell.isBlank() && datecell.isBlank() && cell.getValues == "Completed") {
datecell.setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm");
}
}
;
Try it this way:
function onEdit(e) {
const sh = e.range.getSheet();
const col = sh.getRange(1,1,1,sh.getLastColumn()).getValues().flat().reduce((a,h,i)=> (a[h]=i+1,a),{});
const dateCell = sh.getRange(e.range.rowStart,col['datetime']);
if (sh.getName() == "SHEET_NAME" && e.range.columnStart == 8 && datecell.isBlank() && e.value == "Completed") {
datecell.setValue(new Date()).setNumberFormat("yyyy-MM-dd hh:mm");
}
}

Google Sheets, pop up message based on cell value TRUE/FALSE

I am trying to get Google Sheets show a popup message whenever a cell changes from FALSE to TRUE. I have found a few ways of doing it using onEdit functions. The problem here is that the Cell in question does not really get edited, but rather changes value due to another set of cells meeting certain criteria. That means onEdit functions won't run when the value changes.
I tried this script, but it does nothing:
//popup message
function alertMessageYesNoButton() {
var result = SpreadsheetApp.getUi().alert("Are you sure you want to send an alert about?", SpreadsheetApp.getUi().ButtonSet.YES_NO);
SpreadsheetApp.getActive().toast(result);
}
function sendMessageYesNo(e){
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var cellValue = sheet.getRange(4, 17).getValue();
if (cellValue == 'TRUE'){
alertMessageYesNoButton();
}else{}
}
If someone could come up with something that works, I would really appreciate it.
From your following reply,
cell D17 changes from FALSE to TRUE when three other checkboxes are checked using this formula: {"";SUMPRODUCT(B16:B18)=COUNTA(B16:B18)}.
In this case, how about checking the checkboxes of "B16", "B17", "B18"? When this is reflected in your showing script, how about the following modification? I thought that when those checkboxes are manually checked, onEdit trigger can be used.
In this modification, when all checkboxes of "B16:B18" of "Sheet1" are checked, your script of alertMessageYesNoButton() is run. So, when you test this, please check all checkboxes of "B16:B18" of "Sheet1". By this, the script is run.
Pattern 1:
function onEdit(e) {
const sheetName = "Sheet1"; // This is from your script.
const checkBoxRange = "B16:B18"; // This is from your reply.
const { range } = e;
const sheet = range.getSheet();
const r = sheet.getRange(checkBoxRange);
const rowStart = r.getRow();
const rowEnd = rowStart + r.getNumRows() - 1;
const colStart = r.getColumn();
const condition1 = sheet.getSheetName() == sheetName;
const condition2 = range.rowStart >= rowStart && range.rowEnd <= rowEnd && range.columnStart == colStart;
const condition3 = r.getValues().every(([b]) => b === true);
if (!condition1 || !condition2 || !condition3) return;
alertMessageYesNoButton(); // This is your script.
}
Pattern 2:
function onEdit(e) {
const sheetName = "Sheet1"; // This is from your script.
const checkBoxRange = "B16:B18"; // This is from your reply.
const { range } = e;
const sheet = range.getSheet();
const r = sheet.getRange(checkBoxRange);
const rowStart = r.getRow();
const rowEnd = rowStart + r.getNumRows() - 1;
const colStart = r.getColumn();
const condition1 = sheet.getSheetName() == sheetName;
const condition2 = range.rowStart >= rowStart && range.rowEnd <= rowEnd && range.columnStart == colStart;
const condition3 = r.getValues().every(([b]) => b === true);
if (!condition1 || !condition2 || !condition3) return;
// This is your script.
var cellValue = sheet.getRange(4, 17).getValue();
if (cellValue == 'TRUE') {
alertMessageYesNoButton();
}
}
Reference:
Simple Triggers
Added:
From your following reply,
this works very well for the example I laid out, but I tried using several multiple instances of the same script within the same sheet and it always works only in one of them. So let´s say I have for instances of the same situation (B16:B18), (B13:B15), (D13:D15) and (D16:D18). Only when I check the boxes corresponding to the last function (from top to bottom), the message pops up.
From your question and your reply, I proposed an answer as the checkboxes of "B16:B18". But from your reply, when your checkboxes are "B16:B18", "B13:B15", "D13:D15", "D16:D18", how about the following sample script?
Sample script:
function onEdit(e) {
const sheetName = "Sheet1"; // This is from your script.
const checkBoxRanges = ["B16:B18", "B13:B15", "D13:D15", "D16:D18"]; // This is from your reply.
const { range } = e;
const sheet = range.getSheet();
const actSheetName = sheet.getSheetName();
const res = checkBoxRanges.find(checkBoxRange => {
const r = sheet.getRange(checkBoxRange);
const rowStart = r.getRow();
const rowEnd = rowStart + r.getNumRows() - 1;
const colStart = r.getColumn();
const condition1 = actSheetName == sheetName;
const condition2 = range.rowStart >= rowStart && range.rowEnd <= rowEnd && range.columnStart == colStart;
const condition3 = r.getValues().every(([b]) => b === true);
return condition1 && condition2 && condition3;
});
if (!res) return;
Browser.msgBox(`Checked checkboxes of ${res}`); // Here, you can see the checkbox group that was checked.
alertMessageYesNoButton(); // This is your script.
}
In this case, by giving const checkBoxRanges = ["B16:B18", "B13:B15", "D13:D15", "D16:D18"], the script detects the checked checkboxe group, and show the range as a sample.

Change script to work only on specific tab [duplicate]

This question already has an answer here:
Google App Script onedit restrict to sheet
(1 answer)
Closed 8 months ago.
I have this script:
function onEdit2(e) {
const sheetName = "Charts"; // Please set your sheet name.
const dropDownCell = "B4:B6"; // Please set the range of dropdown list.
var spreadsheet = SpreadsheetApp.getActive();
var cell = spreadsheet.getActiveCell();
var cellR = cell.getRow();
var cellC = cell.getColumn();
var cellValue = cell.getValue();
if (cellR == 4 && cellC == 2) {
spreadsheet.getRange('B6').clearContent();
spreadsheet.getRange('B6').setValue('⚠️ SELECT');
}
}
I would like to make it work only on Charts tab without affecting any other tab. Right now script works in all tabs.
Actually the code doesn't make much sense to me. Here's what it boils down to:
function onEdit2(e) {
const sh = e.range.getSheet();
if(sh.getName() == "Charts" && e.range.columnStart == 2 && e.range.rowStart == 4) {
sh.getRange('B6').setValue('⚠️ SELECT');
}
}
function onEdit2(e) {
const sheetName = "Charts"; // Please set your sheet name.
if( e.range.getSheet().getName() === sheetName ) {
const dropDownCell = "B4:B6"; // Please set the range of dropdown list.
var spreadsheet = SpreadsheetApp.getActive();
var cell = spreadsheet.getActiveCell();
var cellR = cell.getRow();
var cellC = cell.getColumn();
var cellValue = cell.getValue();
if (cellR == 4 && cellC == 2) {
spreadsheet.getRange('B6').clearContent();
spreadsheet.getRange('B6').setValue('⚠️ SELECT');
}
}
}

Toggle rows hide/show between top down checkbox

trying to make a semi/manual tree structure. if check box = true. in a topdown manner. it will look for another check box in the downside direction and unhide rows. i.e. show A2 to A9. if box = false then, Hide: A11 till A19. if there is no check box until the last row it will hide/show all the rows. i.e. B23/B2000. it's a top-down approach so the only action only is limited to a particular column and between the boxes cells are blanks.
function onEdit(e){
const sheet = SpreadsheetApp.getActiveSheet();
const range = e.range;
const editedValue = e.value;
if (range.getA1Notation() === "A1" && editedValue === "TRUE") {
sheet.unhideRow(sheet.getRange("A:A9"));
} else if (range.getA1Notation() === "A1" && editedValue === "TRUE") {
const firstRow = 1;
const lastRow = sheet.getLastRow();
if (pValue === true) {
sheet.hideRows(i + firstRow);
}
});
} else if (e.range.columnStart === 9 && editedValue === "TRUE") {
sheet.hideRows(range.rowStart);
}
}
Solution:
You can use this script to check the rows below the edited checkbox and hide/show rows accordingly:
function onEdit(e){
const sheet = SpreadsheetApp.getActiveSheet();
const range = e.range;
const editedValue = e.value;
const row = range.getRow();
const col = range.getColumn();
const lastRow = sheet.getMaxRows();
var data = sheet.getRange(row+1,col,lastRow-row+1,1).getValues();
for (var i = 0; i < data.length; i++) {
if (data[i][0] === true || data[i][0] === false) {
++i;
break;
}
}
if (i > 1) {
if (editedValue === "FALSE")
sheet.hideRows(row+1,i-1);
else if (editedValue === "TRUE")
sheet.showRows(row+1,i-1);
}
}
Sample Output:

Google Sheet - copy row if checkbox is active

CONTEXT
In a google spreadsheet, copy entire row to another tab when checkbox is active
The below code works and was found online in Code source
function onEdit(event) {
// source sheet named Source A
// target sheet of move to named Development
// getColumn with check-boxes is currently set to column 21
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Source A" && r.getColumn() == 21 &&
r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Development A");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target, {contentsOnly:true});
}
}
PROBLEM
I would like to have this code working in 2 tabs (sheets): Source A and Source B to 2 different destination sheets: Destination A and Destination B
Limitation of one onEdit(event)
WHAT I'VE TRIED
Adding "else if" to the code but it only worked for Source A:
else if if(s.getName() == "Source B" && r.getColumn() == 21 && etc
Instead of using onEdit(event), named each function and then tried to use triggers (onEdit) but nothing worked
Can anyone give me a hand?
Thank you in advance.
function onEdit(e) {
const sh = e.range.getSheet();
const shts = ['Source A','Source B'];
if (~shts.indexOf(sh.getName()) && e.range.columnStart == 21 && e.value == "TRUE") {
//e.range.setValue("FALSE");//reset the checkbox
let tsh = e.source.getSheetByName("Development");
var tgt = tsh.getRange(tsh.getLastRow() + 1, 1);
sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).copyTo(tgt, { contentsOnly: true });
}
}
function onEdit(e) {
const sh = e.range.getSheet();
const shts = ['Source A','Source B'];
const tgts = ['Dest A','Dest B'];
const idx = shts.indexOf(sh.getName());
if (~idx && e.range.columnStart == 21 && e.value == "TRUE") {
//e.range.setValue("FALSE");//reset the checkbox
let tsh = e.source.getSheetByName(tgts[idx]);
var tgt = tsh.getRange(tsh.getLastRow() + 1, 1);
sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).copyTo(tgt, { contentsOnly: true });
}
}