ARTICLE · 1353144
用 AI 写 Excel VBA ⑦:合并拆分后的脏数据,一条宏清干净
系列名称:用 AI 写 Excel VBA|20 节零基础实战课
适用环境:Microsoft 365 / Excel 2016+ 桌面版,Windows(WPS 需另装 VBA 插件,Mac 部分 API 不支持)
阅读时长:约 12 分钟
难度:⭐⭐⭐(实战篇,需要前 6 讲基础)
🎯 一句话成果
今天你拿到一段数据清洗宏:一键完成去重复、删空行、去首尾空格、清除非打印字符。合并完的脏表、从系统导出的乱表,跑一次就干净。

📌 场景痛点
第 5 讲合并完 20 个文件,第 6 讲拆分完总表,你打开结果一看:
同一个订单号出现了 3 次(重复值) 中间夹着几行空行(合并时带进来的) 客户名前面有空格,"张三"和" 张三"被当成两个人 某些单元格里有乱码字符(从网页复制来的 CHAR(160)非断行空格)金额列混进了文本格式的数字
你开始手动:数据→删除重复值→筛选空行→右键删除→逐个 Trim……5000 行搞完,半小时没了,还漏了几个。
这些活,VBA 一个循环全干完。
但注意:数据清洗里有两个经典翻车点,新手必踩:
- 正序删行会跳行漏删
——删了第 5 行,原来的第 6 行变成新的第 5 行,循环就跳过了 RemoveDuplicates只认连续区域——如果中间有空行隔开,去重不完整
今天一次性全解决。
🧠 清洗规则定义(让 AI 明确边界)

清洗项 | 操作 | 注意事项 |
|---|---|---|
重复值 | 按指定列去重,保留首次出现 | 要告诉 AI 按哪列判断 |
空行 | 整行全空的行删除 | 用倒序循环 |
首尾空格 | 文本列 | 区分文本列和数字列 |
非打印字符 |
| 网页复制常见 |
文本型数字 | 转成真数字 | 金额列常见 |
🤖 这一讲用的提示词(直接抄)
【角色】你是资深 Excel VBA 专家,代码要稳、带中文注释、带错误处理。【场景】当前工作簿有一个"清洗源"工作表,第1行是标题,第2行起是数据。数据约 5000 行,A到G列。已知问题:- 有重复行(按A列"订单号"判断)- 有整行全空的行- 文本列(B列客户名、C列产品名)首尾有空格- 部分单元格含非打印字符(如 CHAR(160) 网页空格)- E列金额有时是文本格式【动作】写一个数据清洗宏,一键完成以下操作:1. 按 A 列(订单号)去重,保留首次出现2. 删除整行全空的行(倒序循环)3. B列和C列文本去首尾空格 + Clean非打印字符4. E列金额转为数字格式5. 清洗前弹窗确认,显示将执行哪些操作6. 清洗后弹窗报告:删了几行重复、删了几行空行、清洗了多少单元格【规则】- 倒序删行(For i = lastRow To 2 Step -1)- 不修改列结构、不删列- 清洗前不清空任何数据,只做"净化"- 关闭屏幕刷新【输出】完整可运行 Sub,中文注释,On Error 兜底。
📋 AI 给的代码(完整可运行)
Sub 一键数据清洗()'========================================'功能:去重 + 删空行 + 去空格 + 清乱码 + 转数字'核心:倒序删行 + Trim/Clean + RemoveDuplicates'========================================Dim ws As WorksheetDim lastRow As Long, i As Long, j As LongDim rng As RangeDim cellVal As StringDim dupCount As Long, emptyCount As Long, cleanCount As LongDim msg As StringOn Error GoTo ErrorHandlerApplication.ScreenUpdating = FalseApplication.Calculation = xlCalculationManualSet ws = ThisWorkbook.Sheets("清洗源")lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).RowIf lastRow < 2 ThenMsgBox "数据不足,无需清洗。", vbInformationGoTo CleanUpEnd If'---- 确认弹窗 ----msg = "将对""清洗源""表执行以下清洗操作:" & vbCrLf & vbCrLfmsg = msg & "1. 按 A列(订单号)去重,保留首次出现" & vbCrLfmsg = msg & "2. 删除整行全空的行(倒序安全删除)" & vbCrLfmsg = msg & "3. B/C列去首尾空格 + 清除非打印字符" & vbCrLfmsg = msg & "4. E列金额转为数字格式" & vbCrLf & vbCrLfmsg = msg & "是否继续?"If MsgBox(msg, vbYesNo + vbQuestion, "确认清洗") <> vbYes ThenMsgBox "已取消。", vbInformationGoTo CleanUpEnd IfdupCount = 0emptyCount = 0cleanCount = 0'===== 步骤1:按A列去重 ====='先标记重复(用 CountIf 辅助列),后面统一删'注意:RemoveDuplicates 方法简单但不够灵活,用辅助列法更可控ws.Columns("H").Clear ' 清辅助列ws.Cells(1, "H").Value = "重复标记"Dim dict As ObjectSet dict = CreateObject("Scripting.Dictionary")For i = 2 To lastRowDim orderId As StringorderId = Trim(CStr(ws.Cells(i, 1).Value))If dict.Exists(orderId) And orderId <> "" Thenws.Cells(i, "H").Value = "重复"dupCount = dupCount + 1ElseIf orderId <> "" Thendict(orderId) = iEnd IfNext i'===== 步骤2+3:倒序删空行 + 删重复行 ====='重新计算末行(去重后可能变少)lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).RowFor i = lastRow To 2 Step -1'检查是否重复行If ws.Cells(i, "H").Value = "重复" Thenws.Rows(i).DeleteElse'检查是否空行Set rng = ws.Range("A" & i & ":G" & i)If Application.WorksheetFunction.CountA(rng) = 0 Thenws.Rows(i).DeleteemptyCount = emptyCount + 1End IfEnd IfNext i'清辅助列ws.Columns("H").Clear'===== 步骤3:B/C列去空格 + Clean =====lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).RowFor i = 2 To lastRow'B列:客户名If Trim(ws.Cells(i, 2).Value) <> "" ThencellVal = ws.Cells(i, 2).Value'Trim + Clean + 替换 CHAR(160)cellVal = Trim(Application.WorksheetFunction.Clean(cellVal))cellVal = Replace(cellVal, Chr(160), " ")cellVal = Replace(cellVal, Chr(9), " ") ' Tabws.Cells(i, 2).Value = cellValcleanCount = cleanCount + 1End If'C列:产品名If Trim(ws.Cells(i, 3).Value) <> "" ThencellVal = ws.Cells(i, 3).ValuecellVal = Trim(Application.WorksheetFunction.Clean(cellVal))cellVal = Replace(cellVal, Chr(160), " ")ws.Cells(i, 3).Value = cellValcleanCount = cleanCount + 1End IfNext i'===== 步骤4:E列金额转数字 =====For i = 2 To lastRowIf ws.Cells(i, 5).Value <> "" Then'如果看起来是数字但存储为文本If Not IsNumeric(ws.Cells(i, 5).Value) Then'尝试清理后转换Dim numVal As DoubleOn Error Resume NextnumVal = CDbl(Replace(Replace(ws.Cells(i, 5).Value, ",", ""), " ", ""))On Error GoTo 0If Err.Number = 0 Thenws.Cells(i, 5).Value = numValws.Cells(i, 5).NumberFormat = "#,##0.00"End IfErr.ClearElse'已经是数字,确保格式正确ws.Cells(i, 5).NumberFormat = "#,##0.00"End IfEnd IfNext iCleanUp:Application.Calculation = xlCalculationAutomaticApplication.ScreenUpdating = TrueMsgBox "清洗完成!" & vbCrLf & vbCrLf & _"删除重复行:" & dupCount & vbCrLf & _"删除空行:" & emptyCount & vbCrLf & _"文本清洗单元格数:" & cleanCount & vbCrLf & vbCrLf & _"数据已净化,请检查结果。", vbInformationExit SubErrorHandler:Application.Calculation = xlCalculationAutomaticApplication.ScreenUpdating = TrueMsgBox "清洗出错:" & Err.Description & vbCrLf & "出错行:" & i, vbCriticalEnd Sub
🔍 逐段拆解(核心 4 处)
1)倒序删行——永远不跳行的秘密
For i = lastRow To 2 Step -1ws.Rows(i).DeleteNext i
为什么不能正序?

想象一下:你站在第 5 行,删了它。原来的第 6 行现在变成了第 5 行。循环走到 i = 6,但新的第 5 行(原来的第 6 行)被跳过了。
倒序就不存在这个问题:从最后一行往上删,删第 5 行时,第 6 行不受影响(它还在第 6 行)。
这是 VBA 数据清洗里最重要的一个知识点,没有之一。
2)辅助列标记重复 + 统一删除
ws.Cells(i, "H").Value = "重复" ' 标记' ...If ws.Cells(i, "H").Value = "重复" Then ws.Rows(i).Delete
用 Dictionary 判断重复,标记在辅助列 H,然后统一删除。比 RemoveDuplicates 方法更灵活:
可以精确控制"按哪列判断" 可以统计删了多少行 可以和空行删除合并在同一轮倒序循环里
3)Clean + Trim + Replace(Chr(160)) 三连击
cellVal = Trim(Application.WorksheetFunction.Clean(cellVal))
cellVal = Replace(cellVal, Chr(160), " ")Trim:去掉首尾空格 Clean:去掉 ASCII 0-31 的非打印字符 Replace(Chr(160), " "):网页复制常见的"非断行空格", Trim去不掉它,必须单独处理
三连击覆盖 99% 的"看不见的脏字符"。
4)文本型数字转换
numVal = CDbl(Replace(Replace(ws.Cells(i, 5).Value, ",", ""), " ", ""))金额列常见"1,234.56"被存为文本。先去掉逗号和空格,再 CDbl 转数字。转成功后设格式为 #,##0.00。
⚠️ 数据清洗的 5 个真·坑
现象 | 根因 | 解决 |
|---|---|---|
去重后数据变少了,但没删干净 | 重复行中间有空行隔开, | 用辅助列 + Dictionary 法(本讲代码) |
删空行时跳行漏删 | 正序循环删行 | 改为倒序 |
| 是 | 加 |
文本转数字后变成 | 列宽不够 | 加 |
清洗完发现数据不对 | 清洗前没备份 | 代码里加备份提示,或手动 |
🛠️ 让 AI 改版的常用追问
基础宏跑通后,可以直接追:
"加一个撤销功能:清洗前自动备份到新 sheet" "增加清洗日志:记录每行做了什么操作,输出到新 sheet" "增加按多列去重:A列+B列相同才算重复" "增加异常值检测:金额为负或超过 100 万的标黄" "清洗完后自动生成数据质量报告(重复率、空值率、异常值统计)"
🐍 Python 对比教学(顺手多学一手)
同样需求,Python 用 pandas:
import pandas as pddf = pd.read_excel("清洗源.xlsx")# 去重df = df.drop_duplicates(subset=["订单号"], keep="first")# 删空行df = df.dropna(how="all")# 去空格df["客户名"] = df["客户名"].str.strip().str.replace(r"\s+", " ", regex=True)df["产品名"] = df["产品名"].str.strip().str.replace(r"\s+", " ", regex=True)# 转数字df["金额"] = pd.to_numeric(df["金额"].astype(str).str.replace(",", ""), errors="coerce")df.to_excel("清洗后.xlsx", index=False)
对比:pandas 链式调用更简洁,但 VBA 宏在同事电脑上零部署直接跑。

⚠️ 排错速查
报错 | 原因 | 修法 |
|---|---|---|
运行时错误 13:类型不匹配 |
| 检查是否有非数字字符(如"暂无""N/A"),加 |
清洗后数据全没了 |
| 检查末行计算逻辑 |
辅助列 H 没清掉 | 代码异常中断 | 手动删 H 列,或在错误处理里加 |
宏运行完 Excel 卡死 | 没恢复 | 错误处理里也要恢复 |
📌 本讲小结
你今天拿到了 | 能力 |
|---|---|
完整清洗宏 | 去重+删空行+去空格+清乱码+转数字 |
倒序删行 | VBA 数据清洗第一铁律 |
辅助列标记法 | 比 |
Trim+Clean+Replace 三连 | 覆盖 99% 脏字符 |
排错清单 | 跳行/漏删/类型不匹配一眼定位 |
核心认知:数据清洗不是"删删删",是先标记再统一处理。倒序删行、辅助列标记、三连击去脏——这三个套路记住,以后任何清洗需求都能套。
📢 下节预告
第 8 讲|格式刷失效?让 AI 写统一排版宏
数据洗干净了,但格式还是乱的:列宽参差不齐、有的有边框有的没有、数字格式不统一。下一讲教你写"统一排版宏",一键搞定列宽、边框、字体、数字格式、冻结首行,让表格秒变专业报表。
💬 互动时间
你手头有没有"清洗完还是不对"的脏数据?描述你的数据问题(有什么脏、在哪列、想要什么结果),我帮你把提示词精修到能直接用。















































































