ส่งผ่านช่วงในฟังก์ชันที่กำหนดเองของสคริปต์ Google Apps โดยไม่ใช้สัญลักษณ์ A1


10

ฉันยังใหม่กับสคริปต์ของ Google Apps และฉันต้องการสร้างฟังก์ชั่นสำหรับสเปรดชีตที่รวมค่าเซลล์เมื่อเซลล์มีคุณสมบัติตรงตามเกณฑ์ที่กำหนดเช่นสีพื้นหลัง นอกจากนี้ฉันต้องการส่งช่วงเป็นอาร์เรย์และไม่ใช้สัญลักษณ์ A1ด้วยเหตุผลดังต่อไปนี้

ผมพบว่าฟังก์ชั่นที่ใช้สัญกรณ์ a1 การที่นี่ ปัญหาคือเมื่อฉันมีมันในเซลล์ที่กำหนด

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

และฉันคัดลอกค่าไปยังเซลล์ที่อยู่ติดกันด้านขวาผลลัพธ์จะกลับมาอีก

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

ในขณะที่ฉันต้องการ

= sumWhereBackgroundColorIs ("สีขาว", "B1: B10" )

มิฉะนั้นฉันมักจะแก้ไขอาร์กิวเมนต์การป้อนข้อมูลด้วยตนเองและฉันต้องการหลีกเลี่ยงสิ่งนี้เนื่องจากฉันจะใช้ฟังก์ชั่นนี้อย่างกว้างขวาง

ดังนั้นฉันได้ลองผ่านช่วงเป็นอาร์เรย์ของค่าโดยใช้

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

แต่ฉันไม่ทราบวิธีการรับเซลล์ (เช่นวัตถุประเภทช่วง) เริ่มต้นจากสิ่งที่ฉันมี


ไม่สามารถทำได้โดยไม่ต้องใช้การเรียก API A1 notationถ้าเกิดว่าคุณจำเป็นต้องใช้
Jacob Jan Tuinstra

ฉันเกลียดที่จะพูด แต่สคริปต์ที่คุณพบไม่มีประสิทธิภาพมาก ในสองสามแถวความแตกต่างอาจไม่สำคัญ แต่ถ้าคุณมีแถวมากกว่านั้นให้บอกว่า 100 ความต่างของเวลาในการประมวลผลนั้นมาก สคริปต์ที่ฉันเตรียมไว้นั้นเร็วกว่า 30 เท่าเนื่องจากใช้การเรียก API เพียงสามครั้ง สคริปต์ที่คุณพบใช้สำหรับ 100 แถวโดยประมาณ การเรียก API 300 ครั้ง ดูตัวอย่างของฉัน ตัวเลขที่ระบุคือมิลลิวินาที
Jacob Jan Tuinstra

สิ่งนี้อาจมีประโยชน์: webapps.stackexchange.com/a/58179/12075
sanmai

1
ลองใช้สิ่งนี้: = sumWhereBackgroundColorIs ("white", ADDRESS (ROW (A1), COLUMN (A10), 4) & ":" & ADDRESS (ROW (A10), COLUMN (A10), 4))
ผู้ชม

คำตอบ:


8

ฉันอ้างว่ามันเป็นไปไม่ได้ที่ @ Jacob ฉันจะลบล้างมัน ... (แต่ขอบคุณสำหรับความเร็วที่เพิ่มขึ้น)

โดยใช้:

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

ด้วยฟังก์ชั่นต่อไปนี้จะทำสิ่งที่คุณต้องการ

/**
 * 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
เพิ่งลองและใช้งานได้ ดีมากที่มีคำตอบนี้ในเว็บแอปพลิเคชัน
จาค็อบ ม.ค. Tuinstra

2
ฉันจะทดสอบสิ่งเหล่านี้คุณรู้ ;-)
Tom Horwood

ขอบคุณ pnuts - เพิ่งอ่านคำตอบเก่าของฉันและคิดว่าสีอาจช่วยได้ (ฉันเดาว่ามันจะไม่เกิดขึ้น) ขออภัยทุกคนที่ต้องอ่านคำตอบในรูปแบบแผ่นจดบันทึก :-)
Tom Horwood

2

การอ้างอิง: http://igoogledrive.blogspot.com/2015/11/google-spreadsheet-sum-of-colored-cells.html

แทนที่จะส่งพารามิเตอร์เป็นสตริงไปยังฟังก์ชันที่กำหนดเองสคริปต์ต่อไปนี้จะป้อนข้อมูลเป็นช่วง:

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

ดูภาพหน้าจอต่อไปนี้:

ป้อนคำอธิบายรูปภาพที่นี่


1

สคริปต์เล็กน้อยต่อไปนี้จะทำเคล็ดลับ

รหัส

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

อธิบาย

ก่อนกำหนดสเปรดชีตที่ใช้งานอยู่จะถูกกำหนด จากนั้นทั้งค่าและสีตามช่วงจะถูกนำมาใช้ ค่าจะถูกใช้เพื่อวนซ้ำสีและท้ายที่สุดการรวม

การใช้

ป้อนคำอธิบายรูปภาพที่นี่

ตัวอย่าง

ฉันได้สร้างไฟล์ตัวอย่างสำหรับคุณ: ผลรวมตามพื้นหลัง


1
ฟังก์ชั่นนี้ใช้งานได้ แต่คุณต้องเรียกมันด้วยสัญกรณ์ A1 คือการเขียนลงในเซลล์ = sumIfBgColor (#ffffff, "A1: A10") สิ่งนี้ไม่ตรงกับข้อกำหนดที่ฉันเขียนไว้ด้านบนกล่าวคือในขณะที่คัดลอกและวางสูตรระหว่างเซลล์ ฉันจะต้องแก้ไขเนื้อหาด้วยตนเอง
Ganswer

@ganswer ในความคิดเห็นต่อคำถามของคุณฉันได้กล่าวไปแล้วว่าเป็นไปไม่ได้ รหัสที่คุณมีไม่ควรทำงานด้วยหรือไม่มีสัญลักษณ์ A1 ดังนั้นฉันจึงเขียนสคริปต์ที่ทำ
Jacob Jan Tuinstra

ขอโทษฉันไม่ได้อ่านความคิดเห็นของคุณ ข่าวร้ายมาก! ดังนั้นไม่มีทาง .. ฉันไม่สามารถใช้สัญลักษณ์ A1 ได้ฉันจะต้องเปลี่ยนเค้าโครงทั้งหมดของสเปรดชีต ขอบคุณ
Ganswer

@ganswer คุณคิดว่าคำตอบของฉันมีประโยชน์หรือไม่?
Jacob Jan Tuinstra

1
มันเป็นตัวเลือกที่ดี แต่ฉันมีฟังก์ชั่นที่คล้ายกันซึ่งทำงานกับสัญลักษณ์ A1 แล้ว โปรดแก้ไขคำตอบของคุณรวมทั้งที่ด้านบนแสดงความคิดเห็นบอกว่าสิ่งที่ฉันค้นหาเป็นไปไม่ได้เพื่อที่ฉันสามารถยอมรับคำตอบของคุณเป็นวิธีการแก้ปัญหา
Ganswer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.