3

Excel apparently has this type of conditional formatting built-in.

I'd like to accomplish the same in Google Sheets via Google Apps Script. The following should demonstrate the before and after conditions:

Example Dataset

        A           B           C
  1   apple     Macintosh
  2   apple     Granny Smith
  3   orange    Florida
  4   orange    Valencia
  5   pear      Garden
  6   banana    Chiquita

Resulting Example Dataset

        A           B           C
  1   apple     Macintosh
  2   apple     Granny Smith
  ---------------------------
  3   orange    Florida
  4   orange    Valencia
  ---------------------------
  5   pear      Garden
  ---------------------------
  6   banana    Chiquita
  ---------------------------

The script/answer to this question should display a bottom border under the entire row (of columns 'A', 'B' & 'C') for rows: 2, 4, 5, & 6. The spreadsheet logic is fairly straightforward:

  1. In cell C1, =IF(A1=A2,"NOBORDER","BORDER")
  2. Then wrap the above in =IF(C1="BORDER", addBorder(A1:C1), "NOBORDER")

In a larger dataset, this formating will help the end user see logical groupings more easily. A Google Apps Script is required because the data will be updating dynamically.

Below is some sample Google Apps Script code, but it's not working

function onEdit(event) {
  var sheet = SpreadsheetApp.getActiveSheet();
  var range = event.range;

  var startingRow = range.getRow();
  var numRows = range.getNumRows();
  for (var i = 1; i <= numRows; i++) {
    var rowNbr = startingRow + i - 1;
    Logger.log("changed row %s",rowNbr );
    //Now check the WHOLE row
    var colLeft=1; //1=A
    var colRight=11; //11=K
    var row = sheet.getRange(rowNbr,colLeft, 1, colRight - colLeft + 1);
    if(row.isBlank()) {
      row.setBorder(false, null, true, null, null, null, "red", SpreadsheetApp.BorderStyle.SOLID_MEDIUM);
    } else {
      row.setBorder(false, null, null, null, null, null, "black", SpreadsheetApp.BorderStyle.SOLID_MEDIUM);
    }
  }
}
Rubén
  • 34,714
  • 9
  • 70
  • 166
joelhaus
  • 903
  • 1
  • 10
  • 18
  • My scripts are not worth repeating here, as they are a mix of copied code snippets from various SO answers & the API docs. I was hoping someone more versed in the Google Sheets API could whip something together. – joelhaus Feb 28 '18 at 04:13
  • `addBorder(A1:C1)` This is a custom function. Custom functions can only return a value and are not able to edit properties of the cell, or edit other cells. – Chris Feb 28 '18 at 05:29
  • Thanks Chris, this actually just gave me an idea, but it seems custom functions cannot act on other cells without an array: https://stackoverflow.com/questions/15933019/google-script-setvalue-permission – joelhaus Feb 28 '18 at 06:41

1 Answers1

10

Figured it out with help from this Q&A: https://webapps.stackexchange.com/questions/59484/changing-row-colour-if-value-set?rq=1

This code tests the values in column A. If result = TRUE, applies a border across that entire row:

function onOpen() {
   GroupMyData(); // trigger this function on sheet opening
}

function GroupMyData() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('shared'); // apply to sheet name only
  var rows = sheet.getRange('a1:g'); // range to apply formatting to
  var numRows = rows.getNumRows(); // no. of rows in the range named above
  var values = rows.getValues(); // array of values in the range named above
  var testvalues = sheet.getRange('a1:a').getValues(); // array of values to be tested (1st column of the range named above)

  rows.setBorder(false, false, false, false, false, false, "red", SpreadsheetApp.BorderStyle.SOLID_MEDIUM); // remove existing borders before applying rule below
      //Logger.log(numRows);

  for (var i = 0; i <= numRows - 1; i++) {
      var n = i + 1;
      //Logger.log(n);
      //Logger.log(testvalues[i] > 0);
      //Logger.log(testvalues[i]);
      if (testvalues[i] > 0) { // test applied to array of values
        sheet.getRange('a' + n + ':g' + n).setBorder(null, null, true, null, null, null, "red", SpreadsheetApp.BorderStyle.SOLID_MEDIUM); // format if true
      }
  }
};
joelhaus
  • 903
  • 1
  • 10
  • 18