To @Jacob's claim of impossibility, I refute it thus... (but thanks for the improved speed)
using:
=sumIfBgColor("#ffffff", A1:A10, COLUMN(A1), ROW(A1))
with the following functions will do what you want.
/**
* Sums cell values in a range if they have the given background color
*
* @param {String} color Hex string of color eg ("#ffffff")
* @param {Array.Array} range Values of the desired range
* @param {int} startcol The column of the range
* @param {int} startrow The first row of the range
*
* @return {int} Sum of all cell values matching the condition
*/
function sumIfBgColor(color, range, startcol, startrow){
// convert from int to ALPHANUMERIC - thanks to
// Daniel at http://stackoverflow.com/a/3145054/2828136
var col_id = String.fromCharCode(64 + startcol);
var endrow = startrow + range.length - 1
// build the range string, then get the background colours
var range_string = col_id + startrow + ":" + col_id + endrow
var ss = SpreadsheetApp.getActiveSpreadsheet();
var getColors = ss.getRange(range_string).getBackgrounds();
var x = 0;
for(var i = 0; i < range.length; i++) {
for(var j = 0; j < range[0].length; j++) {
// Sometimes the cell background is eg 'white' rather than '#ffffff'.
// I don't know why - I think it's a bug.
// so we remove that inconsistency with colourNameToHex
// courtesy of Greg at http://stackoverflow.com/a/1573141/2828136
if(colourNameToHex(getColors[i][j].toString()) == color) {
x += range[i][j];
}
}
}
return x;
}
/**
* Takes a colour string and returns it to a hex string. If a non-matching string is
* passed, it will return the argument as is - for this situation it means that a
* hex string can be passed to it and be returned as is. This is not for production.
*
* @param {string} color Must be either a colour name or hex string of color eg ("#ffffff")
*
* @return {object|string} hex string of color eg ("#ffffff") or the argument given.
*/
function colourNameToHex(colour)
{
var colours = {"aliceblue":"#f0f8ff","antiquewhite":"#faebd7","aqua":"#00ffff","aquamarine":"#7fffd4","azure":"#f0ffff",
"beige":"#f5f5dc","bisque":"#ffe4c4","black":"#000000","blanchedalmond":"#ffebcd","blue":"#0000ff","blueviolet":"#8a2be2","brown":"#a52a2a","burlywood":"#deb887",
"cadetblue":"#5f9ea0","chartreuse":"#7fff00","chocolate":"#d2691e","coral":"#ff7f50","cornflowerblue":"#6495ed","cornsilk":"#fff8dc","crimson":"#dc143c","cyan":"#00ffff",
"darkblue":"#00008b","darkcyan":"#008b8b","darkgoldenrod":"#b8860b","darkgray":"#a9a9a9","darkgreen":"#006400","darkkhaki":"#bdb76b","darkmagenta":"#8b008b","darkolivegreen":"#556b2f",
"darkorange":"#ff8c00","darkorchid":"#9932cc","darkred":"#8b0000","darksalmon":"#e9967a","darkseagreen":"#8fbc8f","darkslateblue":"#483d8b","darkslategray":"#2f4f4f","darkturquoise":"#00ced1",
"darkviolet":"#9400d3","deeppink":"#ff1493","deepskyblue":"#00bfff","dimgray":"#696969","dodgerblue":"#1e90ff",
"firebrick":"#b22222","floralwhite":"#fffaf0","forestgreen":"#228b22","fuchsia":"#ff00ff",
"gainsboro":"#dcdcdc","ghostwhite":"#f8f8ff","gold":"#ffd700","goldenrod":"#daa520","gray":"#808080","green":"#008000","greenyellow":"#adff2f",
"honeydew":"#f0fff0","hotpink":"#ff69b4",
"indianred ":"#cd5c5c","indigo ":"#4b0082","ivory":"#fffff0","khaki":"#f0e68c",
"lavender":"#e6e6fa","lavenderblush":"#fff0f5","lawngreen":"#7cfc00","lemonchiffon":"#fffacd","lightblue":"#add8e6","lightcoral":"#f08080","lightcyan":"#e0ffff","lightgoldenrodyellow":"#fafad2",
"lightgrey":"#d3d3d3","lightgreen":"#90ee90","lightpink":"#ffb6c1","lightsalmon":"#ffa07a","lightseagreen":"#20b2aa","lightskyblue":"#87cefa","lightslategray":"#778899","lightsteelblue":"#b0c4de",
"lightyellow":"#ffffe0","lime":"#00ff00","limegreen":"#32cd32","linen":"#faf0e6",
"magenta":"#ff00ff","maroon":"#800000","mediumaquamarine":"#66cdaa","mediumblue":"#0000cd","mediumorchid":"#ba55d3","mediumpurple":"#9370d8","mediumseagreen":"#3cb371","mediumslateblue":"#7b68ee",
"mediumspringgreen":"#00fa9a","mediumturquoise":"#48d1cc","mediumvioletred":"#c71585","midnightblue":"#191970","mintcream":"#f5fffa","mistyrose":"#ffe4e1","moccasin":"#ffe4b5",
"navajowhite":"#ffdead","navy":"#000080",
"oldlace":"#fdf5e6","olive":"#808000","olivedrab":"#6b8e23","orange":"#ffa500","orangered":"#ff4500","orchid":"#da70d6",
"palegoldenrod":"#eee8aa","palegreen":"#98fb98","paleturquoise":"#afeeee","palevioletred":"#d87093","papayawhip":"#ffefd5","peachpuff":"#ffdab9","peru":"#cd853f","pink":"#ffc0cb","plum":"#dda0dd","powderblue":"#b0e0e6","purple":"#800080",
"red":"#ff0000","rosybrown":"#bc8f8f","royalblue":"#4169e1",
"saddlebrown":"#8b4513","salmon":"#fa8072","sandybrown":"#f4a460","seagreen":"#2e8b57","seashell":"#fff5ee","sienna":"#a0522d","silver":"#c0c0c0","skyblue":"#87ceeb","slateblue":"#6a5acd","slategray":"#708090","snow":"#fffafa","springgreen":"#00ff7f","steelblue":"#4682b4",
"tan":"#d2b48c","teal":"#008080","thistle":"#d8bfd8","tomato":"#ff6347","turquoise":"#40e0d0",
"violet":"#ee82ee",
"wheat":"#f5deb3","white":"#ffffff","whitesmoke":"#f5f5f5",
"yellow":"#ffff00","yellowgreen":"#9acd32"};
if (typeof colours[colour.toLowerCase()] != 'undefined')
return colours[colour.toLowerCase()];
return colour;
}
Best Answer
You start by getting a reference to a Range with the
getRange
function. Once we have that, and since this range consists of a single cell, we can use thesetValue
function:... which will write
TEXT
to cellB5
.If you have a multi-cell range (which is more common), and you don't want to write the same value to all of the cells, you need to use the
setValues
function (note the plural), which takes an array of arrays ([[]]
) as argument:In this case, we have two cells on the same row, so the outer array has a single element: the inner array, which again have two elements - one for each cell.
Compare to the next example, where we want to write to a range that spans multiple rows:
And finally, let's write to a multi-column, multi-row range:
I have created an example spreadsheet to demonstrate these snippets - feel free to copy it.
Please note that any function that directly fetches or manipulates spreadsheet data directly, is slow, regardless of the amount of data involved. So keep the number of spreadsheet function calls low. If you want to update multiple cells, it is usually better to fetch the full array of values first, then update the values you want to change, and write back the whole array.
In this example, we have a spreadsheet with data from
A1
toH8
, but we want to update only two cells:D7
andG6
. The rest of the cells should be unchanged.Note how we use
range.getValues()
to get an array of the existing values. Then we set the individual values in that array. Since JavaScript array indexes are0
-based, row 7 will be6
, and columnD
, being the 4th column, will be3
- hencevalues[6][3]
. Similarly,G6
will bevalues[5][6]
.Finally, we write the array back to the range. We can update as many values we like in the array, while keeping the number of spreadsheet function calls low - only a single
getValues
and a singlesetValues
.From your comment it is probably worth mentioning how a pure function can be used from a spreadsheet. A pure function is a function that has no side effects, that is, its return value depends only on its arguments.
A pure function can be called from the spreadsheet with
=functionName
. Let's say you want a function multiplies an input value with 2, and returns its result. Enter this in the script editor:In your spreadsheet, let's say in cell
A2
, you would enter the formula=multiplyByTwo(4)
.A2
will then display8
.You could also use other cells as arguments. Let's change the formula to
=multiplyByTwo(B2)
, and in cellB2
enter the number6
. CellA2
will now display12
.Here's another example for pure functions, and read more about Custom functions in Google's documentation.
You can also return a multi-dimensional array, in which case the result will span several rows/columns in the spreadsheet. The function
can be used in cell
D2
as=multiplyByTwoAndFour(3)
, which will causeD2
to display6
andD3
to display12
.