Passer la plage dans la fonction personnalisée du script Google Apps sans utiliser la notation A1

10

Je suis nouveau dans le script Google Apps et je voudrais créer une fonction pour une feuille de calcul qui additionne les valeurs des cellules lorsque les cellules répondent à certains critères, tels que la couleur d'arrière-plan. De plus, je voudrais passer la plage sous forme de tableau et ne pas utiliser la notation A1 pour la raison suivante.

J'ai trouvé une fonction qui utilise la notation A1 ici . Le problème est que lorsque je l'ai sur une cellule donnée

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

et je copie la valeur dans la cellule adjacente droite, le résultat sera à nouveau

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

alors que j'aimerais avoir

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

sinon, je dois toujours modifier manuellement l'argument d'entrée et je veux éviter cela car je dois utiliser cette fonction de manière intensive.

Par conséquent, j'ai essayé en passant une plage comme un tableau de valeurs en utilisant

=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;
}

mais je ne sais pas comment obtenir la cellule (c'est-à-dire l'objet de type Range) à partir de ce que j'ai.

Ganswer
la source
Ce n'est pas possible, sans l'utilisation d'un appel API. Si cela se produit, vous devez utiliser le A1 notation.
Jacob Jan Tuinstra
Je déteste le dire, mais le script que vous avez trouvé n'est pas très efficace. Sur quelques lignes, la différence peut ne pas être significative, mais si vous avez plus de lignes, disons 100, alors la différence de temps de traitement est énorme. Le script que j'ai préparé est 30 fois plus rapide, car il n'utilise que trois appels d'API. Le script que vous avez trouvé utilise pour 100 lignes, environ. 300 appels API. Voir mon exemple. Les nombres donnés sont des millisecondes.
Jacob Jan Tuinstra
Cela peut être utile: webapps.stackexchange.com/a/58179/12075
sanmai
1
essayez d'utiliser ceci: = sumWhereBackgroundColorIs ("white", ADDRESS (ROW (A1), COLUMN (A10), 4) & ":" & ADDRESS (ROW (A10), COLUMN (A10), 4))
roamer

Réponses:

8

À la revendication d'impossibilité de @ Jacob, je la réfute ainsi ... (mais merci pour l'amélioration de la vitesse)

en utilisant:

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

avec les fonctions suivantes fera ce que vous voulez.

/**
 * 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
la source
1
Je viens de l'essayer et cela fonctionne. Très bien d'avoir cette réponse sur les applications Web.
Jacob Jan Tuinstra
2
Je teste ces choses, tu sais. ;-)
Tom Horwood
Merci pnuts - je lisais juste mon ancienne réponse et je pensais qu'un peu de couleur pourrait aider (je suppose que cela ne se produira pas cependant). Désolé tous ceux qui doivent lire les réponses de style bloc-notes :-)
Tom Horwood
2

Référence: http://igoogledrive.blogspot.com/2015/11/google-spreadsheet-sum-of-colored-cells.html

Au lieu de transmettre des paramètres sous forme de chaîne à la fonction personnalisée, le script suivant prend l'entrée en tant que plage:

/**
* @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;
};

Jetez un œil à la capture d'écran suivante:

entrez la description de l'image ici

Kishan
la source
1

Le petit script suivant fera l'affaire.

Code

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;
}

Expliqué

Tout d'abord, la feuille de calcul active est déterminée. Ensuite, les valeurs et les couleurs, basées sur la plage, sont extraites. Les valeurs seront utilisées pour parcourir les couleurs et finalement la sommation.

Usage

entrez la description de l'image ici

Exemple

J'ai créé un exemple de fichier pour vous: somme basée sur l'arrière-plan

Jacob Jan Tuinstra
la source
1
cette fonction fonctionne mais vous devez l'appeler avec la notation A1, c'est-à-dire écrire sur une cellule = sumIfBgColor (#ffffff, "A1: A10") Cela ne correspond pas aux exigences que j'ai écrites ci-dessus, à savoir en copiant et collant la formule entre les cellules Je vais devoir éditer le contenu manuellement
Ganswer
@ganswer Dans mon commentaire à votre question, j'ai déjà mentionné que ce n'était pas possible. Le code que vous avez ne devrait pas avoir fonctionné avec ou sans la notation A1. J'ai donc écrit un script qui le fait.
Jacob Jan Tuinstra
désolé, je n'ai pas lu votre commentaire. Tellement mauvaise nouvelle! Il n'y a donc aucun moyen ... Je ne peux pas utiliser la notation A1, je vais devoir changer complètement la disposition de ma feuille de calcul. merci
Ganswer
@ganswer Avez-vous trouvé ma réponse utile?
Jacob Jan Tuinstra
1
c'est une bonne option mais j'avais déjà une fonction similaire qui fonctionne avec la notation A1. Veuillez modifier votre réponse en incluant en haut un commentaire disant que ce que je recherche n'est pas possible, afin que je puisse accepter votre réponse comme solution
Ganswer