excel 如何通过只显示第二个值来修复#SPILL!错误?

2admgd59  于 2023-01-27  发布在  其他
关注(0)|答案(3)|浏览(749)

我有一个列,其中显示的一些信息如下:
| 产品信息|
| - ------|
| 我是2020年的第3款产品|
| 1995年创立,2021年上市|
| 我不确定我是不是来自2019 2020 2021|
我有一个公式来提取上一列中的年份,即:

=IFERROR(FILTERXML("<k><m>"&SUBSTITUTE([@[Product Name]]," ","</m><m>")&"</m></k>","//m[.=number() and string-length()=4]"),"")

这个公式的问题是,它在第一种情况下工作正常,但在另外两种情况下却给我一个#SPILL!错误。我理想的输出应该是:
| 产品信息|年份|
| - ------|- ------|
| 我是2020年的第3款产品|小行星2020|
| 1995年创立,2021年上市|小行星2021|
| 我不确定我是不是来自2019 2020 2021||

  • 基本上,对于第一种情况,只返回4位数。每次我只有一个4位数的序列,我都想返回那个序列。
  • 对于第二种情况,我只想返回第二年。每次我有2个4位数的序列时,我只想返回第二年。
  • 对于第三种情况,我想什么都不返回。每当我有超过2个4位数的序列时,我想返回空白。

我最后尝试添加的是position()〉5,这将截断第二个示例中的1995,但我会继续在第三个示例中出现错误。此外,我的列表相当庞大,我不确定position()〉5是否适用于第二个示例中的所有产品。
我不是很好与xpath,所以任何帮助将不胜感激。谢谢!

iq3niunx

iq3niunx1#

**免责声明:**下面的解答是基于这样的假设编写的:当'count of years〈3'时,返回最后一个给定的年份。如果'count〉= 3',则只返回最后一个年份,如果年份是成对出现的。因此使用'modulus 2 == 0'。‡

如果您愿意,您当然可以扩展xpath。但是,我会稍微重写它。每个 predicate ,即左右方括号之间的结构,都是给定节点列表的过滤器。编写多个这样的结构实际上就是anding这样的 predicate 。为了更好地理解大多数常见的xpath 1.0函数在FILTERXML()中可以做什么,我想把你转到this post。
所以要写出一个连续的 predicate 模式,我会选择:

  • [.*0=0]-首先返回所有数字的过滤节点列表,其中节点乘以零等于零;
  • [string-length()=4]-则只返回长度为4个字符的对象‡‡;
  • [position() = last() and (position() = 1 or position() mod 2 = 0)]-第三个也是最后一个 predicate 是查询中最棘手的,首先检查position() = last(),表示节点必须是第2步过滤后的节点列表中的最后一个节点**,**(position() = 1 or position() mod 2 = 0)表示我们要检查该节点是否也位于第一个索引 * 或 * 索引位置的模2等于0‡‡‡。

B2中的公式:

=IFERROR(FILTERXML("<t><s>"&SUBSTITUTE(A2," ","</s><s>")&"</s></t>","//s[.*0=0][string-length()=4][position() = last() and (position() = 1 or position() mod 2 = 0)]"),"")

虽然以上方法适用于Excel 2013及更高版本‡‡‡‡,但您确实讨论了溢出行为。如果您碰巧使用ms 365中的当前通道,您也可以尝试:

=LET(x,TEXTSPLIT(A2," "),y,--FILTER(x,ISNUMBER(-(x&"**0"))*(LEN(x)=4),{1,2,3}),z,COUNT(y),IF(OR(z=1,MOD(z,2)=0),TAKE(y,,-1),""))

‡如果你只需要返回过去一年的值,如果'count〈3',那么你可以使用xpath "//s[.*0=0][string-length()=4][position()<3 and position() = last()]"或ms 365公式=LET(x,TEXTSPLIT(A2," "),y,FILTER(x,ISNUMBER(-(x&"**0"))*(LEN(x)=4),""),IF(COUNTA(y)>2,"",TAKE(y,,-1)))
[3]注意,如果你想验证一个年份是在1900-2050年之间,你可以更加严格地使用[.*1>1899][.*1<2051]来代替第一个和第二个 predicate 。
‡‡‡注意在xpath * 中编写and/or语句的顺序很重要,我们需要使用显式括号来控制优先级。
‡‡‡‡‡这对于Excel Online或Excel for Mac来说是不正确的

zour9fqk

zour9fqk2#

只需添加一个简单的子句来确定返回的个数,例如使用ROWS(因为默认情况下FILTERXML返回一个 vertical 数组):

=LET(
    ζ, FILTERXML(
        "<k><m>" &
            SUBSTITUTE(
                [@[Product Name]],
                " ",
                "</m><m>"
            ) & "</m></k>",
        "//m[.=number() and string-length()=4]"
    ),
    ξ, ROWS(ζ),
    IF(ξ > 2, "", INDEX(ζ, ξ))
)

编辑:我可能更喜欢在这里避免使用FILTERXML

=LET(
    ζ, TEXTSPLIT([@[Product Name]], " "),
    ξ, -(ζ & "**0"),
    IF(COUNT(ξ) > 2, "", IFERROR(-LOOKUP(1, FILTER(ξ, LEN(ζ) = 4)), ""))
)
vltsax25

vltsax253#

您可以使用TEXTAFTER函数尝试执行以下操作。假设您在末尾使用空格分隔年份。如果不是这种情况,则可以调整公式以进行其他检查(它是一个数字和四位数,但严格地说,年份可以少于或多于4位)。如果前面的假设不适用,请告诉我,以便我可以尝试修改它。以下是一个数组版本,因此,如果您使用Excel表格,则可以使用整个表格列:

=LET(in,A2:A4,last,TEXTAFTER(in," ",-1),
 IF(ISNUMBER(1*TEXTAFTER(SUBSTITUTE(in," "&last,"")," ",-1)),"",last))

对于超过一年的情况,它将删除找到的最后一年,如果第二次搜索是数字,则返回空,否则返回找到的前一年。

相关问题