Rango de aprobación en la función personalizada de script de Google Apps sin usar la notación A1

10

Soy nuevo en el script de Google Apps y me gustaría crear una función para una hoja de cálculo que sume los valores de las celdas cuando las celdas cumplen ciertos criterios, como el color de fondo. Además, me gustaría pasar el rango como una matriz y no usar la notación A1 por la siguiente razón.

Encontré una función que usa la notación A1 aquí . El problema es que cuando lo tengo en una celda determinada

=sumWhereBackgroundColorIs("white", "A1:A10")

y copio el valor en la celda adyacente derecha, el resultado será nuevamente

= sumWhereBackgroundColorIs ("blanco", "A1: A10" )

mientras me gustaría tener

= sumWhereBackgroundColorIs ("blanco", "B1: B10" )

de lo contrario, siempre tengo que modificar manualmente el argumento de entrada y quiero evitarlo, ya que tengo que usar esta función ampliamente.

Por lo tanto, he intentado pasar un rango como una matriz de valores usando

=sumIfBgColor(#ffffff, A1:A10)


function sumIfBgColor(color, range){
    var x = 0;
    for(var i = 0; i < range.length; i++){
      for(var j = 0; j < range[i].length; j++){

        var cell = getCell();

        if(cell.getBackgroundColor() == color)
          x += parseFloat(range[i][j]);
      }
    }
    return x;
}

pero no sé cómo obtener la celda (es decir, el objeto de tipo Range) a partir de lo que tengo.

Ganswer
fuente
Eso no es posible sin el uso de una llamada API. Si eso sucede, debe usar el A1 notation.
Jacob Jan Tuinstra
Odio decirlo, pero el script que encontraste no es muy eficiente. En algunas filas, la diferencia puede no ser significativa, pero si tiene más filas, digamos 100, entonces la diferencia en el tiempo de procesamiento es enorme. El script que preparé es 30 veces más rápido, porque usa solo tres llamadas API. El script que encontró utiliza para 100 filas, aprox. 300 llamadas API. Mira mi ejemplo. Los números dados son milisegundos.
Jacob Jan Tuinstra
Esto puede ser útil: webapps.stackexchange.com/a/58179/12075
sanmai
1
intente utilizar esto: = sumWhereBackgroundColorIs ("white", ADDRESS (ROW (A1), COLUMN (A10), 4) & ":" & ADDRESS (ROW (A10), COLUMN (A10), 4))
roamer

Respuestas:

8

Para el reclamo de imposibilidad de @ Jacob, lo refute así ... (pero gracias por la velocidad mejorada)

utilizando:

=sumIfBgColor("#ffffff", A1:A10, COLUMN(A1), ROW(A1))

con las siguientes funciones harás lo que quieras.

/**
 * 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;
}
Tom Horwood
fuente
1
Solo lo probé y funciona. Muy bueno tener esta respuesta en aplicaciones web.
Jacob Jan Tuinstra
2
Pruebo estas cosas, ya sabes. ;-)
Tom Horwood
Gracias por favor, solo estaba leyendo mi respuesta anterior y pensé que un poco de color podría ayudar (aunque supongo que no sucederá). En este momento todo el mundo que tiene que leer las respuestas de estilo bloc de notas :-)
Tom Horwood
2

Referencia: http://igoogledrive.blogspot.com/2015/11/google-spreadsheet-sum-of-colored-cells.html

En lugar de pasar parámetros como una cadena a la función personalizada, el siguiente script toma la entrada como un rango:

/**
* @param {string} color String as background color to be searched for in sumRange
* @param {range} sumRange Range to be evaluated
* @return {number}
* @customfunction
*/

function sumColoredCells(color,sumRange) {
  var activeRange = SpreadsheetApp.getActiveRange();
  var activeSheet = activeRange.getSheet();
  var formula = activeRange.getFormula();
  var rangeA1Notation = formula.match(/\,(.*)\)/).pop();
  var range = activeSheet.getRange(rangeA1Notation);
  var bg = range.getBackgrounds();
  var values = range.getValues();
  var total = 0;

  for(var i=0;i<bg.length;i++)
    for(var j=0;j<bg[0].length;j++)
      if( bg[i][j] == color )
        total=total+(values[i][j]*1);
  return total;
};

Echa un vistazo a la siguiente captura de pantalla:

ingrese la descripción de la imagen aquí

Kishan
fuente
1

El siguiente pequeño script hará el truco.

Código

function sumIfBgColor(color, range){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var getColors = ss.getRange(range).getBackgrounds();
  var getValues = ss.getRange(range).getValues(), x = 0;
  for(var i = 0; i < getValues.length; i++) {
    for(var j = 0; j < getValues[0].length; j++) {
      if(getColors[i][j].toString() == color) {
        x += getValues[i][j];
      }
    }
  }
  return x;
}

Explicado

Primero, se determina la hoja de cálculo activa. Luego, se obtienen tanto los valores como los colores, según el rango. Los valores se utilizarán para recorrer los colores y, en última instancia, la suma.

Uso

ingrese la descripción de la imagen aquí

Ejemplo

He creado un archivo de ejemplo para usted: Suma basada en el fondo

Jacob Jan Tuinstra
fuente
1
esta función funciona pero debe llamarla con notación A1, es decir, escribir en una celda = sumIfBgColor (#ffffff, "A1: A10") Esto no se ajusta a los requisitos que escribí anteriormente, es decir, mientras copie y pegue la fórmula entre celdas Tendré que editar el contenido manualmente
Ganswer
@ganswer En mi comentario a su pregunta, ya mencioné que no es posible. El código que tiene no debería haber funcionado con o sin la notación A1. Por eso escribí un guión que sí.
Jacob Jan Tuinstra
lo siento, no leí tu comentario. ¡Tan malas noticias! Así que no hay forma ... No puedo usar la notación A1, tendré que cambiar completamente el diseño de mi hoja de cálculo. gracias
Ganswer
@ganswer ¿Le pareció útil mi respuesta?
Jacob Jan Tuinstra
1
Es una buena opción, pero ya tenía una función similar que funciona con la notación A1. Modifique su respuesta, incluido en la parte superior un comentario que indique que lo que busco no es posible, de modo que pueda aceptar su respuesta como solución
Ganswer