0

I have a database that has columns of RGB values and I wanted to display the color on anther column. I will have a custom function on the cell where I passed in the RGB values from the other columns.

=setBGColor(INDIRECT(ADDRESS(ROW(),COLUMN(F2)), INDIRECT(ADDRESS(ROW(),COLUMN(G2)), INDIRECT(ADDRESS(ROW(),COLUMN(H2)))

In the custom function I want to set the background color of the caller cell and also return the hex value. The first problem I ran into is that I couldn't find a decimal to hex conversion function from the Google script. In the spreadsheet there is the handy DEC2HEX function but I couldn't find it in the script editor.

The second problem is that I don't know how to get the cell that called the function. I tried this and it doesn't work. I tested with some dummy hex value and got an error "You do not have permission to call setBackground".

function setBGColor()
{
  //var rgb_hex = "#" + decToHexFunc(r) + decToHexFunc(g) + decToHexFunc(b);

  SpreadsheetApp.getActiveSpreadsheet().getCurrentCell().setBackground("FFE4CE"); // test
  //return rgb_hex;  
}

enter image description here

reddy
  • 1,721
  • 3
  • 16
  • 26
  • If you are trying to replicate the `DEC2HEX` function in Google Apps Script, you can manually create an RGB to HEX script as a substitute, using this [guide](https://stackoverflow.com/a/5624139/15384825). On question 2, custom functions cannot use the `setBackgrounds()` method due to authorization requirements, resulting in an error message. This is because Google Sheets restricts custom functions from formatting or changing cell appearance to maintain security and prevent unexpected or malicious behavior. If you're interested, we can explore alternative solutions for your issue. – SputnikDrunk2 Apr 28 '23 at 23:56
  • Also, kindly share a sample sheet to replicate your setup accurately, if needed. – SputnikDrunk2 Apr 28 '23 at 23:56
  • @SputnikDrunk2 I thought the limitation only applies to custom functions that are trying to setbackground for a range of cells? While I'm only trying to do it for the one cell that calls the function? – reddy Apr 29 '23 at 00:14
  • According to this [post](https://stackoverflow.com/a/15936281/15517777) on StackOverflow, `custom functions` can only return values for your sheet and cannot set anything, such as `setValues()` or `setBackgrounds()`. – SputnikDrunk2 Apr 29 '23 at 00:26
  • According to the [documentation](https://developers.google.com/apps-script/guides/sheets/functions#using_services), `custom functions` have a very limited set of available Apps Script Services. – Tedinoz Apr 29 '23 at 00:29
  • So is there a workaround for this? I've seen the use of the `onEdit` event handler to do it but I don't like it triggering on every rgb hex. https://stackoverflow.com/a/57417702/1862525 – reddy Apr 29 '23 at 01:17

2 Answers2

0

Alternative Solution [UPDATED]

Note: This script is intended to serve as a starting point or reference for your project. It's important to note that the community members do not provide coding services. While the logic outlined here has some limitations, it will help you get started with your approach to the issue at hand.

As an alternative solution, you could incorporate the usage of the onEdit() trigger which allows you to use the setBackground() function. Please review the script comments to understand how the script works. This script will automatically add the HEX value & background color in an instance of onEdit() function.

This onEdit() function will only run once you enter the word 'set' on a cell under the Hex column on any sheet in your Spreadsheet file. See demo below.

Sample Script [UPDATED]

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

  //Getting the current column & row
  var column = sheet.getActiveRange().getColumn();
  var row = sheet.getActiveRange().getRow();

  //getting the current RGB data from the selected cell & filter it just in case there are typos
  var rgb = sheet.getRange(row, column - 3, 1, 3).getValues()
    .filter(x => !x.join().match(/[a-zA-Z]/gm));

  //Do not run script if no conditions are met
  if (sheet.getActiveCell().getValue() == 'set') {
    var hex = rgb.map(x => [rgbToHex(x[0], x[1], x[2])]);

    //Set the hex value & BG color
    sheet.getRange(row, column).setValue(hex);
    sheet.getRange(row, column).setBackground(hex);

    //Adjusts font color accordingly for readibility if BG color is too dark or too light.
    isColorDark(rgb[0][0], rgb[0][1], rgb[0][2]) ? sheet.getRange(row, column).setFontColor('white') : sheet.getRange(row, column).setFontColor('black');
  }
}

function rgbToHex(red, green, blue) {
  var hex = "#" + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1);
  return hex;
}

//Checks if BG dark or light
function isColorDark(r, g, b) {
  var luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
  return luminance < 0.5;
}

Demo

  • After placing the word "set" on the Hex column:

enter image description here

Reference

SputnikDrunk2
  • 3,398
  • 1
  • 5
  • 17
  • Hi, my columns `F`, `G`, `H` held the `R`, `G`, `B` values separately. I want the function to run on per cell, I don't want to specify the column in the script because I will need to use the function on multiple sheets where the column needed to be used will be different. – reddy Apr 29 '23 at 03:25
  • I understand. Can you please update your posted question and add a sample sheet with accurate data similar to your actual sheet for better replication accuracy? – SputnikDrunk2 Apr 29 '23 at 03:29
  • Hi, I added an image of the setup in the OP – reddy Apr 29 '23 at 03:39
  • Updated the posted alternate answer. Thanks – SputnikDrunk2 Apr 29 '23 at 06:45
  • Thanks, I modified this a bit so it can be applied to a range of selection in the column instead of one at a time. – reddy May 01 '23 at 15:06
0

A custom function can not change the sheet format which is why you are getting the error, however I have an alternate solution for you where you wont have to use a custom function at all. By using an onEdit() function this can be solved.

function onEdit(e){
  var column_number = e.source.getActiveSheet().getActiveRange().getColumn();
  //check if one of the first three columns (R, G, B) is edited
  if(column_number == 1 || column_number == 2 || column_number == 3){

    var s = SpreadsheetApp.getActiveSheet();
    var row_number = e.source.getActiveSheet().getActiveRange().getRowIndex();

    //Check if all the three values are filled (r,g,b)
    if( !s.getRange(row_number,1).isBlank() && !s.getRange(row_number,2).isBlank() && !s.getRange(row_number,3).isBlank()){
      
      var r = parseInt(s.getRange(row_number,1).getValue());
      var g = parseInt(s.getRange(row_number,2).getValue());
      var b = parseInt(s.getRange(row_number,3).getValue());

      s.getRange(row_number,4).setBackgroundRGB(r,g,b);
      s.getRange(row_number,4).setValue(s.getRange(row_number,4).getBackground());
    }
  }
}

This code assumes that your R,G,B values will be entered in First, Second and Third Columns respectively and you need the color and hex code in the 4th column. If that is not the case, you can just edit the numeric column values in the code or just use 3 variables.

Output