☰
WPS表格重复值与空值清理:用WorkBuddy+JSA实现办公自动化
2026/10/19 5:51:48 网站建设 项目流程

WPS 表格里的重复值和空值,看起来是两个很小的数据处理点,实际清理起来却非常消耗耐心。我第一次帮同事整理一张 8000 行的客户表时,光是“去重”就折腾了三轮:第一轮发现数字和文本不一致,第二轮发现单元格末尾带着空格,第三轮又发现“重复值”在不同业务里判断的列根本不一样。也就是从那次之后,我意识到如果能把这类处理逻辑写成 JSA 宏固定下来,把需求描述交给 WorkBuddy 生成代码,再由 WPS 去执行,整套流程能省下大量时间。WorkBuddy 加 WPS-JSA,用中文描述“删除重复值、去掉空值”这种工作需求,就能得到可运行的宏,这套组合可以说就是给日常办公场景设计的“靠嘴编程”。这篇文章会沿着一个真实场景展开:删除数据里的重复值和空值,从环境准备、第一条指令、代码逻辑、多场景处理,一直到批量化和排查链路。

1. WorkBuddy 到底解决什么问题——先把“靠嘴编程”这几个字拆清楚

1.1 “靠嘴编程”不是喊一句话就完了,而是把需求整理成机器能理解的描述

“靠嘴编程”听起来像是动动嘴就能让电脑自己干活,但它实际的含义是:用自然语言把需求说清楚,由 AI 工具把自然语言翻译成可执行代码。放在 WPS-JSA 这个场景里,就是你说“把 A 列重复行去掉”,WorkBuddy 根据你给出的表格结构、数据特征和描述,生成一段 JSA 代码,你再把这段代码放进 WPS 的运行环境去执行。关键点在于,最终执行任务的还是代码,不是语音助手,也不是对话框。WorkBuddy 把“写代码”这一步简化了,但“把需求描述准确”这个环节并没有消失,反而变得更重要。

我第一次使用时的体会是:这种工具最怕的不是你不会写代码,而是你不会提需求。你如果说“删除重复值”,它默认的处理方式可能是保留第一次出现、删除后续行;但如果你想要的是把重复单元格清空、或者把重复行标成红色,那必须明确说出来。因此,我把使用 WorkBuddy 的第一步理解成“当需求分析师”:先梳理清楚要处理哪张表、哪一列、什么规则、保留什么、结果放哪里。

1.2 为什么要用 JSA,而不是 VBA 或 Python?

提到表格宏,大多数人先想到 VBA,也有人第一反应是 Python 和 pandas。这里我说一下为什么 WPS-JSA 更适合当前这个场景。

VBA 的核心优势是历史兼容性好,网上教程多。但 WPS 从某些版本开始对 JSA 的支持更完整,JSA 作为 WPS 内置的 JavaScript 运行环境,和 WPS 表格对象模型直接打通。对普通办公用户来说,学习 JavaScript 的基础语法比学习 VBA 的“录制宏—改代码”更符合现在的前端思维习惯。

Python 不是不能做,但会引入不少额外成本。你要装 Python 环境、装库、处理文件路径、考虑会不会被公司安全策略拦截。即便写一个去重脚本,也需要把表格文件读进来、处理、再写出去,整个过程和 WPS 表格自身是分离的。优点是数据处理能力更强、适合大数据量,但如果只是“打开表格、删重复行、保存”,用 JSA 宏更直接。

WorkBuddy 在这里的角色,就是把 JSA 的编写门槛降下来。它生成的是 JavaScript 代码,但你不需要从零开始写。你把需求描述得越清楚,它生成的代码越接近你想要的逻辑。最终代码留在 WPS-JSA 编辑器里,你可以反复查看、保存和复用,不会像“一次性脚本”那样用完就找不到了。

1.3 弄清楚边界:哪些任务适合用 WorkBuddy + WPS-JSA

我整理了一下,下面这些场景最适合用这套组合:

  • 表格行数在几万行以内,需要按规则去重、删除空行、填充空值、格式化。
  • 任务需要反复执行,比如每个月导出的报表结构相同,只是数据变化。
  • 你已经描述得清楚,但缺少写代码能力,或者写得很慢。
  • 需要把处理过程沉淀下来,以后再跑一遍,而不是每次手工点菜单。

不适合的场景也要说清楚。如果单表数据量超过几十万行,JSA 遍历加删除会比较吃力,优先考虑导出到专业工具处理。如果你对数据一致性和代码安全要求极高,每一条逻辑都要自己审核,那你更应该把它生成的代码当草稿,而不是直接信任。如果表格结构经常变,上一次按 B 列去重,下一次要按 C 列和多列联合去重,那么提示词也得同步变,复用性会打折。

1.4 环境准备的几个前置条件

在实际跑第一个样例之前,我会建议先确认三件事:

  • WPS 版本支持 JSA。打开 WPS 表格,找到“开发工具”选项卡,如果没有,先去设置里启用。进入之后能看到 JSA 编辑器,就说明环境可用。
  • WorkBuddy 能够正常访问当前文件。如果脚本操作当前表格,文件路径通常不关键;如果脚本要遍历外部文件,路径里有中文、空格、括号的时候要特别小心。
  • 备份权限和工作目录权限。删除行、填充单元格这类操作会改动原始数据,脚本最好在一个副本文件上运行。

在不确定环境的情况下,先用一个 20 行左右的小表测试,别拿正式数据上来就跑。环境没问题了,再去纠结构代码怎么写。

2. 跑通第一句指令:删除整列重复值,背后到底生成了什么

2.1 第一条指令示例

我第一次给 WorkBuddy 的需求是这样的:

“当前打开了一个销售表,第一行是标题,A 列是订单编号。按 A 列判断重复,然后保留第一次出现的记录,把后面重复出现的行删掉。”

这里面的关键词是:活动工作表、第一行表头、A 列、保留第一次、删除后面重复的行。注意我没有说“所有列”,因为需求只是在 A 列维度去重。

WorkBuddy 生成的代码,核心逻辑大概是:

function removeDuplicateByColumnA() { const sht = ActiveSheet; const lastRow = sht.Cells(sht.Rows.Count, 1).End(xlUp).Row; const seen = new Set(); for (let i = 2; i <= lastRow; i++) { const value = String(sht.Cells(i, 1).Value2); if (seen.has(value)) { sht.Rows(i).Delete(); i--; } else { seen.add(value); } } }

这段代码不是唯一写法,但代表了最直接的实现思路:从第 2 行开始遍历,每读到一个值就放进 Set,Set 里已经有了就删除当前行。因为删除行之后后面的行会上移,所以循环变量需要减 1,保证下一次处理的是当前这一行的新内容。

2.2 为什么要先备份,再看运行结果

跑这段代码之前,我一定先复制一份原始文件。WPS-JSA 的宏一旦执行,删除行是不可撤销的,如果你在同一个文件上操作,点错一次前面的手工整理全部白费。备份看起来是多余动作,实际上是最省时间的一步。

跑完以后,验证方法主要有三个:

  • 看行数变化。执行前后的行数差应该等于重复行数。
  • 看 A 列是否还有重复。可以选中 A 列,用“条件格式—突出显示重复项”检查。
  • 抽样看删除边界。找一下原来重复的那几行,确认保留的是第一次还是最后一次。

2.3 分歧点:删行、清空还是标记

很多人只扔给 WorkBuddy 一个“删除重复值”需求,然后发现结果不完全符合预期。原因是“删除重复值”在企业里至少有几种理解:

  • 删除整行,只保留唯一值对应的第一次出现行。
  • 只清空重复单元格里的值,其他列数据不动。
  • 把重复行标记出来,比如标成黄色,原数据保留。
  • 按两列联合判断重复,例如“客户编号 + 日期”才能确定唯一。

不同理解对应完全不同的代码。删除整行需要遍历后 Delete;清空值只需要把重复位置 Value2 设为空;标记则只需要修改 Interior.Color;多列联合去重需要在 Set 中组合 key,不能只读一列。WorkBuddy 没办法自己猜出你要哪种,你必须说清楚。这也是我反复提醒“需求比代码更关键”的原因。

2.4 隐藏的数据陷阱:空格、文本、格式

去重去不干净的常见原因,不是逻辑有问题,而是数据有问题。

第一种是空格。单元格里“张三”和“张三 ”,肉眼看着差不多,脚本用 String 取值后做严格比较,两个字符串不一样。解决办法是先 Trim 一遍,再去判断。

第二种是数据类型。A 列大部分是数字,少部分是文本数字,“12345”数值和“12345”文本在 Set 里的表现也可能不同,最终导致重复项没有被识别。建议先把整列类型统一成文本或数字,再做去重。

第三种是隐藏字符。从系统导出的数据,可能在字符串里带了换行符、制表符或者不可见字符,打印出来看不出来,比较的时候就是不同。遇到这种情况,先做一次字符清理。

所以更稳妥的指令是:

“先去掉 A 列每个单元格首尾空格,再按 A 列内容去重,保留第一次出现,删除后续重复行。”

3. 再进一步:空值筛选、清除与整表脏数据整理

3.1 空值不是一个单一问题

空值的处理比重复值更容易翻车。因为你必须区分三种情况:

  • 整行所有关键列都为空:这通常是可以安全删除的脏数据行。
  • 只有某一列单元格为空:其他列有数据,不能删整行。
  • 单元格内容是有空格或者字符串“null”:并不是严格意义的空值。

很多指令只说“删除空值”,生成的代码很容易把不该删的行也删了。正确做法是先把“空值”的定义说清楚:是真空单元格,还是空格、空字符串、或者指定列的缺失值。

3.2 删除完全空白行的处理方式

指令示例:

“当前工作表数据从第 1 行到第 1000 行,判断每一行 A、B、C 三列是否都为空,如果是,就删除整行。第一行是表头,不参与判断。”

生成逻辑一般是:

function removeBlankRows() { const sht = ActiveSheet; const lastRow = 1000; for (let i = lastRow; i >= 2; i--) { const a = String(sht.Cells(i, 1).Value2 || "").trim(); const b = String(sht.Cells(i, 2).Value2 || "").trim(); const c = String(sht.Cells(i, 3).Value2 || "").trim(); if (a === "" && b === "" && c === "") { sht.Rows(i).Delete(); } } }

这段代码选择从最后一行向前遍历,是因为删除行会影响行号,倒序遍历时,未处理的行不会因为删除而改变位置。如果你看到生成的代码是正序遍历,就要检查里面有没有做下标补偿,否则很容易漏行。

3.3 非空行里的空单元格,不要删行

如果只是某列空,但整行有数据,不能删行。比如“C 列是手机号,有些行为空,我想最后再统一填充成 0”。正确做法是遍历 C 列,判断为空则赋 0。删行会把整个客户记录删掉,后果很严重。

这里我建议在指令里把范围和填充规则都写完整:

“C 列从第 2 行到第 500 行,如果单元格为空,填入 0,不为空的不动。”

填充值不一定是 0,还可以是“未知”、当前日期、或者从上一行向下填充。不同的填充策略也是 JSA 代码里一个明显的差异点。如果你不说明,工具可能默认填 0,但业务上可能希望保留可读标记。

3.4 完整清洗一条指令拆成三步

我处理真实表格的习惯,是把一个复杂需求拆成一个三步指令序列。

第一步:清理空格。

“当前表所有用到的区域,每个单元格去掉首尾空格。”

第二步:删空行。

“删除 A、B、C 三列都为空的整行。”

第三步:去重。

“按 A 列判断重复,保留第一次出现的行,删除后续重复行。”

这样拆分的好处是每跑一步都能检查结果,出现问题能快速定位是哪一步。如果把所有逻辑塞进一句 100 字的长指令,WorkBuddy 大概率能理解,但一旦某一步做错了,你很难判断是提示词理解错了,还是执行逻辑有 bug。

3.5 用一张表说明不同需求的应对思路

需求描述实际处理方式关键判断
删除整行空白遍历关键列,全部为空则 Delete确认哪几列是关键列
某列为空填充默认值单列遍历,空则赋值确认填充值和列范围
某列为空标黄单列遍历,空则改底色确认标色位置和颜色
去重前清理空格先 Trim,再去重清理范围是全表还是指定列
按多列联合去重Set 中组合多个字段去重维度要提前说清楚

这张表只是思路参考,每一条落到 WorkBuddy 时,还是要加具体的表名、列名和数据范围。

4. 高效发号施令的工作流:从单条指令到批量日常编排

4.1 提示词的四要素公式

我总结了一个适用于这类自动化场景的提示词公式:

处理对象 + 范围 + 规则 + 结果形式

比如:

“在活动工作表中,A 列从第 2 行到第 1000 行,按 A 列去重,保留第一次出现的行,删除其他重复行。第一行保留不变。”

这个描述里,每一个维度都有对应信息:

  • 对象:活动工作表。
  • 范围:A 列 2 到 1000 行。
  • 规则:A 列重复时保留第一次。
  • 结果形式:删除其他重复行。

加上结果形式,是因为有时候你需要的是“把重复项标记”,而不是删除。这个区别如果不说清楚,代码会走完全不同的分支。

4.2 多文件批量场景的命令结构

批量处理是 WorkBuddy 比较容易被低估的能力。你可以让它生成一个脚本,遍历某个目录下的所有表格文件,在每个文件里做同样的去重和空值清理。

关键描述是:

“写一个 JSA 函数,遍历 D:/清洗任务/ 目录下所有表格文件,逐个打开,在第一个工作表执行:删除完全空白行,再按 A 列去重保留第一次出现。保存并关闭文件。”

这段描述里要给出明确的目录路径和文件名规则。脚本里通常需要用到文件系统对象获取文件名列表,再逐个打开、执行、保存、关闭。如果文件中有多个工作表,还要指定处理哪个 Sheet,否则默认只处理激活的那一张。

批量场景特别要注意文件命名问题。如果目录下有临时文件、备份文件、或者不是目标结构的文件,脚本可能全部打开跑一遍,最后产生错误结果。我的做法是把待处理文件放到一个独立目录,确认里面只有目标文件,再运行批量脚本。“先隔离、再批量”,这个顺序不变。

4.3 从“每次生成代码”变成“长期跑固定宏”

第一次用 WorkBuddy 生成的代码,经过验证以后,应该沉淀下来。它不只是解决一次问题,还能变成你常用的办公工具。

具体做法是:

  • 打开 WPS 的 JSA 编辑器,把验证过的函数复制进去。
  • 按用途命名,比如 cleanSpaces、removeBlankRows、removeDuplicatesByColumnA。
  • 给宏绑定快捷键或者放到自定义功能区,以后一键执行。

长期使用后,你会有几个固定的宏模板。这个价值比临时生成一次大得多。因为生成代码虽然快,但每次生成你还是需要检查和测试,而固定宏一旦稳定下来,就变成了随时可调用的确定性工具。

4.4 为什么不建议把 WorkBuddy 当神仙工具

WorkBuddy 的优势是生成速度快,能把自然语言翻译成代码。但它有一个明显的特点:它生成的是建议代码,不是经过你业务验证的最终发布脚本。

一旦数据量增大、表格结构变化、或者处理规则变化,原来有用的代码就可能失效。比如去重从单列改成多列,模板就不能直接用;数据从 1 万行变成 50 万行,遍历删除也会明显变慢。所以任何通过这套流程生成的脚本,在真正长期使用之前,至少要经过一次完整的副本验证。

这个心态摆正了,WorkBuddy 才是一个好工具。否则你只是把“不会写代码”换成了“不会验收代码”,最后出问题还是得手工处理。

5. 越容易翻车的地方,越要按固定顺序排查

5.1 常见现象和根因

我根据实际使用整理了下面这些常见现象:

现象根因方向
运行后没变化操作的不是当前工作表,或者范围写错
删除行后数据错位遍历顺序不对,没有处理行号变化
去重有遗漏有空格、数据类型不一致
空值清不干净空格、空字符串、真空单元格混在一起
报错找不到对象Sheet 名称不对、API 名称错误、版本不支持
脚本运行很慢行数太大、删除操作太频繁

5.2 推荐的排查链路

如果脚本运行结果不对,我会按下面的顺序排查,不跳步:

  1. 先备份原文件,确保可以恢复。
  2. 缩小测试范围,比如只处理前 20 行,快速看逻辑是否符合预期。
  3. 检查输入数据本身。用条件格式看有没有空格、数据类型是否一致。
  4. 检查 WorkBuddy 生成代码里操作的是 ActiveSheet 还是指定 Sheet,区域有没有写死。
  5. 在 JSA 编辑器里设置断点或者弹窗,打印中间变量。
  6. 最后才考虑改代码逻辑。

这个顺序的关键在于:先排除环境和数据问题,再怀疑代码问题。很多人调试时一上来就改代码,改来改去发现根因是文件没保存、目录不对、或者数据里有不可见空格,非常浪费时间。

5.3 三条值得收藏的经验

第一条,复杂任务永远在副本上验证。这不是对 WorkBuddy 不信任,而是对数据安全的基本尊重。

第二条,生成代码后至少看一遍关键结构。不需要逐行看懂,但要确认没有明显问题。比如它操作的是不是你要处理的列,删除的是不是整行,有没有用到不存在的 Sheet 名称。这一点只要认真扫,谁都能做到。

第三条,遇到大数据量时,优先考虑“先标记再删除”或者“复制有效数据到新表”,而不是在一张大表里做几十万次逐行 Delete。逐行删除在数据量大时速度会明显下降,而且每删一次行,内存里的对象位置都在变化,出错概率更高。

把这些经验固化下来,你再遇到“删除重复值、空值”这类需求时,会发现第一步不是急着让 WorkBuddy 生成代码,而是先想清楚你的数据长什么样、要变成什么样。想清楚之后,让 WorkBuddy 生成代码只是几秒钟的事,剩下的就是测试一遍、保存宏、以后继续用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询