I have something like this on a sheet
NAME | POINTS | ELIGIBLE | FINAL |
---|---|---|---|
Alice | 700 | YES | |
Bob | 500 | NO | |
Carol | 300 | NO | |
Dave | 200 | YES | |
Eve | 100 | YES |
I need to achieve the following in column D:
- If it's a "NO", the final points will be the same as the original (like a placeholder) i.e. =B{row}
- If it's a "YES", the final points will follow the same sequence as column B, except skipping all the "NO" in the list
so in this example, the output should be like this
NAME | POINTS | ELIGIBLE | FINAL |
---|---|---|---|
Alice | 700 | YES | 700 |
Bob | 500 | NO | 500 |
Carol | 300 | NO | 300 |
Dave | 200 | YES | 500 |
Eve | 100 | YES | 300 |
When doing this manually, I just copy all values of B2:B, paste to D2, then apply filter "YES" to column C and paste to D2 once again. (this will paste some ugly trailing values to empty rows, but doesn't matter)
The current script
However, when doing this with script, I have to use a for loop to check column C of every row, then assign a =B{n} formula to column D, where n increases only when the current row is a YES
j = 2; //starting from the second row
for (var i = 0; i < lastRow - 1; i++) {
if (sheet.getRange(i+2,3).getValue() == "YES") {
sheet.getRange(i+2,4).setFormula(`B${j}`);
j++;
}
else {
sheet.getRange(i+2,4).setFormula(`B${j}`);
}
}
but this also means the processing time will scale with number of rows (10,000 - 20,000ms per ~100 row), all other actions I am doing only takes ~1000ms in total, which is why I'm looking for an option that does not need iterating to save a lot of time.
I don't mind not using formula in column D as long as the value is correct.
I have tried these
get B2:B as range, set filter (C1:C text equals to "YES"), then copyTo() D2:
seq = lbSheet.getRange(`B2:B${lastRow}`);
sheet.getRange("C1:C").createFilter();
filter = lbSheet.getFilter();
criteria = SpreadsheetApp.newFilterCriteria().whenTextEqualTo("YES").build();
filter.setColumnFilterCriteria(3,criteria);
seq.copyTo(sheet.getRange(`D2`),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
this does not paste to filtered cells only, but all cells
getValues(B2:B), set filter (C1:C text equals to "YES"), getRange(D2:D).setValues(B2:B):
seq = lbSheet.getRange(`B2:B${lastRow}`).getValues();
sheet.getRange("C1:C").createFilter();
filter = lbSheet.getFilter();
criteria = SpreadsheetApp.newFilterCriteria().whenTextEqualTo("YES").build();
filter.setColumnFilterCriteria(3,criteria);
sheet.getRange(`D2:D${lastRow}`).setValues(seq);
this gives range mismatch error