1. 这篇文章真正要解决的问题先说结论2025 年还在纠结“要不要学 VBA”“VBA 是不是过时了”的人大概率还没遇到真正需要批量处理 Excel 的场景。而很多 Excel 重度用户真正卡住的不是不懂编程是没有一个低成本的方式把“我会操作 Excel”变成“我能写脚本自动化 Excel”。WorkBuddy 作为一个办公场景的 AI 助手工具在 VBA 学习上解决了一个很实际的问题它能把自然语言指令转换成可以运行的 VBA 代码并且能解释代码逻辑、指出报错原因、给出修改建议。这意味着你可以用“告诉 AI 我想要什么”的方式来学 VBA而不是先啃完几百页语法书再动手。本文会用 WorkBuddy 辅助完成一个非常高频的实战任务删除 Excel 数据区域中的重复值和空值。这个任务几乎每个做数据整理的人都遇到过而且实现方式很多踩坑也很多。通过这个任务你可以同时掌握WorkBuddy 的基本使用流程和核心能力边界VBA 中处理单元格区域、数组、集合、字典的核心方法删除重复值空值时的三种主流实现思路实际运行脚本时最常见的报错和排查方法。读完这篇文章你可以照着步骤在自己电脑上从零跑通一个 VBA 自动化脚本并且理解每一行代码为什么这么写。这就是本文和“复制粘贴一段 VBA 代码”之间的最大区别。2. WorkBuddy 与 VBA 的定位为什么这两个词会被放在一起2.1 WorkBuddy 到底是什么从名字和用途看WorkBuddy 是一个面向办公场景的 AI 工作台工具。它可以使用自然语言生成代码、解释技术概念、辅助处理文档和表格里的实际任务也被不少用户用来搭建个人工作台、写网页、做接口自动化等。和其他编程助手相比WorkBuddy 更聚焦办公场景尤其适合 Excel/WPS 重度用户。对于 VBA 学习来说WorkBuddy 的核心价值不是“帮你写代码”而是“在你写代码的每个环节提供即时反馈”。你可以在 WorkBuddy 里直接提问“用 VBA 删除 A 列重复值保留第一次出现的记录”“这段代码为什么提示下标越界”“字典和集合在去重场景中哪个更快”“如何遍历整个工作表并删除空白行”。它会给出可运行的 VBA 代码还会解释代码的关键逻辑。这本质上把“查文档、看论坛、问前辈”的三个步骤压缩成了一个对话。2.2 什么时候要以 VBA 为主角虽然 WorkBuddy 能生成代码但 VBA 本身才是解决问题的底层能力。原因很现实Excel/WPS 原生支持宏和 VBA不需要额外运行时环境VBA 可以直接操作单元格、区域、工作表、文件对于几千行、几万行的数据整理任务用 VBA 比手工筛选快几十倍WPS 表格也能运行 VBA在启用 VBA 宏插件的前提下这让 VBA 在国内办公环境里覆盖面更广。用 WorkBuddy 学 VBA正确的姿势是让 AI 承担“写第一版代码”和“解释报错”的工作但你自己要能看懂代码逻辑、会改代码、能判断结果对不对。否则一旦遇到与 AI 场景不同的小差异或者 AI 给了不兼容的版本写法你就会卡死。2.3 需要区分的几个概念很多人刚接触时会混淆几个相关工具和概念。概念定位与本文的关系WorkBuddy办公场景 AI 助手可生成 VBA、处理工作流本文用它来辅助生成和调试 VBACodeBuddy偏开发场景的 AI 编程助手两者定位不同不作为本文重点Excel VBAExcel 内置的宏编程语言本文实战部分的主题WPS VBAWPS 表格使用的 VBA 宏支持插件国内用户常用运行环境之一WPS JS 加载项WPS 的 JavaScript 自动化方案可作为 VBA 替代方案参考但不是本文主角从工作效率角度看VBA 仍然是目前 Excel/WPS 场景下批处理数据最直接、资料最多、上手壁垒相对低的一种方案。WorkBuddy 这类 AI 工具恰好弥补了 VBA“语法繁杂、调试费劲”的短板。3. 环境准备与前置条件在开始实战之前需要准备好运行环境。如果你用的是公司电脑或财务专用机先和对应 IT 部门确认宏功能可以启用避免因为权限问题卡在第一步。3.1 软件环境操作系统Windows 7 及以上。WorkBuddy 是否支持 Win7 取决于具体版本建议使用最新的 Windows 10/11WPS/Excel 均需要可用。表格软件Microsoft Excel 2016 及以上或 WPS Office已安装 VBA 宏插件。WorkBuddy你需要有一个能正常访问的 WorkBuddy 客户端或网页版。本文流程以“能自然语言对话并生成 VBA 代码”为基准具体界面以你使用的版本为准。宏安全设置需要允许运行宏。在 Excel 中可以点击菜单“文件→选项→信任中心→宏设置”选择“禁用所有宏并发出通知”或者“启用所有宏”仅限测试环境也可以将文件保存为.xlsm格式并在打开时点击“启用宏”。WPS 用户使用 VBA 插件时按插件对应说明开启。3.2 准备测试数据为了安全测试我们不要一开始就清理工作数据。建议新建一个工作簿在 Sheet1 中准备一份明显包含重复值和空值的测试表格。示例数据如下你可以直接手动输入序号姓名部门销售额1张三销售部10002张三销售部10003李四市场部20004空技术部15005王五空8006李四市场部20007王五财务部空这份数据包含两种典型脏数据整行完全重复的记录第 1 行和第 2 行第 3 行和第 6 行单元格空值第 4 行姓名缺失、第 5 行部门缺失、第 7 行销售额缺失。我们的目标是用 VBA 程序自动识别并删除重复行然后处理空值区域最终输出一份干净的数据表。请注意这里我们要先明确业务规则是“只要整行重复就删除”还是“按某一列判断重复后删除”这直接影响代码写法。我们会在下一节仔细分析。4. 实战场景分析删除重复值和空值的完整思路在写代码之前先想清楚逻辑。很多人看到“删除重复值空值”就急着写循环结果写出来的代码既慢又容易误删数据。真正合理的顺序是先定义规则再选实现方案最后动手。4.1 明确需求规则处理重复值首先要回答一个问题什么是“重复”严格重复所有字段都相同。按关键列重复比如“姓名”相同就算重复保留第一次出现的记录。处理空值也要区分删除整个行只要任意一个关键字段为空就删除该行只删除包含空值的单元格删除后下方单元格上移把空值单元格填充为固定的占位值例如“未知”或 0。本文采用最常见的场景先按整行完全重复来去重保留第一次出现的记录然后把关键列姓名、部门、销售额中的空值视为脏数据删除这些行。你也可以在看清代码后自行调整。4.2 删除重复值的常用实现思路VBA 中删除重复值主要有四种方式它们的效率和适用场景差异很大方式实现核心优点缺点RemoveDuplicates 方法调用 Excel 内置去重功能代码量最少速度快只能对选定区域使用难以精细控制字典Dictionary用 Key 判断是否出现过灵活可自定义关键列需引用 Scripting 库或用 CreateObject集合Collection用集合判断 Key 是否存在自带计数功能写法略绕新手不易理解双重循环遍历单元格逐个比较最直观适合小数据量大数据量时会很慢对于“整行完全重复”最推荐的是RemoveDuplicates 方法这是 Excel 2010 以后版本提供的内置功能代码短、效率高。但如果你需要在 WPS 或旧版本 Excel 中使用或者需要按自定义规则去重推荐字典方案。本文两种都会给出示例。4.3 删除空值的常见坑空值问题比表面看起来更麻烦单元格看起来是空的实际上里面可能有空格字符用IsEmpty判断只对真正未赋值的单元格有效用Text 判断时公式返回空字符串也可能被当成空值遍历删除行时如果用For Each正向循环删除行会让后面的行上移导致跳行漏删。这些坑在代码实现部分都有对应解法。你可以先记住一个原则凡是涉及删除行的循环尽量使用倒序循环For i lastRow To 1 Step -1。5. 用 WorkBuddy 生成第一版 VBA 代码按列去重方案现在进入核心实战环节。先演示一个最容易扩展的方案按“姓名”列去重保留第一次出现的记录同时删除姓名、部门、销售额中的空值行。这个任务你完全可以交给 WorkBuddy 写但我建议你先理解下面的代码再动手执行。5.1 使用 Excel 内置 RemoveDuplicates 的版本这个版本最简单适合整行完全重复去重。 文件路径模块1直接在VBA编辑器中插入模块 Sub DeleteDuplicatesAndBlanks_Simple() Dim lastRow As Long Dim ws As Worksheet 明确操作对象避免误操作其他工作表 Set ws ThisWorkbook.Sheets(Sheet1) 获取数据区域最后一行行号 lastRow ws.Cells(ws.Rows.Count, A).End(xlUp).Row 如果要处理所有列先选中数据区域 With ws.Range(A1:D lastRow) 对选定区域去重。参数1表示总列数为4列参数2表示无标题行。 如果第一行是标题行应将参数设置为 xlYes .RemoveDuplicates Columns:Array(1, 2, 3, 4), Header:xlNo End With MsgBox 删除重复值完成当前数据区域最后一行是 lastRow End Sub这段代码的关键点在于RemoveDuplicates的Columns参数。如果你只想按“姓名”去重就写Columns:Array(1)如果整行所有列相同才算重复就要把 1 到 4 列都写上。容易出错的地方RemoveDuplicates方法在 Excel 2010 之后才有WPS 的 VBA 插件是否支持需要以你的版本为准。另外它执行后lastRow并不会自动更新为新的最后一行需要在去重后再重新计算一次行数。5.2 使用字典按自定义列规则去重如果要求更灵活比如比较时忽略首尾空格推荐字典方案。 文件路径模块1直接在VBA编辑器中插入模块 Sub DeleteDuplicatesByKey() Dim ws As Worksheet Dim lastRow As Long Dim i As Long Dim dict As Object Set ws ThisWorkbook.Sheets(Sheet1) lastRow ws.Cells(ws.Rows.Count, A).End(xlUp).Row 创建字典对象。使用 CreateObject 可以避免手动添加引用 Set dict CreateObject(Scripting.Dictionary) 倒序遍历从最后一行开始 For i lastRow To 2 Step -1 以姓名列A列为判断依据 Dim key As String key Trim(CStr(ws.Cells(i, 1).Value)) 如果该姓名已经在字典中说明是重复行删除 If dict.Exists(key) Then ws.Rows(i).Delete Else 如果第一次遇到该姓名记录到字典中 dict.Add key, i End If Next i MsgBox 按姓名列去重完成 End Sub这段代码的逻辑是倒序遍历每一行拿 A 列的值判断是否在字典中。如果已经存在就删除当前行否则加入字典。倒序删除的关键原因是删除倒数第一行不会影响前面行的索引真正避免漏删。需要注意这个版本没有处理空值。空值的处理逻辑我们在下一节一起加进去。6. 完整实战删除重复值、空值的最终 VBA 代码为了让初学者直接能用我把空值处理和重复值处理合在一个过程里。这个版本是二手数据清洗里比较通用的写法去重 删除关键列空值。6.1 最终代码可直接复制运行 文件路径模块1在VBA编辑器中插入一个模块并复制此代码 Option Explicit Sub Clean_Data_RemoveDupAndBlank() Dim ws As Worksheet Dim lastRow As Long Dim lastCol As Long Dim i As Long Dim j As Long Dim dict As Object Dim hasError As Boolean Dim dataArea As Range 手动确认防止误删 If MsgBox(即将删除重复行和空值行是否继续, vbYesNo vbQuestion, 确认) vbNo Then Exit Sub End If Set ws ThisWorkbook.Sheets(Sheet1) 获取数据区域边界按A列向上定位最后一行 lastRow ws.Cells(ws.Rows.Count, A).End(xlUp).Row 如果只有表头没有数据直接退出 If lastRow 2 Then MsgBox 没有数据需要清理, vbInformation, 提示 Exit Sub End If 获取最大列数考虑B、C、D列都可能更长 lastCol ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column If lastCol 1 Then lastCol 1 定义数据区域用于后续定位 Set dataArea ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol)) 第一步处理重复行 Set dict CreateObject(Scripting.Dictionary) For i lastRow To 2 Step -1 构造该行的唯一识别字符串把所有非空单元格值用管道符连接 Dim rowKey As String Dim cellValue As String rowKey For j 1 To lastCol cellValue Trim(CStr(ws.Cells(i, j).Value)) rowKey rowKey cellValue | Next j 如果该行所有字段都不为空才参与重复判断 If Trim(rowKey) || String(lastCol - 1, |) Then If dict.Exists(rowKey) Then 重复行直接删除 ws.Rows(i).Delete Else dict.Add rowKey, i End If End If Next i 重新计算最后一行因为删除行后行号已经变化 lastRow ws.Cells(ws.Rows.Count, A).End(xlUp).Row 第二步处理空值行 For i lastRow To 2 Step -1 Dim isEmptyRow As Boolean isEmptyRow False For j 1 To lastCol 使用 Trim 和 Len 判断兼容空格空值 If Len(Trim(CStr(ws.Cells(i, j).Value))) 0 Then isEmptyRow True Exit For End If Next j If isEmptyRow Then ws.Rows(i).Delete End If Next i MsgBox 清理完成, vbInformation, 完成 End Sub6.2 代码逻辑拆解这段代码比前面的示例要长因为它考虑了几类初学者最容易踩坑的情况。第一部分先处理重复行。核心思路是用rowKey把整行数据拼成一个长字符串用这个字符串作为字典的 Key。只要整行的所有列拼接结果一样就判定为重复。这样比只按某一列去重更严格能防止“不同人同名但数据不同却被删除”的问题。第二部分处理空值行。我们使用的是Len(Trim(...)) 0这种写法它可以兼容单元格为空的两种情况真正没有赋值以及里面只包含空格。整个代码的关键是两次For i lastRow To 2 Step -1倒序循环。每次删除一行后面的行会自动上移但因为我们是倒着遍历所以不会影响还没检查到的行。这一点初学者必须记住在 VBA 里删除行优先用倒序循环。6.3 如何运行这段代码打开 Excel 或 WPS 表格按Alt F11打开 VBA 编辑器点击菜单“插入”→“模块”在代码窗口粘贴上面的代码按F5或点击工具栏中的运行按钮如果弹出了“即将删除重复行和空值行”的确认框点击“是”运行完成后会弹出“清理完成”的提示框。6.4 试运行与验证运行前建议先在测试数据上执行一次。确认之后观察 Sheet1 中的数据原来重复的第 2 行、第 6 行应该已经消失包含空值的第 4 行、第 5 行、第 7 行应该已经被删除剩下的数据按原来的顺序排列。如果结果不对不要急着改代码。先在 VBA 编辑器中按Ctrl G打开立即窗口打印一些关键信息来定位问题。比如在代码里临时加入Debug.Print 当前处理到第 i 行该行内容为 rowKey然后在菜单“视图”→“立即窗口”中查看输出。这是 VBA 调试最基础的手段。Debug.Print和MsgBox的区别在于Debug.Print不会中断程序适合批量输出调试信息MsgBox会弹窗阻塞适合少量提示。7. 进阶方案只删除重复值空值单独处理有时候业务上不希望删除“含空值的整行”而是希望把空值单元格填充为特定值。这时你会用到的是“只处理空值单元格”的思路。这里给出一个单独填充空值的子过程方便你按需调用。 文件路径模块1追加在这个或新建模块中 Sub FillBlankWithDefault() Dim ws As Worksheet Dim lastRow As Long Dim lastCol As Long Dim i As Long Dim j As Long Set ws ThisWorkbook.Sheets(Sheet1) lastRow ws.Cells(ws.Rows.Count, A).End(xlUp).Row lastCol ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column If lastCol 1 Then lastCol 1 For i 2 To lastRow For j 1 To lastCol If Len(Trim(CStr(ws.Cells(i, j).Value))) 0 Then 如果是数字列可以填0如果是文本列可以填未知 ws.Cells(i, j).Value 未填写 End If Next j Next i MsgBox 空值单元格已填充, vbInformation, 完成 End Sub这段代码和上面删除空值行的代码区别在于它不删除行只把空单元格替换成“未填写”。在实际项目里空值是“删行”还是“填充”完全取决于业务要求。比如财务数据中销售额为空可能是业务没发生也可能是漏报直接删行有可能把有价值的记录删掉。所以动手处理之前一定要先和数据使用方确认规则。8. WorkBuddy 常见问题与 VBA 运行报错排查下面是初学者在实际运行 VBA 脚本时最容易遇到的三类问题。如果你照着本文的代码操作大概率会遇到以下情况中的一种或几种。8.1 WorkBuddy 使用时的问题问题现象可能原因处理方式生成代码运行报错生成的是通用代码和你的 Excel/WPS 版本或数据结构不匹配把报错信息原样复制回 WorkBuddy 对话框让它基于新上下文修正上下文用量满了对话历史太长新开一个会话只粘贴核心需求和当前报错代码无法在 WPS 中运行WPS 没有安装 VBA 插件先安装 WPS VBA 宏插件或在 WorkBuddy 中要求生成“兼容 WPS 的 VBA 代码”主题和实际表格不匹配你的数据结构与提问描述不一致尽量在工作表截图/说明列名后再让 AI 生成8.2 VBA 代码运行时的问题问题现象可能原因排查方式解决方案提示“下标越界”访问的单元格行号或列号超出了工作表范围检查代码中Cells(行, 列)里的行号列号是否可能为 0 或超过 1048576在访问前用If lastRow 1做边界判断提示“该应用程序的宏语言支持功能被取消”Excel/WPS 未启用 VBA 支持或 WPS 未安装 VBA 插件检查“信任中心”的宏设置确认插件状态按软件版本安装 VBA 插件或在 Excel 中启用宏删除行后数据错乱正序循环删除导致跳行检查循环是否用了For i 1 To lastRow改用For i lastRow To 2 Step -1字典 Add 方法报“键已存在”没有先判断Exists就执行Add检查代码中是否少写If Not dict.Exists(key) Then在Add之前先判断程序运行很慢数据量大且逐单元格读取改用整列赋值到数组处理再写回下次进阶学习数组和 Range.Value 批量读写删除空值时误删了有内容的行空值判断逻辑错误检查是否用了IsEmpty且没考虑空格改用Len(Trim(...)) 0判断8.3 一个容易被忽略的坑合并单元格如果数据表里存在合并单元格整行删除和空值判断都会变得不可预测。比如某一行有一个合并单元格其他单元格非空这时Trim(CStr(ws.Cells(i, j).Value))的结果很可能是空字符串因为合并单元格中只有左上角单元格有值。遇到这种情况建议先取消合并单元格或者在代码中先遍历MergeArea来判断实际值。不过这个问题超出了本文范围你只需要知道用 VBA 清洗数据前先检查是否存在合并单元格。9. 最佳实践与工程建议9.1 数据清洗前必须做的三件事第一备份原始数据。不要直接在唯一的工作表上跑删除脚本。最稳妥的做法是复制一份工作簿副本或者把原始数据复制到隐藏的工作表。建议增加一个确认弹窗来防止误操作本文最终代码已经包含这个环节实际项目中也可以把备份动作直接写进程序。第二明确字段规则。哪一列是唯一标识空值是否允许重复的定义是什么这些都要和数据使用方确认。业务规则不确定时宁可先输出重复记录清单也不要直接删除。你可以写一个宏把“将要删除的行”标红而不是立刻删除人工检查后再执行真正的清理。第三用测试数据验证代码。随手造一个 20 行左右的测试表包含各种边界情况空行、隐藏行、重复行、带空格的单元格、合并单元格。代码先在测试表上跑通再接触真实数据。9.2 VBA 代码的编写规范所有过程Sub前尽量加上Option Explicit强制声明变量减少拼写错误引起的“变量未定义”问题工作表对象用变量声明避免写Sheet1后改表名导致代码失效删除操作前先用MsgBox或Application.DisplayAlerts做好安全和友好提示尽量使用With语句减少代码重复关键步骤写注释。VBA 代码最大的问题不是运行效率低而是三个月后自己看不懂。比如Trim(CStr(ws.Cells(i, j).Value))这一句不写注释的话下次维护的人会很痛苦。9.3 性能优化方向如果数据量超过 5 万行逐行操作单元格就会变慢。推荐先学习两个技巧把区域整体读入数组在内存中完成去重和空值判断最后一次性写回关闭屏幕刷新和自动计算在代码开头写Application.ScreenUpdating False结尾写Application.ScreenUpdating True明显提升速度。这里也提醒一下如果你擅长用 WPS JS 加载项可以考虑把 VBA 方案迁移到 JS尤其在 WPS 环境中 JS 加载项的兼容性和分发效率都更好。但 VBA 的资料和社区经验依然最丰富对大多数人仍然是更稳妥的起点。9.4 把 WorkBuddy 当成教练而不是代笔用 WorkBuddy 学 VBA和用搜索引擎找代码最大的区别在于你可以连续追问。比如它给了你一段代码你可以追问“把这里的删除逻辑改成填充逻辑”“为什么用字典而不是集合”“这段代码在 WPS 中能运行吗”“如果我想先选出重复行而不是直接删除该怎么改”。这种“拿到代码后再追问三次”的学习方式比直接复制粘贴代码更有效。还有一种很推荐的做法是先用 WorkBuddy 生成代码再自己手动改一个变量比如把按 A 列去重改成按 C 列去重观察结果变化。改一次你的理解就深一层。10. 总结与后续学习建议本文的核心是借助 WorkBuddy 这类 AI 工具打通一条“从想到做”的 VBA 学习路径。很多人学习 VBA 失败的最大原因不是语言难而是“不知道从哪里开始”。本文用“删除重复值、空值”这个日常工作里最常见的需求展示了一条完整的路径分析需求 → 确定规则 → 生成代码 → 运行验证 → 处理报错 → 优化改进。你可以把本文的最终代码当作第一个 VBA 工具把它保存在个人宏工作簿中Personal.xlsb以后在任何工作簿里都能调用。写完这个工具后建议继续按以下顺序进阶学习单元格和区域的常用属性与方法Value、Offset、Resize、CurrentRegion练习数组与循环把一个区域的数据一次性读入数组遍历处理后再写回学习条件结构If、Select Case 在处理复杂规则时的写法掌握错误处理On Error Resume Next 与 On Error GoTo 的适用场景了解 VBA 与 WPS JS 加载项的取舍什么时候该继续用 VBA什么时候迁移到 JS。在实践时有一个底线原则要记住所有涉及删除、覆盖、批量修改的脚本第一步永远是备份和确认。即便有 WorkBuddy 帮你写代码代码最终是在你的电脑、你的数据上运行这个责任最终要自己承担。建议在把脚本用在工作表之前先看一遍每一行代码在做什么再决定是否运行。如果你已经把代码跑通了尝试给自己增加一个挑战改写代码使得删除重复值时不是按整行判断而是按“姓名 部门”两列组合判断空值则填充为“待补充”。这个任务既会让你真正掌握字典和条件判断也让你理解“业务规则”和“代码逻辑”之间的转化过程。如果卡住了就把你的代码和报错信息发给 WorkBuddy让它和你一起调试。