这应该是 SUMIF 公式吗?
Should this be a SUMIF formula?
我正在尝试创建一个可以在列 A 中识别名称 Brooke B
的公式,例如,从那里我想对列 I Cash Discounts
中列出的值求和该特定用户。
(是的,此用户没有现金折扣,因此第 I 栏说明 "Non-Cash Payment")。
这里总共有大约 80 个用户,所以我更愿意在 A 列中自动识别姓名。
Sheet: https://docs.google.com/spreadsheets/d/1xzzHT7VjG24UJ4ZXaiZWsfzroTpn7jCJLexuTOf6SQs/edit?usp=sharing
Cash Discounts
sheet 中列出的所需结果,在 C 列中按用户列出。
您正在尝试计算给予列表中的人的每人现金折扣总额。您有从 POS 系统导出的数据,您已在其中添加了一个公式来逐行计算折扣金额。您推测是否可以使用 SUMIFS
公式计算折扣总额。
在我看来,尽管 Google sheet 的功能(尽管,毫无疑问,比我更有本事的人会反驳这个理论)。 A 列包含名称,还包括子分组(及其小计)以及交易日期。有 83 个独特的人和超过 31,900 条交易行。
此答案是一个基于脚本的解决方案,它使用折扣总计的名称和值更新 sheet。经过的执行时间是@11 秒。
function so5882893202() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get the Discounts sheet
var discsheetname = "Discounts";
var disc = ss.getSheetByName(discsheetname);
//get the Discounts data
var discStartrow = 3;
var discLR = disc.getLastRow();
var discRange = disc.getRange(discStartrow, 1, discLR-discStartrow+1, 9);
var discValues = discRange.getValues();
// isolate Column A
var discnameCol = discValues.map(function(e){return e[0];});//[[e],[e],[e]]=>[e,e,e]
//Logger.log(discnameCol); // DEBUG
// isolate Column I
var discDiscounts = discValues.map(function(e){return e[8];});//[[e],[e],[e]]=>[e,e,e]
//Logger.log(discDiscounts); // DEBUG
// create an array to build a names list
var names =[]
// get the number of rows on the Discounts sheet
var discNumrows = discLR-discStartrow+1;
// Logger.log("DEBUG: number of rows = "+discNumrows);
// identify search terms
var searchPercent = "%";
var searchTotal = "Total";
// loop through Column A
for (var i=0; i<discNumrows; i++){
//Logger.log("DEBUG: i="+i+", content = "+discnameCol[i]);
// test if value is a date
if (Object.prototype.toString.call(discnameCol[i]) != "[object Date]") {
//Logger.log("it isn't a date")
// test whether the value contains a % sign
if ( discnameCol[i].indexOf(searchPercent) === -1){
//Logger.log("it doesn't have a % character in the content");
// test whether the value contains the word Total
if ( discnameCol[i].indexOf(searchTotal) === -1){
//Logger.log("it doesn't have the word total in the content");
// test whether the value is a blank
if (discnameCol[i] != ""){
//Logger.log("it isn't empty");
// this is a name; add it to the list
names.push(discnameCol[i])
}// end test for empty
}// end test for Total
} // end for percentage
} // end test for date
}// end for
//Logger.log(names);
// get the number of names
var numnames = names.length;
//Logger.log("DEBUG: number of names = "+numnames)
// create an array for the discount details
var discounts=[];
// loop through the names
for (var i=0;i<numnames;i++){
// Logger.log("DEBUG: name = "+names[i]);
// get the first row and last rows for this name
var startrow = discnameCol.indexOf(names[i]);
var endrow = discnameCol.lastIndexOf(names[i]+" Total:");
var x = 0;
var value = 0;
// Logger.log("name = "+names[i]+", start row ="+ startrow+", end row = "+endrow);
// loop through the Cash Discounts Column (Column I) for this name
// from the start row to the end row
for (var r = startrow; r<endrow;r++){
// get the vaue of the cell
value = discDiscounts[r];
// test that it is a value
if (!isNaN(value)){
// increment x by the value
x = +x+value;
// Logger.log("DEBUG: r = "+r+", value = "+value+", x = "+x);
}
}
// push the name and the total discount onto the array
discounts.push([names[i],x]);
}
//Logger.log(discounts)
// get the reporting sheet
var reportsheet = "Sheet10";
var report = ss.getSheetByName(reportsheet);
// define the range (allow row 1 for headers)
var reportRange = report.getRange(2,1,numnames,2);
// clear any existing content
reportRange.clearContent();
//update the values
reportRange.setValues(discounts);
}
报告 Sheet - 摘录
并不是每个人都希望通过脚本解决他们的问题。该答案试图使用常见的 garden-variety formula/functions.
提供 可重复 解决方案
如其他地方所述,传播的布局sheet 不适合 quick/simple 解决方案,但可以分解数据以编译 non-script 答案.虽然它可能 "seem" 好像下面的公式不够“简单,但当采用时 one-at-a-time 它们是合乎逻辑的,非常容易创建,并且非常容易验证成功的结果。
注意:一开始就知道第一行数据=行#3,最后一行数据=行#31916。
步骤#1 - 从 ColumnA
中获取 Text
个值
- 在单元格 J3 中输入此公式,并复制到第 31916 行
=if(isdate(A3),"",A3)
:
- 评估A列,如果内容是日期,returns空白,否则returns上下文
- 以客户"AJ"为例,此时的内容包括:
- AJ
- 10% BuildingDiscount
- 10% BuildingDiscount Total:
- Northwestern 10%
- Northwestern 10% Total:
- AJ Total:
Step#2 - 忽略包含“10%”的值(这会删除标题和 sub-subtotals
- 在单元格 K3 中输入此公式并复制到第 31916 行
=iferror(if(search("10%",J3)>0,"",J3),J3)
:在 J 列中搜索“10%”。Returns 除包含“10%”的值之外的所有值。
- 以客户"AJ"为例,此时的内容包括:
- AJ
- AJ Total:
**Step#3 - 忽略包含单词 "Total"
的值
- 在单元格 L3 中输入此公式并复制到第 31916 行。
=iferror(if(search("total",K3)>0,"",K3),K3)
- 以客户"AJ"为例,此时的内容包括:
- AJ
步骤#3 后的结果
您可能会想,“这不能用一个公式完成吗?” and/or “数组公式会更有效”。这两种想法都是正确的,但我们正在寻找简单易行的方法,而单个公式并不简单(如下所示);鉴于此,数组公式是 out-of-the-question unless/until 专家可以在数据上挥舞魔杖。
FWIW - 合并步骤#1、2 和 3
- 步骤#1、2 和 3 中的每一个都相互依存。因此,可以创建一个结合这些步骤的单一公式。
- 在单元格 J3 中输入此公式,然后复制到行 #31916。
=iferror(if(search("total",iferror(if(search("10%",if(isdate(A3),"",A3))>0,"",if(isdate(A3),"",A3)),if(isdate(A3),"",A3)))>0,"",iferror(if(search("10%",if(isdate(A3),"",A3))>0,"",if(isdate(A3),"",A3)),if(isdate(A3),"",A3))),iferror(if(search("10%",if(isdate(A3),"",A3))>0,"",if(isdate(A3),"",A3)),if(isdate(A3),"",A3)))
如图所示,第 3 步以 L 列中的主要空单元格结束;唯一填充的单元格是客户名称在交易开始时的第一个实例 - 例如本例中的 "Alec"。但是(@Rubén 的支持)可以填充 L 列中的空白事务单元格。Webapps 上的 An arrayformula to find the previous non-empty cell in another column 解释了如何。
步骤#4 - 为每个交易行创建一个客户名称。
- 在单元格 M3 中输入此公式,它会自动将单元格填充到行#31916
=ArrayFormula(vlookup(ROW(3:31916),{IF(LEN(L3:L31916)>0,ROW(3:31916),""),L3:L31916},2))
步骤#5 - 获取每笔交易金额的折扣金额
- 折扣值已经显示在第 I 列中。它们与文本值穿插在一起,因此通过测试 D 列中的值来测试这是否是总行的公式;只有当有一个值(产品项目)时,公式才会测试第 I 列中是否有一个值。
- 在单元格N3中输入这个公式,它会自动将单元格填充到行#31916
=ArrayFormula(if(len(D3:D31914)>0,if(ISNUMBER(I3:I31916),I3:I31916,0),""))
步骤#5 后的屏幕截图
按查询报告
报告是通过查询完成的。这些可以放在任何地方,但将它放在单独的 sheet.
上可能更方便
步骤#6.1 - 查询结果以创建显示所有客户总数的报告
=query(Discounts_analysis!$M:$N916,"select M, sum(N) where N is not null group by M label M 'Customer', sum(N) 'Total Discount' ",1)
步骤 #6.2 - 查询结果以创建按客户显示总计的报告 客户收到折扣的地方
=query(Discounts_analysis!$M:$N916,"select M, sum(N) where N >0 group by M label M 'Customer', sum(N) 'Total Discount' ",1)
步骤#6.3 - 查询结果以创建显示没有折扣的客户的报告
- `=query(query(Discounts_analysis!$M:$N916,"select M, sum(N) where N is not null group by M label M 'Customer', sum(N) 'Total Discount' ",1),"select Col1 where Col2=0")`
查询截图
我正在尝试创建一个可以在列 A 中识别名称 Brooke B
的公式,例如,从那里我想对列 I Cash Discounts
中列出的值求和该特定用户。
(是的,此用户没有现金折扣,因此第 I 栏说明 "Non-Cash Payment")。
这里总共有大约 80 个用户,所以我更愿意在 A 列中自动识别姓名。 Sheet: https://docs.google.com/spreadsheets/d/1xzzHT7VjG24UJ4ZXaiZWsfzroTpn7jCJLexuTOf6SQs/edit?usp=sharing
Cash Discounts
sheet 中列出的所需结果,在 C 列中按用户列出。
您正在尝试计算给予列表中的人的每人现金折扣总额。您有从 POS 系统导出的数据,您已在其中添加了一个公式来逐行计算折扣金额。您推测是否可以使用 SUMIFS
公式计算折扣总额。
在我看来,尽管 Google sheet 的功能(尽管,毫无疑问,比我更有本事的人会反驳这个理论)。 A 列包含名称,还包括子分组(及其小计)以及交易日期。有 83 个独特的人和超过 31,900 条交易行。
此答案是一个基于脚本的解决方案,它使用折扣总计的名称和值更新 sheet。经过的执行时间是@11 秒。
function so5882893202() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get the Discounts sheet
var discsheetname = "Discounts";
var disc = ss.getSheetByName(discsheetname);
//get the Discounts data
var discStartrow = 3;
var discLR = disc.getLastRow();
var discRange = disc.getRange(discStartrow, 1, discLR-discStartrow+1, 9);
var discValues = discRange.getValues();
// isolate Column A
var discnameCol = discValues.map(function(e){return e[0];});//[[e],[e],[e]]=>[e,e,e]
//Logger.log(discnameCol); // DEBUG
// isolate Column I
var discDiscounts = discValues.map(function(e){return e[8];});//[[e],[e],[e]]=>[e,e,e]
//Logger.log(discDiscounts); // DEBUG
// create an array to build a names list
var names =[]
// get the number of rows on the Discounts sheet
var discNumrows = discLR-discStartrow+1;
// Logger.log("DEBUG: number of rows = "+discNumrows);
// identify search terms
var searchPercent = "%";
var searchTotal = "Total";
// loop through Column A
for (var i=0; i<discNumrows; i++){
//Logger.log("DEBUG: i="+i+", content = "+discnameCol[i]);
// test if value is a date
if (Object.prototype.toString.call(discnameCol[i]) != "[object Date]") {
//Logger.log("it isn't a date")
// test whether the value contains a % sign
if ( discnameCol[i].indexOf(searchPercent) === -1){
//Logger.log("it doesn't have a % character in the content");
// test whether the value contains the word Total
if ( discnameCol[i].indexOf(searchTotal) === -1){
//Logger.log("it doesn't have the word total in the content");
// test whether the value is a blank
if (discnameCol[i] != ""){
//Logger.log("it isn't empty");
// this is a name; add it to the list
names.push(discnameCol[i])
}// end test for empty
}// end test for Total
} // end for percentage
} // end test for date
}// end for
//Logger.log(names);
// get the number of names
var numnames = names.length;
//Logger.log("DEBUG: number of names = "+numnames)
// create an array for the discount details
var discounts=[];
// loop through the names
for (var i=0;i<numnames;i++){
// Logger.log("DEBUG: name = "+names[i]);
// get the first row and last rows for this name
var startrow = discnameCol.indexOf(names[i]);
var endrow = discnameCol.lastIndexOf(names[i]+" Total:");
var x = 0;
var value = 0;
// Logger.log("name = "+names[i]+", start row ="+ startrow+", end row = "+endrow);
// loop through the Cash Discounts Column (Column I) for this name
// from the start row to the end row
for (var r = startrow; r<endrow;r++){
// get the vaue of the cell
value = discDiscounts[r];
// test that it is a value
if (!isNaN(value)){
// increment x by the value
x = +x+value;
// Logger.log("DEBUG: r = "+r+", value = "+value+", x = "+x);
}
}
// push the name and the total discount onto the array
discounts.push([names[i],x]);
}
//Logger.log(discounts)
// get the reporting sheet
var reportsheet = "Sheet10";
var report = ss.getSheetByName(reportsheet);
// define the range (allow row 1 for headers)
var reportRange = report.getRange(2,1,numnames,2);
// clear any existing content
reportRange.clearContent();
//update the values
reportRange.setValues(discounts);
}
报告 Sheet - 摘录
并不是每个人都希望通过脚本解决他们的问题。该答案试图使用常见的 garden-variety formula/functions.
提供 可重复 解决方案如其他地方所述,传播的布局sheet 不适合 quick/simple 解决方案,但可以分解数据以编译 non-script 答案.虽然它可能 "seem" 好像下面的公式不够“简单,但当采用时 one-at-a-time 它们是合乎逻辑的,非常容易创建,并且非常容易验证成功的结果。
注意:一开始就知道第一行数据=行#3,最后一行数据=行#31916。
步骤#1 - 从 ColumnA
中获取Text
个值
- 在单元格 J3 中输入此公式,并复制到第 31916 行
=if(isdate(A3),"",A3)
:- 评估A列,如果内容是日期,returns空白,否则returns上下文
- 以客户"AJ"为例,此时的内容包括:
- AJ
- 10% BuildingDiscount
- 10% BuildingDiscount Total:
- Northwestern 10%
- Northwestern 10% Total:
- AJ Total:
Step#2 - 忽略包含“10%”的值(这会删除标题和 sub-subtotals
- 在单元格 K3 中输入此公式并复制到第 31916 行
=iferror(if(search("10%",J3)>0,"",J3),J3)
:在 J 列中搜索“10%”。Returns 除包含“10%”的值之外的所有值。- 以客户"AJ"为例,此时的内容包括:
- AJ
- AJ Total:
**Step#3 - 忽略包含单词 "Total"
的值- 在单元格 L3 中输入此公式并复制到第 31916 行。
=iferror(if(search("total",K3)>0,"",K3),K3)
- 以客户"AJ"为例,此时的内容包括:
- AJ
步骤#3 后的结果
您可能会想,“这不能用一个公式完成吗?” and/or “数组公式会更有效”。这两种想法都是正确的,但我们正在寻找简单易行的方法,而单个公式并不简单(如下所示);鉴于此,数组公式是 out-of-the-question unless/until 专家可以在数据上挥舞魔杖。
FWIW - 合并步骤#1、2 和 3
- 步骤#1、2 和 3 中的每一个都相互依存。因此,可以创建一个结合这些步骤的单一公式。
- 在单元格 J3 中输入此公式,然后复制到行 #31916。
=iferror(if(search("total",iferror(if(search("10%",if(isdate(A3),"",A3))>0,"",if(isdate(A3),"",A3)),if(isdate(A3),"",A3)))>0,"",iferror(if(search("10%",if(isdate(A3),"",A3))>0,"",if(isdate(A3),"",A3)),if(isdate(A3),"",A3))),iferror(if(search("10%",if(isdate(A3),"",A3))>0,"",if(isdate(A3),"",A3)),if(isdate(A3),"",A3)))
如图所示,第 3 步以 L 列中的主要空单元格结束;唯一填充的单元格是客户名称在交易开始时的第一个实例 - 例如本例中的 "Alec"。但是(@Rubén 的支持)可以填充 L 列中的空白事务单元格。Webapps 上的 An arrayformula to find the previous non-empty cell in another column 解释了如何。
步骤#4 - 为每个交易行创建一个客户名称。
- 在单元格 M3 中输入此公式,它会自动将单元格填充到行#31916
=ArrayFormula(vlookup(ROW(3:31916),{IF(LEN(L3:L31916)>0,ROW(3:31916),""),L3:L31916},2))
步骤#5 - 获取每笔交易金额的折扣金额
- 折扣值已经显示在第 I 列中。它们与文本值穿插在一起,因此通过测试 D 列中的值来测试这是否是总行的公式;只有当有一个值(产品项目)时,公式才会测试第 I 列中是否有一个值。
- 在单元格N3中输入这个公式,它会自动将单元格填充到行#31916
=ArrayFormula(if(len(D3:D31914)>0,if(ISNUMBER(I3:I31916),I3:I31916,0),""))
- 在单元格N3中输入这个公式,它会自动将单元格填充到行#31916
步骤#5 后的屏幕截图
按查询报告
报告是通过查询完成的。这些可以放在任何地方,但将它放在单独的 sheet.
上可能更方便步骤#6.1 - 查询结果以创建显示所有客户总数的报告
=query(Discounts_analysis!$M:$N916,"select M, sum(N) where N is not null group by M label M 'Customer', sum(N) 'Total Discount' ",1)
步骤 #6.2 - 查询结果以创建按客户显示总计的报告 客户收到折扣的地方
=query(Discounts_analysis!$M:$N916,"select M, sum(N) where N >0 group by M label M 'Customer', sum(N) 'Total Discount' ",1)
步骤#6.3 - 查询结果以创建显示没有折扣的客户的报告
- `=query(query(Discounts_analysis!$M:$N916,"select M, sum(N) where N is not null group by M label M 'Customer', sum(N) 'Total Discount' ",1),"select Col1 where Col2=0")`
查询截图