Passa intervallo nella funzione personalizzata dello script di Google Apps senza utilizzare la notazione A1


10

Sono nuovo nello script di Google Apps e vorrei creare una funzione per un foglio di calcolo che somma i valori delle celle quando le celle soddisfano determinati criteri, come il colore di sfondo. Inoltre, vorrei passare l'intervallo come un array e non usare la notazione A1 per il seguente motivo.

Ho trovato una funzione che utilizza la notazione A1 qui . Il problema è che quando l'ho su una determinata cella

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

e copio il valore nella cella adiacente destra il risultato sarà di nuovo

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

mentre mi piacerebbe avere

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

altrimenti devo sempre modificare manualmente l'argomento di input e voglio evitarlo poiché devo usare questa funzione ampiamente.

Quindi ho provato passando un intervallo come una matrice di valori 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;
}

ma non so come ottenere la cella (cioè l'oggetto di tipo Range) a partire da quello che ho.


Questo non è possibile, senza l'uso di una chiamata API. Se ciò accade, è necessario utilizzare il A1 notation.
Jacob Jan Tuinstra,

Odio dirlo, ma la sceneggiatura che hai trovato non è molto efficiente. Su alcune righe, la differenza potrebbe non essere significativa, ma se hai più righe, diciamo 100, la differenza nel tempo di elaborazione è enorme. Lo script che ho preparato è 30 volte più veloce, perché utilizza solo tre chiamate API. Lo script che hai trovato utilizza per 100 righe, ca. 300 chiamate API. Vedi il mio esempio I numeri indicati sono millisecondi.
Jacob Jan Tuinstra,


1
prova ad usare questo: = sumWhereBackgroundColorIs ("white", ADDRESS (ROW (A1), COLUMN (A10), 4) & ":" & ADDRESS (ROW (A10), COLUMN (A10), 4))
roamer

Risposte:


8

All'affermazione dell'impossibilità di @ Jacob, lo rifiuto così ... (ma grazie per la velocità migliorata)

utilizzando:

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

con le seguenti funzioni farà quello che vuoi.

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

1
L'ho appena provato e funziona. Molto bene avere questa risposta su applicazioni Web.
Jacob Jan Tuinstra,

2
Metto alla prova queste cose, lo sai. ;-)
Tom Horwood,

Grazie pnuts - stavo solo leggendo la mia vecchia risposta e ho pensato che un po 'di colore potesse aiutare (suppongo che non accadrà comunque). Scusate tutti coloro che devono leggere lo stile del blocco note e le risposte :-)
Tom Horwood,

2

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

Invece di passare parametri come stringa alla funzione personalizzata, il seguente script prende l'input come intervallo:

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

Dai un'occhiata al seguente screenshot:

inserisci qui la descrizione dell'immagine


1

Il seguente piccolo script farà il trucco.

Codice

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

spiegato

Innanzitutto, viene determinato il foglio di calcolo attivo. Quindi vengono recuperati sia i valori che i colori, in base all'intervallo. I valori verranno utilizzati per scorrere i colori e infine la somma.

uso

inserisci qui la descrizione dell'immagine

Esempio

Ho creato un file di esempio per te: somma basata sullo sfondo


1
questa funzione funziona ma devi chiamarla con notazione A1, cioè scrivere su una cella = sumIfBgColor (#ffffff, "A1: A10") Questo non si adatta ai requisiti che ho scritto sopra, vale a dire mentre copia e incolla la formula tra le celle Dovrò modificare il contenuto manualmente
Ganswer,

@ganswer Nel mio commento alla tua domanda, ho già menzionato che non è possibile. Il codice che hai non avrebbe dovuto funzionare con o senza la notazione A1. Pertanto ho scritto una sceneggiatura che lo fa.
Jacob Jan Tuinstra,

scusa non ho letto il tuo commento. Quindi cattive notizie! Quindi non c'è modo ... Non posso usare la notazione A1, dovrò cambiare completamente il layout del mio foglio di calcolo. grazie
Ganswer il

@ganswer Hai trovato utile la mia risposta?
Jacob Jan Tuinstra,

1
è una buona opzione ma avevo già una funzione simile che funziona con la notazione A1. Modifica la tua risposta includendo nella parte superiore un commento che dice che ciò che cerco non è possibile, in modo da poter accettare la tua risposta come soluzione
Ganswer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.