从日期范围计算特定月份的天数。 Google 张
Counting the number of days in specific months from date range. Google sheets
我正在尝试制作一个 google sheet,它将自动计算设备每月维修的天数。
我需要它来计算列中的日期并 post 不同列行中的结果,因为会有一个列表,该列表将不断有新条目
例如:
Device| start date | end date.
Laptop| 8/29/2021 | 9/10/2021. 2 days in August, 10 days in September
第 1 个月的第 2 列第 1 列和第 2 个月的第 2 列中的预期结果
我找到了这个公式:
=ArrayFormula(query({EOMONTH(row(indirect("A"&A2):indirect("A"&B2)),0),row(indirect("A"&A2):indirect("A"&B2))},"Select Col1,Count(Col2) group by Col1 label Col1 'Month', count(Col2)'Days in Month' format Col1 'MMMM-YYYY' "))
但我不能在列表中使用它 sheet。任何想法将不胜感激
也许最简单的方法是使用 sequence()
枚举日期,仅使用 text()
将它们格式化为月份名称,然后使用 query()
聚合数据,然后使用一些字符串操作将数据拆分为列,如下所示:
=arrayformula(
if(
isdate(B2) * isdate(C2),
split(
regexreplace(
join(
"",
flatten(
query(
" days in " & text(sequence(C2 - B2 + 1, 1, B2), "mmµmmmm→"),
"select count(Col1), Col1 group by Col1 label count(Col1) '' ",
0
)
)
),
"\d+µ", ""
),
"→"
),
iferror(1/0)
)
)
此公式将处理跨越多个月的日期,给出与期间中的月份一样多的列。
如果每个月可以有一个公式,那么这个就可以了。
您的用例只调用了两个月。如果维修可以跨越 3 个月,您希望如何显示?
第一个输出列
在您的示例中,B 列是开始日期,D 列是输出:
=ARRAYFORMULA(
IF(Month(B2:B) = Month(C2:C),
C2:C - B2:B + 1
& IF(C2:C - B2:B +1 = 1, " day in ", " days in ")
& Text(B2:B, "mmmm"),
EOMONTH(B2:B, 0)-B2:B + 1
& IF(EOMONTH(B2:B, 0)-B2:B+1 = 1, " day in ", " days in ")
& Text(B2:B, "mmmm")
)
)
说明 - 首先我们检查开始日期和结束日期是否在同一个月。如果是,则为差值 + 1、您的文本和月份的串联,如下所示。
EOMONTH()
为您提供所选月份的最后一天。因此,这可以通过获取月份的最后一天,减去开始日期得到该月的天数来实现。
要获取月份的文本字值,请使用 TEXT()
函数将数据转换为月份。 'mmmm' 给出八月,'mmm' 给出八月,'mm' returns 给出月份。
中间的 if 语句纠正了 1 天和 3 天的语法差异。
然后将它们与 'days in' 文本连接在一起,并将其包装在 ARRAYFORMULA()
.
中
第二个输出列
与第一个类似,但数学有点不同。
=Arrayformula(
IF(Month(B2:B) = Month(C2:C),
"",
Text(C2:C, "dd")
& IF( Text(C2:C, "dd") = 1, " day in ", " days in ")
& Text(C2:C, "mmmm")
)
)
解释 - 首先我们检查开始和结束是否在同一个月,如果是,那么这个月是空白的。如果您希望有 0 天,您可以调整以显示这一点。
在这里你可以得到这个月的天数。由于九月的天数等于日期。因此,您使用 TEXT() 和 'dd' 获取月数,并将其与您的文本和月份的文本值连接起来。
尝试:
=ARRAYFORMULA(SPLIT(FLATTEN(QUERY(TRANSPOSE(QUERY(QUERY(IFERROR(SPLIT(FLATTEN(IF((A1:A="")+(B1:B=""),,
IF(C1:C-B1:B>=SEQUENCE(1, MAX(C1:C-B1:B), ),
ROW(A1:A)&"×"&TEXT((B1:B)+SEQUENCE(1, MAX(C1:C-B1:B), ), "mm"), ))), "×")),
"select count(Col1) where Col2 is not null group by Col1 pivot Col2"), "offset 1", 0)),,9^9)), " "))
demo spreadsheet
我正在尝试制作一个 google sheet,它将自动计算设备每月维修的天数。
我需要它来计算列中的日期并 post 不同列行中的结果,因为会有一个列表,该列表将不断有新条目
例如:
Device| start date | end date.
Laptop| 8/29/2021 | 9/10/2021. 2 days in August, 10 days in September
第 1 个月的第 2 列第 1 列和第 2 个月的第 2 列中的预期结果
我找到了这个公式:
=ArrayFormula(query({EOMONTH(row(indirect("A"&A2):indirect("A"&B2)),0),row(indirect("A"&A2):indirect("A"&B2))},"Select Col1,Count(Col2) group by Col1 label Col1 'Month', count(Col2)'Days in Month' format Col1 'MMMM-YYYY' "))
但我不能在列表中使用它 sheet。任何想法将不胜感激
也许最简单的方法是使用 sequence()
枚举日期,仅使用 text()
将它们格式化为月份名称,然后使用 query()
聚合数据,然后使用一些字符串操作将数据拆分为列,如下所示:
=arrayformula(
if(
isdate(B2) * isdate(C2),
split(
regexreplace(
join(
"",
flatten(
query(
" days in " & text(sequence(C2 - B2 + 1, 1, B2), "mmµmmmm→"),
"select count(Col1), Col1 group by Col1 label count(Col1) '' ",
0
)
)
),
"\d+µ", ""
),
"→"
),
iferror(1/0)
)
)
此公式将处理跨越多个月的日期,给出与期间中的月份一样多的列。
如果每个月可以有一个公式,那么这个就可以了。
您的用例只调用了两个月。如果维修可以跨越 3 个月,您希望如何显示?
第一个输出列
在您的示例中,B 列是开始日期,D 列是输出:
=ARRAYFORMULA(
IF(Month(B2:B) = Month(C2:C),
C2:C - B2:B + 1
& IF(C2:C - B2:B +1 = 1, " day in ", " days in ")
& Text(B2:B, "mmmm"),
EOMONTH(B2:B, 0)-B2:B + 1
& IF(EOMONTH(B2:B, 0)-B2:B+1 = 1, " day in ", " days in ")
& Text(B2:B, "mmmm")
)
)
说明 - 首先我们检查开始日期和结束日期是否在同一个月。如果是,则为差值 + 1、您的文本和月份的串联,如下所示。
EOMONTH()
为您提供所选月份的最后一天。因此,这可以通过获取月份的最后一天,减去开始日期得到该月的天数来实现。
要获取月份的文本字值,请使用 TEXT()
函数将数据转换为月份。 'mmmm' 给出八月,'mmm' 给出八月,'mm' returns 给出月份。
中间的 if 语句纠正了 1 天和 3 天的语法差异。
然后将它们与 'days in' 文本连接在一起,并将其包装在 ARRAYFORMULA()
.
第二个输出列
与第一个类似,但数学有点不同。
=Arrayformula(
IF(Month(B2:B) = Month(C2:C),
"",
Text(C2:C, "dd")
& IF( Text(C2:C, "dd") = 1, " day in ", " days in ")
& Text(C2:C, "mmmm")
)
)
解释 - 首先我们检查开始和结束是否在同一个月,如果是,那么这个月是空白的。如果您希望有 0 天,您可以调整以显示这一点。
在这里你可以得到这个月的天数。由于九月的天数等于日期。因此,您使用 TEXT() 和 'dd' 获取月数,并将其与您的文本和月份的文本值连接起来。
尝试:
=ARRAYFORMULA(SPLIT(FLATTEN(QUERY(TRANSPOSE(QUERY(QUERY(IFERROR(SPLIT(FLATTEN(IF((A1:A="")+(B1:B=""),,
IF(C1:C-B1:B>=SEQUENCE(1, MAX(C1:C-B1:B), ),
ROW(A1:A)&"×"&TEXT((B1:B)+SEQUENCE(1, MAX(C1:C-B1:B), ), "mm"), ))), "×")),
"select count(Col1) where Col2 is not null group by Col1 pivot Col2"), "offset 1", 0)),,9^9)), " "))