【问题标题】:select cells in a column WHERE corresponding cells' value is given选择列中的单元格,其中给出相应单元格的值
【发布时间】:2019-09-17 08:07:07
【问题描述】:

假设您在 Google 表格中有这样的电子表格

你想 将 Q:Q 中所有单元格的值求和 D:D 列中对应的单元格(即在同一行)具有某些给定值..

现在,如果我们使用像 MySql 这样的数据库语言,我想这会很容易,您可能会指示类似的东西

SELECT cells in "Tot. / Anno" (Q:Q) WHERE "level" (D:D) is B or MID

就是这样,但我想在 Javascript 中不可能有这么直接的东西;所以恐怕需要一些解决方法。

那么,首先,表格背后的逻辑是什么?
level 下的 D:D 列中,您有四个选项可供您选择,它们是:bmidpro 顶部。 B 代表基本,这里的逻辑是试图建立一个渐进预算
有些费用是基本的,您无法避免,例如医疗或您的银行帐户或电话费;而其他喜欢休闲和旅行的人是次要的,你可以尽情享受;所以它们不是基本的,但很可能是 mid pro 甚至 top :) 这就是背后的逻辑和价值的尺度。

当您在 D2 中选择给定标准时,您应该根据相同的渐进逻辑在 G2 中获得匹配的 SUM:

b   in D2  -->  only sum cells in Q:Q where value is b
mid in D2  -->  only sum cells in Q:Q where value is b OR mid
pro in D2  -->  only sum cells in Q:Q where value is b OR mid OR pro
top in D2  -->       sum cells in Q:Q where value is b OR mid OR pro OR top

现在,关于编码,这是我找到的解决方法。 确实有效,但并不优雅。
我想听听一些更有效和更合适的方法来处理这个问题:我处于初级水平,我确信有更有效的解决方案可供使用

// onEdit is meant to make sure that a real-time recalculation is triggered  
// at any change within the specified columns
function onEdit(e){

var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();

  var cell = sheet.getRange("Q2");
  var range = e.range;
  var columnOfCellEdited = range.getColumn();

  if (columnOfCellEdited === 4 || 17) {


// creating 2 different arrays from the two different comlumns (ranges)  
var range1 = sheet.getRange("D3:D100").getValues();
var range2 = sheet.getRange("Q3:Q100").getValues();  

// merging the two single arrays into one 2d array (you can't have one single 
// 2d array from the start because the two columns are not adjacent I guess)
var range=[],i=-1;
while ( range1[++i] ) { 
  range.push( [ range1[i][0], range2[i][0] ] );
}

// I tried to come up with a global SUM but I don't know why it does not work
// var valore_glob = range2.reduce(function(acc, val) { return acc + val; }, 0);

// as much filters as given values in the validation drop-down list: each  
// filter returns only the correspoding values

// FILTRO BASE - keeps only B values
var filt_bas = range.filter(function (dataRow) {  return dataRow[0] ===  'b';});
// splitting the 2d array into two singles arrays, we keep only the second  
// one for the follwing SUM
var yArray_bas = filt_bas.map(function(tuple) {    return tuple[1];});  
// summing up all the values within the resulting array
var valore_bas = yArray_bas.reduce(function(acc, val) { return acc + val; }, 0);

// FILTRO MID - keeps only MID values 
var filt_mid = range.filter(function (dataRow) {  return dataRow[0] ===  'mid';});
// splitting the 2d array into two singles arrays, we keep only the second  
// one for the follwing SUM
var yArray_mid = filt_mid.map(function(tuple) {    return tuple[1];});  
// summing up all the values within the resulting array
var valore_mid = yArray_mid.reduce(function(acc, val) { return acc + val; }, 0);

// FILTRO PRO - keeps only PRO  values  
var filt_pro = range.filter(function (dataRow) {  return dataRow[0] ===  'pro';});
// splitting the 2d array into two singles arrays, we keep only the second  
// one for the follwing SUM
var yArray_pro = filt_pro.map(function(tuple) {    return tuple[1];});  
// summing up all the values within the resulting array
var valore_pro = yArray_pro.reduce(function(acc, val) { return acc + val; }, 0);  

// FILTRO TOP - keeps only TOP values 
var filt_top = range.filter(function (dataRow) {  return dataRow[0] ===  'top';});
// splitting the 2d array into two singles arrays, we keep only the second  
// one for the follwing SUM
var yArray_top = filt_top.map(function(tuple) {    return tuple[1];});  
// summing up all the values within the resulting array
var valore_top = yArray_top.reduce(function(acc, val) { return acc + val; }, 0);   

var selector = sheet.getRange("D2").getValue();

switch (selector) {
  default:
    cell.setValue(valore_bas);
    break;
  case 'mid':
    cell.setValue(valore_bas + valore_mid);
    break;
  case 'pro':
    cell.setValue(valore_bas + valore_mid + valore_pro);
    break;
  case 'top':
    cell.setValue(valore_bas + valore_mid + valore_pro + valore_top);
}

  }
}

欢迎提出建议,谢谢。

致谢:
Writing google Javascript similar to vlookup
Sum elements of an array with specific attribute
Spreadsheet Non-Adjacent Column data
How to find the sum of an array of numbers
How to filter an array of arrays?
Split a 2D array into single arrays

code.gs 中最新的实际工作代码: https://jsfiddle.net/John_Galassi/5ahrLmg9/

【问题讨论】:

  • 如果这是 Excel,我会看一个简单的 SUMIFS 函数,但我对 Google 表格一无所知
  • 为了稍微清理一下,如果你问我,我建议你使用箭头函数使这个(和其他例子)var filt_bas = range.filter(function (dataRow) { return dataRow[0] === 'b';}); 到这个var filt_bas = range.filter((dataRow) => dataRow[0] === 'b'); 更容易看到。
  • 我同意@HarassedDad,sumif 功能应该足够了吗?
  • @MauriceNino 我一开始确实尝试过,但在我看来这个符号在 GAS 上不起作用,你能确认一下吗?无论如何我会再试一次,谢谢
  • @HarassedDad,Casper 是的,可以在 excel 中工作,但我希望从代码端实现一些东西。谢谢你的回答

标签: javascript arrays database google-apps-script google-sheets


【解决方案1】:

使用你可以尝试的内置函数

=iferror(sumproduct(regexmatch(D3:D, "^("&vlookup(D2, {"b", "b"; "mid", "b|mid"; "pro", "b|mid|pro"; "top", "b|mid|pro|top"}, 2, 0)&")$"), Q3:Q))

或者,取决于您的语言环境

=iferror(sumproduct(regexmatch(D3:D; "^("&vlookup(D2; {"b"\ "b"; "mid"\ "b|mid"; "pro"\"b|mid|pro"; "top"\ "b|mid|pro|top"}; 2; 0)&")$"); Q3:Q))

或者,您可以在 google 脚本中创建自定义函数:

function sumOnCondition(filter, checkrange, sumrange) {
var arr, ind;
arr = ["b", "mid", "pro", "top"];
ind = arr.indexOf(filter);
arr = (filter === "top") ? arr : arr.slice(0, ind + 1);
return checkrange.map(function(r, i) {
    return arr.indexOf(r[0]) > -1 ? Number(sumrange[i]) : 0;
}).reduce(function(a, b) {
    return a + b;
})
}

并在电子表格中输入 G2

=sumOnCondition(D2, D3:D, Q3:Q)

或者,取决于您的语言环境

=sumOnCondition(D2; D3:D; Q3:Q)

看看有没有帮助?

【讨论】:

  • 我在这两种情况下都得到了一个错误。我得到“TypeError: Impossibile chiamare il metodo "map" di undefined. (riga 6, file "sum")"
  • 您能否分享一份您的电子表格副本,以便我仔细查看?
  • 是的,当然谢谢,让我准备一下,我会在原始问题的末尾发布一个链接。谢谢
  • 您好,您的语言环境需要使用分号作为参数分隔符。我已经更新了这两个公式并将它们输入到您的电子表格中(单元格 T2 和 U2)。看看它现在是否有效?
  • 谢谢你,它似乎工作。我仍然想提出几个问题,但它现在似乎有效。真的非常感谢,它真的比我以前的更苗条更优雅。我希望稍后我可以就其他问题向您提问。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-23
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
相关资源
最近更新 更多