系列 · Excel 函数学习与实战 第 8 篇 / 共 9 篇 教程

Excel / WPS 奇怪问题记录

持续记录 Excel、WPS 和影刀表格自动化中不常见但容易踩坑的问题,包括影刀 set_range 写入异常和 XLOOKUP 数组回退失效。

作者:黄撑 更新于 2026-08-03
本文目录 8 节 · 点击展开

这篇文章只记录结论和解决方法,不展开排查过程。以后遇到类似的 Excel / WPS 奇怪问题,会继续追加在这里。

01|影刀 set_range() 写入等号文本时报 COM 异常

现象

使用影刀批量写入 WPS 二维数据:

sheet.set_range(1, "E", data)

可能出现下面的异常,并且同一份数据总是卡在固定区域:

pywintypes.com_error: (-2147352567, '发生意外。', ..., -1880948725)

原因

数据中存在= 开头的普通文本,例如客服备注:

=键盘和鼠标寄回换货,已建单发群

影刀调用 set_range() 写入时,会把这类内容交给 WPS 按公式解析。内容不是合法公式时,影刀就可能收到 COM 异常。

解决方法

确认这些内容本来就是文本后,在写入前加一个英文单引号:

for row in data:
    for index, value in enumerate(row):
        if isinstance(value, str) and value.startswith("="):
            row[index] = "'" + value

sheet.set_range(1, "E", data)

英文单引号不会显示在单元格中,看到的内容仍然以 = 开头。

只处理确定属于文本的内容。真正需要执行的公式不能加英文单引号。

02|数组 XLOOKUP[if_not_found] 没有逐项回退

现象

需要按顺序从多个工作表查找同一个 ID,最开始使用了嵌套 XLOOKUP

=XLOOKUP(
    E2#,
    汇总表!C:C,
    汇总表!A:A,
    XLOOKUP(
        E2#,
        渠道A!C:C,
        渠道A!A:A,
        "----------"
    )
)

单独用 XMATCH 检查时,目标 ID 明明可以在「渠道A」中找到;但放回整列公式后,部分结果仍然显示 ----------

原因

当第一个 XLOOKUP 使用 E2# 进行数组查询时,它返回的是一整组结果,例如:

[值1, 值2, #N/A, 值3, #N/A, ...]

这里不是整个结果都没找到,而是数组中的部分元素没找到

在当前 WPS 场景中,外层 XLOOKUP[if_not_found] 没有继续针对数组里的每个 #N/A 逐项执行内层查询。结果数组整体已经产生了匹配值,因此部分未匹配元素没有按预期回退到第二个工作表。

这也是为什么:

  • 单独查询某一个 ID 可以找到;
  • 使用 E2# 批量查询时却出现漏匹配;
  • 清洗空格、统一转数值或文本都无法解决。

解决方法

先把多个查询区域纵向合并,再只执行一次 XLOOKUP

=LET(
    ID,IFERROR(--TRIM(CLEAN(SUBSTITUTE(SUBSTITUTE(E2#,CHAR(160),""),UNICHAR(12288),""))),"")&"",
    汇总ID,IFERROR(--TRIM(CLEAN(SUBSTITUTE(SUBSTITUTE(汇总表!C2:C50000,CHAR(160),""),UNICHAR(12288),""))),"")&"",
    渠道AID,IFERROR(--TRIM(CLEAN(SUBSTITUTE(SUBSTITUTE(渠道A!C2:C50000,CHAR(160),""),UNICHAR(12288),""))),"")&"",
    渠道BID,IFERROR(--TRIM(CLEAN(SUBSTITUTE(SUBSTITUTE(渠道B!C2:C50000,CHAR(160),""),UNICHAR(12288),""))),"")&"",
    所有ID,VSTACK(汇总ID,渠道AID,渠道BID),
    所有结果,VSTACK(
        汇总表!A2:A50000,
        渠道A!A2:A50000,
        渠道B!D2:D50000
    ),
    IF(ID="","",XLOOKUP(ID,所有ID,所有结果,"----------"))
)

VSTACK 的顺序就是匹配优先级:先查「汇总表」,再查「渠道A」,最后查「渠道B」。

这样 [if_not_found] 只需要返回一个普通文本,不再承担“数组套数组”的逐项回退。

如果不想纵向合并,也可以让每个 XLOOKUP 单独返回数组,再用 IFNA 逐项替换。关键是不要继续把一个数组查询直接放进另一个数组 XLOOKUP[if_not_found] 中。