脚本(可能是自定义函数?)会更好。
解决方案 1
以下是您可以放入标题的公式(放入J1,删除以下所有内容)。
它的运行速度比第二种解决方案快得多,并且没有 N² 大小限制。它也适用于空托运人(& "♥" 用于那些空托运人):只要 A:A 列具有某些值,它就不会被忽略。
={
"Row of Last Entry";
ARRAYFORMULA(
IF(
A2:A = "",
"",
VLOOKUP(
ROW(F2:F)
+ VLOOKUP(
F2:F & "♥",
{
UNIQUE(F2:F & "♥"),
SEQUENCE(ROWS(UNIQUE(F2:F)))
* POWER(10, INT(LOG10(ROWS(F:F))) + 1)
},
2,
0
),
SORT(
{
ROW(F2:F) + 1
+ VLOOKUP(
F2:F & "♥",
{
UNIQUE(F2:F & "♥"),
SEQUENCE(ROWS(UNIQUE(F2:F)))
* POWER(10, INT(LOG10(ROWS(F:F))) + 1)
},
2,
0
),
ROW(F2:F);
{
SEQUENCE(ROWS(UNIQUE(F2:F)))
* POWER(10, INT(LOG10(ROWS(F:F))) + 1),
SEQUENCE(ROWS(UNIQUE(F2:F)), 1, 0, 0)
}
},
1,
1
),
2,
1
)
)
)
}
详细说明其工作原理
- 对于每一行,我们使用
VLOOKUP 在已排序的虚拟范围内搜索特殊数字,以获取与当前匹配的上一个条目的行号。
- 行的特殊编号的构造如下:我们在唯一条目中获取当前条目的序号,并将当前行号附加到该序号。
- 生成的特殊数字的右侧部分(行号)必须在它们之间对齐。如果条目的序号为 13,行号为 1234 且有 100500 行,则编号必须为
13001234。 001234 是右对齐部分。
- 对齐是通过将序列号乘以 10 的
(log10(total number of rows) + 1) 的幂来完成的,得到 13000000(来自上面的示例)。此方法用于避免使用 LEN 和 TEXT - 处理数字比处理字符串更快。
- 虚拟范围在第一列中具有几乎相同的特殊数字,在第二列中具有原始行号。
- 几乎相同的特殊数字:它们只是增加了 1,因此
VLOOKUP 最多会在当前字符串对应的数字前一步停止。
- 虚拟范围还有一些特殊的行(在排序前添加到底部),其中所有
0 的右侧部分作为其特殊编号(第 1 列),0 作为行号(第 2 列) .这样做是为了让VLOOKUP 在第一次出现该条目时找到它。
- 虚拟范围已排序,因此我们可以使用外部
VLOOKUP 的 is_sorted 参数设置为 1:这将导致最后一个匹配小于或等于正在查找的数字。
-
& "♥" 被附加到条目后,因此VLOOKUP 也将找到空条目。
解决方案 2 - 速度慢且有限制
但是对于一些足够少的行,这个公式有效(输入J1,删除下面的所有内容):
={
"Row of Last Entry";
ARRAYFORMULA(
REGEXEXTRACT(
TRANSPOSE(QUERY(TRANSPOSE(
IF(
(FILTER(ROW(F2:F), F2:F <> "") > TRANSPOSE(FILTER(ROW(F2:F), F2:F <> "")))
* (FILTER(F2:F, F2:F <> "") = TRANSPOSE(FILTER(F2:F, F2:F <> ""))),
TRANSPOSE(FILTER(ROW(F2:F), F2:F <> "")),
""
)
), "", ROWS(FILTER(F2:F, F2:F <> "")))),
"(\d*)\s*$"
)
)
}
但是有一个问题。公式内部的虚拟范围大小为 N²,其中 N 是行数。对于当前的 1253 行,它可以工作。但是有一个限制,超过这个限制就会抛出范围过大的错误。
这就是使用FILTER(...) 而不仅仅是F2:F 的原因。