我有自动计算每个项目损益的工作表。目前他们使用的是固定工资,但我想改变它,以纳入任何未来的工资变化。项目持续时间是从L1排序的,基于E2中的持续时间参数,使用=EDATE($C$2, SEQUENCE(1, $E$2, 0))
列L中的每个单元格按顺序遍历持续时间,计算相关值。
工资成本的公式引用下面的数据集,该数据集也是使用=FILTER(FILTER(AllStaffProjectAllocationTbl,AllStaffProjectAllocationTbl[Project Code Name]=B2), {1,0,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0})
从另一个工作表中的数据自动生成的,并且可以具有可变的条目数:
L7中计算工资成本的当前公式(来自第一张图片)是=MMULT(SEQUENCE(1,ROWS($A$18#),1,0),($L$1#>=OFFSET($A$18#,0,3,,1))*($L$1#<=OFFSET($A$18#,0,4,,1))*OFFSET($A$18#,0,5,,1))
,它使用了第二张图片中的F列(我希望删除它)。
我在表EmployeeSalaryTbl中得到了一组新的工资数据(为了确保下面的计算正常进行,我必须添加一个虚构的结束日期31/12/9999。理想情况下,这应该是空白的,我将在下面的计算中检查它):
我已经开始修改L7中的MMult函数,以执行以下操作:
1.项目工期顺序
1.检查从A18开始的员工是否参与了从L1开始的给定月份的项目
1.如果是,则从EmployeeSalaryTbl中查找日期范围内的薪金,并将该月的薪金相加。
这是我目前所拥有的,但不幸的是,它给了我一个错误:=MMULT(SEQUENCE(1,ROWS($A$18#),1,0),IF(AND(($L$1#>=OFFSET($A$18#,0,3,,1))*($L$1#<=OFFSET($A$18#,0,4,,1))),SUMIFS(EmployeeSalaryTbl[Salary Monthly], EmployeeSalaryTbl[Employee],$A$18#, EmployeeSalaryTbl[Salary Start Date],"<="&$L$1#, EmployeeSalaryTbl[Salary End Date],">="&$L$1#),0))
图2定义的项目数据为:
| 员工|角色|专业|开始日期|结束日期|月薪|
| - -|- -|- -|- -|- -|- -|
| 鲍勃|高级程序员|程序设计|2020年1月12日|2020年6月5日|4,333英镑|
| 戴夫|中级程控仪|程序设计|2020年2月1日|2020年5月30日|3,167英镑|
| 彼得|高级程序员|程序设计|2020年1月1日|2020年1月31日|4,583英镑|
| 杰克|初级程序员|程序设计|2020年2月1日|2020年6月30日|2,083英镑|
| 理查德德|资深艺术家|艺术|2020年3月1日|2020年4月30日|3,750英镑|
| 罗德尼|QA负责人|质量保证部|2020年3月1日|2020年6月30日|4,333英镑|
| 项目1 -聘用1|高级制片人|生产部|2020年2月1日|2020年5月30日|3,458英镑|
| 罗杰|质量保证部|质量保证部|2020年1月1日|2020年4月30日|1,667英镑|
| 韦斯利|中级程控仪|程序设计|2020年2月1日|2020年5月31日|3,750英镑|
| 拉结|资深艺术家|艺术|2020年1月1日|2020年6月30日|3,333英镑|
| 项目1 -聘用2|首席程序员|程序设计|2020年1月1日|2020年7月31日|4,417英镑|
EmployeeSalaryTbl中的数据为:
| 员工|薪资起始日期|薪资终止日期|薪资|月薪|每日薪金|
| - -|- -|- -|- -|- -|- -|
| 鲍勃|2020年1月1日|2021年3月31日|5.2万英镑|4,333英镑|199英镑|
| 鲍勃|2021年4月1日|2022年3月31日|5万5千英镑|4,583英镑|211英镑|
| 鲍勃|2022年4月1日|九九年十二月三十一日|5万8千英镑|4,833英镑|222英镑|
| 戴夫|2020年1月1日|2021年3月31日|3.8万英镑|3,167英镑|146英镑|
| 戴夫|2021年4月1日|九九年十二月三十一日|4.2万英镑|3,500英镑|161英镑|
| 韦斯利|2020年1月1日|九九年十二月三十一日|4.5万英镑|3,750英镑|173英镑|
| 杰克|2020年1月1日|九九年十二月三十一日|2.5万英镑|2,083英镑|96英镑|
| 理查德德|2020年1月1日|九九年十二月三十一日|4.5万英镑|3,750英镑|173英镑|
| 罗德尼|2020年1月1日|九九年十二月三十一日|5.2万英镑|4,333英镑|199英镑|
| 项目1 -聘用1| 2020年1月1日|九九年十二月三十一日|4.15万英镑|3,458英镑|159英镑|
| 罗杰|2020年1月1日|九九年十二月三十一日|2万英镑|1,667英镑|77英镑|
| 史提|2020年1月1日|九九年十二月三十一日|2.7万英镑|2,250英镑|104英镑|
| 拉结|2020年1月1日|九九年十二月三十一日|4万英镑|3,333英镑|153英镑|
| 彼得|2020年1月1日|九九年十二月三十一日|3.4万英镑|2,833英镑|130英镑|
| 萨拉|2020年1月1日|九九年十二月三十一日|2.2万英镑|1,833英镑|84英镑|
| 克洛伊|2020年1月1日|九九年十二月三十一日|3.3万英镑|2,750英镑|127英镑|
| 马修|2020年1月1日|2021年3月31日|2.3万英镑|1,917英镑|88英镑|
| 马修|2021年4月1日|九九年十二月三十一日|2.8万英镑|2,333英镑|107英镑|
| 项目1 -聘用2| 2020年1月1日|九九年十二月三十一日|3.6万英镑|3,000英镑|138英镑|
1条答案
按热度按时间oxcyiej71#
使用您输入的数据,并假设没有Excel版本限制(未在问题中指定),在单元格
H2
中输入以下公式:两个 *Excel表 * 被定义为具有动态范围:项目信息
TB_Prj
,薪资信息TB_Roster
,在H1
中横向生成月份信息如下:它会产生月份的第一天。在公式中表示为
SOMs
(月的开始)。类似地,我使用EOMs
来表示每个相应的月的结束。输出结果会产生
1x12
数组。输出如下:
仅显示部分薪金表(
TB_Roster
)备注:
请检查结果,您的数据需要清理,例如,薪金表中的Peter有两个日期间隔重叠的条目。
如果您无法使用表格(例如,输入基于SPILL公式,如
FILTER
),则可以使用范围。您可以定义以下两个数据集范围:prjSet
、rosterSet
,然后定义每个Map的数据行,如下所示:INDEX(rng,,x)
,其中x
表示每个范围中的相应列号,其中rng
为prjSet
或rosterSet
。例如,name
变量可以如下定义:说明
使用 *Excel表格 * 使其具有动态范围,因此在添加附加信息时不需要更改公式。我们使用
LET
函数使公式更易于维护,定义所需的输入和中间结果。BYCOL
用于迭代所有SOMs
值。对于每个月初(SOM
),我们执行以下操作:从活动项目中查找
namesActive
,检查项目的开始时间是否早于或等于SOM
,项目的结束时间是否大于或等于EOM
。如果项目表中没有满足条件的名称,FILTER
返回错误(#CALC!
),因为Excel中不允许使用空数组。如果要处理这种情况,则需要调整公式(使用FILTER
和IF
的第三个输入参数条件来计算cost
)或更好地清理数据。我不会期望在一个给定的月份没有任何活动的项目在公司层面。有了姓名列表后,我们转到第二个Excel表(
TB_Roster
),根据start
、end
日期查找有效薪金。我们在
end
中处理空值,假设如果没有值(数据被格式化为日期,所以空表示0
)。下面的IF
条件确保它(在第二个FILTER
调用中):所以如果
end
数组为正(日期表示为从0
开始的正整数,即 * 整数 *),然后分配一个值,因此我们使用该值,否则(0
)将替换为EOM
。如果没有结束日期,则条件 * 始终为真 *(所有end
值都考虑在内)。IF
使用数组,它计算数组中每个元素的条件,并返回每个元素的相应值。通过这样做,我们将空值的情况固定为有效的情况,因此 * 不需要使用虚构的日期 *。与
XMATCH
相关的条件可确保我们仅根据上一次FILTER
调用中的名称(项目表中的有效名称,即namesActive
)筛选name
。此筛选器的结果(cost
)满足所有条件,并返回所有匹配的月薪。如果根据过滤条件没有匹配,我们返回
0
(但是可以使用其他值,例如NA()
)。为了做到这一点,我们使用FILTER
函数的第三个输入参数。最后,我们将所有符合条件的薪资加总。
附加:检查间隔一致性
根据问题的答案:我提供的Excel: #CALC! error (Nested Array) when using MAP functions for counting interval overlaps,它可以用来检查日期间隔是否不正确(结束日期在开始日期之前),或者薪资表的间隔是否重叠:
输出将是输入数据: