How to use Google app script to automatically border line below When Value Changes - google-sheets

I want to add a border line below the row whenever column C value changes.
I haven’t touched macro for a long time, this is a script I put together but it doesn’t work as expected. Anyone know where the problem is? Thanks!
function underline() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
for (var i = 1; i < 10; i++) {
if (sheet.getRange(spreadsheet.getCurrentCell().getRow() + i, 3) != sheet.getRange(spreadsheet.getCurrentCell().getRow() + i+1, 3)) {
sheet.getRange(spreadsheet.getCurrentCell().getRow() + i, 1, 1, sheet.getMaxColumns()).activate();
spreadsheet.getActiveRangeList().setBorder(null, null, true, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID);
}
}
};

Your original code is a bit convoluted, doing a lot with a single if statement. I took the liberty to separate the complicated bit into a distinct function, findOriginal(cell). The following code adds one line:
function findOriginal(cell) { //offsets given cell until finds new content
while (cell.getValue() == cell.offset(1,0).getValue()) cell = cell.offset(1,0);
return cell;
}
function underline() {
var spreadsheet = SpreadsheetApp.getActive(),
cell = spreadsheet.getSelection().getCurrentCell();
cell = findOriginal(cell);
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(cell.getRow(), 1, 1, sheet.getLastColumn()) // setting the range to border
.setBorder(null, null, true, null, null, null,
'#000000', SpreadsheetApp.BorderStyle.SOLID); // you wrote this line
};

Related

How can I color a row using jsPDF AutoTable based on a single cell value?

I'm trying to create a PDF based off of an interactive/dynamic table using jsPDF + AutoTable. The last cell in a row will either say "Yes" or "No" - if the cell says "Yes" the entire row should be highlighted.
The closest I've come is getting the cell to highlight, but I need the entire row to highlight. I seem to be having trouble tying the cell to the row index.
This is my code so far:
willDrawCell: function (data) {
if (data.cell.text == "Yes") {
doc.setFillColor(67, 160, 71);
}
}
Thanks for any help.
I was able to resolve this!
Before my doc.autoTable() call, I calculate the index where the "Yes" is, and store those values in an array. I then loop over each row index and setFillColor as appropriate. Here is what my code looks like now:
willDrawCell: function (data) {
if (data.cell.text == "Yes") {
doc.setFillColor(67, 160, 71);
}
for (let i = 0; i < ready_rows.length; i++) {
if (data.row.index === ready_rows[i]) {
doc.setFillColor(239, 154, 154);
}
}
}
here currentRow is row which given in auto table
var res1 = doc.autoTableHtmlToJson(document.getElementById(m));
var idmm=document.getElementById(n);
var clength=res1.columns.length;
var crow=res1.rows.length;
doc.autoTable(res1.columns, res1.data, {margin: {top: vy+25},pageBreak: 'auto',styles: {cellPadding: 1.5,fontSize:fsize , },fontStyle: 'bold',drawRow: function (row, data) {
currentRow1 = row;
currentRow1.height =30;
if((currentRow1.cells[0].text[0].includes('Total')) || (currentRow1.cells[0].text[0].includes('Avg'))||(currentRow1.cells[0].text[0].includes('count'))||(currentRow1.cells[0].text[0].includes('Min'))||(currentRow1.cells[0].text[0].includes('Max')))
{
1
for(var i=0;i<res1.columns.length;i++)
{
currentRow1.cells[i].styles.fontStyle = "bold";
currentRow1.cells[i].styles.font = "sans-serif" ;
currentRow1.cells[i].styles.fillColor = [243,205,204];
currentRow1.cells[1].styles.columnWidth="wrap";
currentRow1.cells[1].styles.FontSize=30;
}
}
},columnStyles: {0: {columnWidth: columnwidthrgroup},},});
```

How to add a row bellow the last item on a list

I have a list of tasks, and I want to create a macro to add a row bellow the last item to that list. But all the macros that i've tried didnt work. Can someone help me with this?
here it is:
function AddRow() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(spreadsheet.getCurrentCell().getRow() + 22, 1, 1, sheet.getMaxColumns()).activate();
spreadsheet.getActiveSheet().insertRowsAfter(spreadsheet.getActiveRange().getLastRow(), 1);
spreadsheet.getActiveRange().offset(spreadsheet.getActiveRange().getNumRows(), 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getCurrentCell().offset(0, 8).activate();
spreadsheet.getCurrentCell().setFormulaR1C1('=TODAY()');
spreadsheet.getCurrentCell().offset(0, -2).activate();
spreadsheet.getActiveRangeList().setBorder(null, null, null, true, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID);
spreadsheet.getCurrentCell().offset(5, 0).activate();
};

Radio button in Google Sheets formula

So I've created sort of radio button chooser table with check boxes so I can pick which line I want and that brings the value from this line out to the result cell...
this is the basic principle:
this way which ever checkbox I click, the value of that cell becomes 1 (TRUE) rather than 0 (FALSE), and using SUMPRODUCT formula, every line is multiplied by the boolean checkbox so if the checkbox is not checked, the production is zeroed, and if the checkbox is checked, the value remains.
In this example on B8 I get:
B8 = A2*B2 + A3*B3 + A4*B4 = 0*3 + 1*8 + 0*12 = 8
That works well as long as the values are numbers..
Now I'm trying to do the same but with string values..
something like this:
Any idea?
Solution:
Use IF to get corresponding Col B
JOIN the resulting array
Sample:
=ARRAYFORMULA(TEXTJOIN(",",1,IF(A2:A4,B2:B4,)))
I used the checkbox and Google Apps Script, where column A (1) and column B (2) contain the checkboxes. For example:
function onEdit(evt) {
var range = evt.range;
var val = range.getValue();
var row = range.getRow();
var col = range.getColumn();
// -------------------------------------
// --- Cannot be both add and delete ---
// -------------------------------------
if (col == 1) {
if (val) {
SpreadsheetApp.getActiveSheet().getRange(row,2).setValue('FALSE');
}
}
else if (col == 2) {
if (val) {
SpreadsheetApp.getActiveSheet().getRange(row,1).setValue('FALSE');
}
}
}
I would like to share my codes. Please run onStart() for setting up radio boxes as well.
function onEdit(e) {
// radio button
var ss = SpreadsheetApp.getActiveSpreadsheet();
var gsheetrange = gsheet.getDataRange().getValues();
var rowcount = gsheetrange.length; // find end of row
for(var i = 0; i <= rowcount; i++) { // start from 0.
if (i==gedited){
gsheet.getRange(gedited, 2).setValue("true");
}
else
{
gsheet.getRange(i, 2).setValue("false");
}
}
}

Google sheets- loop search column, select tow

I have a google spreadsheet that i have one last problem i cant seem to solve.
i added a button to this script, and when i press the button it triggers the AddClient function.
How can i make the script below loop down all rows in column 3 searching for the yes value, when it finds it, copy the row below it to sheet "client" and then stop?
function AddClient(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "SETUP" && r.getColumn() == 3 && r.getValue() == "yes") {
var row = r.getRow() + 1; // Add 1 to the active row
var targetSheet = ss.getSheetByName("client");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 2, 1, 4).copyTo(target, {contentsOnly:true}); //Only selecting column 2, then the following 4 columns
}
}
Edit*
Example document:
https://docs.google.com/spreadsheets/d/1DFbAp0IN8_UFv9u8kWiZBTxDogj4e7FnuAPzC0grDw0/edit?usp=sharing
Any help greatly appreciated!
Cheers,
Reiel
Since you have a static form the position of the informatin to be copied will not change
Since we know we want to copy over the data we won't need to do any validation of where we are so all of that stuff can go
Sheets have an appendRow method that take care of the bookkeeping involved with finding the last row
This allows us to simplify the script to the following:
function AddClient() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName("SETUP").getRange(25, 2, 1, 4).getValues()[0];
ss.getSheetByName("client").appendRow(data);
}
Edit:
To remove duplicates you could do the following:
function AddClient() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName("SETUP").getRange(25, 2, 1, 4).getValues()[0];
var clients = ss.getSheetByName("client").getDataRange().getValues();
if (!clients.filter(function(row) {return data.join("|") === row.join("|");})) {
ss.getSheetByName("client").appendRow(data);
}
}
Note that for the particular example there are some problems because the leading zero gets cut off. Sheets is a bit weird and sometimes tries to force the format to be a number even when you set the cells' formats to Text...

moveTo messing up cells outside the range

im rearranging a spreadsheet using google script. I am first sorting it and then moving some rows within a range to the end of the sheet. Everytime i do the moveTo function some cells that reference the moved rows get changed to reflect the new row numbers even though the cells are outside my range and should not be modified. For example if im moving cell b3 and i have cell f4 =b3 then when i move b3 cell f4 changes to be whatever b3 is now. i tried locking it with =b$3 but still didnt work. Also it messes up the conditional formatting that should be in place for the entire column using something like "d2:e" and it changes to be something like "d2:e109" or something similar. Any clue whats going on?
function onEdit(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var allowedSheet = 1;
if(sheet.getIndex() == allowedSheet) {
var editedCell = sheet.getActiveCell();
var sortBy = [1, 3, 2];
var triggerCol = [1,2,3,10,11,12];
var rangeStart = "A";
var rangeEnd = "E";
var tableRange = "A2:E";
if(triggerCol.indexOf(editedCell.getColumn()) > -1) {
var range = sheet.getRange(tableRange);
range.sort([{column: sortBy[0], ascending: true}, {column: sortBy[1], ascending: false}, {column: sortBy[2], ascending: true}]);
var indexOfIncome = find( sheet, 2, "Income");
if( indexOfIncome > 0 ){
var overflowRange = sheet.getRange("A2:E" + (indexOfIncome - 1 ));
var lastRow = findFirstEmptyCell( sheet, 1 );
overflowRange.moveTo(sheet.getRange("A" + ( lastRow )));
var fullRange = sheet.getRange(rangeStart + indexOfIncome + ":" + rangeEnd);
fullRange.moveTo(sheet.getRange(rangeStart + "2"));
}
}
}
}
function find( sheet, column, value ) {
var data = sheet.getRange(1, column, sheet.getMaxRows()).getValues();
for( i = 0; i < sheet.getMaxRows(); i++ ){
if (data[i][0].toString().indexOf(value) > -1 ) {
return i + 1;
}
}
return 0;
}
function findFirstEmptyCell ( sheet, column ){
var data = sheet.getRange( 1, column, sheet.getMaxRows() ).getValues();
for( i = 0; i < sheet.getMaxRows() ; i++ ){
if( data[i][0] == "" ){
return i + 1;
}
}
return 0;
}
It's an expected behaviour, moveTo works just like Cut (Ctrl+X), while your looking for Copy+Paste then delete original content, which should be copyTo(newRange) associated with clear(oldRange).
I got it to work by using copy and then clearing. Now why in the world google would make a single function that behaves the exact opposite from all the other functions is beyond me. The documentation says moveto behaves as cut and paste but when i cut and paste i do not mess up the rest of my sheet.

Resources