我有这个怪异的问题让我大吃一惊。
考虑以下电子表格结构:
| A B C D E
----------------------------------------------------------------------
1 | The awsome project of Foo
2 |
3 | Pri Type Issue Estim Subject
4 |
5 | 1 Story FA-133 The great UI feature
6 | FA-134 5 Do some work
7 | FA-135 2 Document the work
8 | Bug FA-137 1 Fix the misplaced pixel
9 | FA-136 2 Regression test
10|
11| 2 Story FA-153 The awsome BL computation
12| FA-154 5 Do some work
13| FA-155 2 Document the work
14| Bug FA-157 1 Fix the precision trancation error
15| Bug FA-129 1 Fix the wrong error code
16| FA-156 2 Regression test
Pri =优先级, Estim =估算
嗯,还有技能类型,但让我们保持简单,对吧......
现在,故事是什么?究竟。我们正在寻找这个故事。
对于不是故事(并且不为空)的每条记录,我需要提取第一个主题和优先级 故事记录在它上面。
我们如何在电子表格中执行此操作?
我正在努力帮助我的scrum-master,他现在正在使用电子表格与我们的客户沟通,以进行美容和计划会议。
现在,在每个sprint开始时,一旦范围关闭,他会手动将所有任务行(非 Story )复制到备忘录纸币并把它们放在板上。 到目前为止 - 很棒。我们喜欢scrum。
但是:我想自动打印这些笔记。和duhhh一样,我们在2013年...... 为此,我需要一个CSV或TSV字符串,其中包含相关记录的值,因此我可以制定并打印它们。
现在,假设我想在每个任务的记录上计算一个故事名称的列,该任务说明问题任务的故事是什么,这个故事的优先级是什么,我该怎么做在我们的谷歌电子表格?
如果你跳过诸如“拖动优先级以填充故事中的每个任务”的建议,或者“为故事主题添加一个简单的列并手动填写”,我会感谢你。
首先 - 我们的客户喜欢这个电子表格清晰可读,没有重复信息,我们尽力满足他的需求。所以 - 隐藏的列是答案的一半。不是全部。
第二 - 在规划任务在优先级发生变化时在故事之间移动,因此感到不舒服。
想法是自动化平凡的工作,而不是为计算机工作......
如果我可以使用公式计算这些值 - 那就太棒了
答案 0 :(得分:1)
所以,我花了很多时间来做这件事,但终于找到了一个有效的解决方案 - 尽管不是最漂亮的解决方案。
我已经创建了一个电子表格:https://docs.google.com/spreadsheets/d/13KdxYCvNHekAd3pXOhHftSzAzMXS9HqoOCtFoxXocCM/edit?usp=sharing - 看看它,我试图尽可能接近模拟情况。我将尝试解释我搞砸了什么:)
首先,我添加了两列(F,G),我们将在那里计算结果。关键功能非常难看,让我们通过一个例子来看一下 - 让我们仔细看看F15,你可以在其中找到以下功能:
=if(and(B15<>"",B15<>"Story"),index(A:E,row(B15)+MAX(arrayformula(if((arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15))>0,-99999999,arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15)))),1),"")
我承认,非常难看,但也许我可以解释一下。 (另外,在电子表格中我添加了一些额外的列,H到L,我在其中逐步解释我使用的函数 - 请参阅下面的编号列表)
首先,我们做一个快速条件(IF)并检查问题的类型不应为空或故事:if(and(B15<>"",B15<>"Story")
- 如果那是真的,我们会做一些魔术(稍后解释),如果为FALSE,我们在这个单元格中写了一个空字符串 - ),"")
- 在这个丑陋的大函数的最后。
现在,魔法来了。逻辑上它看起来像:
在丑陋的函数中,以下代码片段代表上述逻辑:
filter(C:C,B:B="Story")
- 一个简单的过滤器,可以找到故事类型问题的所有问题编号arrayformula(match(filter(C:C,B:B="Story"),C:C,0))
- 这将为每个问题编号找到确切的行号。arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15)))
- 一个简单的减法将告诉我们行中这些行的“距离”。但是,我们应该在这里做一个小技巧,因为如果这些结果是积极的,那就意味着在我们的行之后有之后的。但是我们不想考虑这些因素,因此会出现一个IF,它确保在这些情况下不会选择这些选项:
if((arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15))>0,-99999999,arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15))))
MAX(arrayformula(if((arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15))>0,-99999999,arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15))))
- 我们正在选择最接近的选项。 (MAX功能将选择最接近的负数为零)index(A:E,row(B15)+MAX(arrayformula(if((arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15))>0,-99999999,arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15)))),1)
- 最后,我们使用INDEX函数导航到该行。第一个参数是范围,第二个参数是我们在前面的步骤中计算的行(魔术),最后一个参数(1)是列号。由于我们需要优先权,因此将其设置为1。限制:该功能假设每个故事都有一个问题编号。
我希望它有所帮助。
更新:
如果您想计算所有非故事但有问题编号的行,请更改以下函数:
=if(and(C15<>"",B15<>"Story"),index(A:E,row(B15)+MAX(arrayformula(if((arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15))>0,-99999999,arrayformula(match(filter(C:C,B:B="Story"),C:C,0))-row(B15)))),1),"")
(只有第一个条件改变了:B15到C15)