ส่งผ่านช่วงในฟังก์ชันที่กำหนดเองของสคริปต์ 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.