夜雨聆风学习资料网

ARTICLE · 1131916

Excel VBA编程-一键拆分

Excel VBA编程-一键拆分

本期知识点来源(来自网络实战技巧)

上网搜 Excel VBA 实用技巧时,有一个办公里特别高频的痛点:一张大表里混着好多类别的数据,想按某个类别(比如"部门""地区""销售员")拆成一张张小表,各自发给对应的人。

国外 Excel 教学站 ExcelOwl、ExcelErrorFinder、ExcelDemy 以及微软官方论坛都给出了同一个思路:按某一列的值,让 VBA 自动建新表,再把"属于这个值"的行整行搬过去。例如一张全国销售表,按"地区"一列一点,就变成"华北""华东""华南"三张表。

我们在这个思路上,今天扩展出 3 个由浅入深的实战案例。核心就三句话:找类别 → 建新表 → 搬对应行。下面三个案例全都是这个套路,只是越来越省事。


案例 1(简单):按第 1 列(A 列)一键拆分

功能说明:你的数据第 1 列就是"类别"(比如 A 列写着部门名),运行后,VBA 会自动找出所有不同的部门,每个部门建一张表,并把对应的行整行搬过去。适合"类别就在第 1 列"的最常见情况。

代码(按 Alt + F11 打开编辑器 → 插入「标准模块」→ 粘贴下面全部内容,含最下方的函数):

Sub 一键拆分_简单()    Dim 主表 As Worksheet    Dim 清单表 As Worksheet    Dim 最后行 As Long, i As Long, j As Long, k As Long    Dim 拆分列 As Long    Dim 当前值 As String    Dim 清单行 As Long    Dim 已记录 As Boolean    Dim 目标表 As Worksheet    Dim 目标行 As Long    Set 主表 = ActiveSheet    拆分列 = 1   ' 按第 1 列(A 列)拆分,要按 B 列就改成 2    最后行 = 主表.Cells(主表.Rows.Count, 拆分列).End(xlUp).Row    ' 建一张临时清单表,记下出现过的不同类别    Set 清单表 = Sheets.Add    清单表.Name = "临时清单"    清单行 = 1    ' 第一遍:找出所有不同的类别    For i = 2 To 最后行        当前值 = CStr(主表.Cells(i, 拆分列).Value)        If 当前值 <> "" Then            已记录 = False            For j = 1 To 清单行 - 1                If CStr(清单表.Cells(j, 1).Value) = 当前值 Then                    已记录 = True                    Exit For                End If            Next j            If 已记录 = False Then                清单表.Cells(清单行, 1).Value = 当前值                清单行 = 清单行 + 1            End If        End If    Next i    ' 如果以前拆过、存在同名表,先删掉,保证重新拆是干净的    Application.DisplayAlerts = False    For j = 1 To 清单行 - 1        For k = Sheets.Count To 1 Step -1            If Sheets(k).Name = 清洗表名(CStr(清单表.Cells(j, 1).Value)) Then                Sheets(k).Delete            End If        Next k    Next j    Application.DisplayAlerts = True    ' 第二遍:每个类别建一张表,把对应的行搬过去    For j = 1 To 清单行 - 1        当前值 = CStr(清单表.Cells(j, 1).Value)        Set 目标表 = Sheets.Add(After:=Sheets(Sheets.Count))        目标表.Name = 清洗表名(当前值)        主表.Rows(1).Copy 目标表.Rows(1)   ' 先搬表头        目标行 = 2        For i = 2 To 最后行            If CStr(主表.Cells(i, 拆分列).Value) = 当前值 Then                主表.Rows(i).Copy 目标表.Rows(目标行)                目标行 = 目标行 + 1            End If        Next i        目标表.Columns.AutoFit    Next j    ' 删掉临时清单表,不在工作簿里留垃圾    Application.DisplayAlerts = False    清单表.Delete    Application.DisplayAlerts = True    主表.Activate    MsgBox "拆分完成!共生成 " & (清单行 - 1) & " 张表。", vbInformationEnd Sub' 把类别名整理成合法的工作表名(去掉非法符号,最长 31 字)Function 清洗表名(名称 As String) As String    清洗表名 = Replace(Replace(Replace(Replace(Replace(Replace(名称, "/", " "), "\", " "), "?", " "), "*", " "), "[", " "), "]", " ")    清洗表名 = Left(清洗表名, 31)End Function

操作步骤:

  1. 在 Excel 里建一张表:第 1 行是表头(如"姓名,部门,金额"),第 1 列(A 列)写类别(如"销售部""技术部""财务部",每个可重复多行)。
  2. 按上面建好模块、把整段代码(含下方函数)一起粘贴进去。
  3. 把光标放在 一键拆分_简单 里,按 F5 运行(或回 Excel 按 Alt + F8 选它运行)。
  4. 看结果:工作簿里多出了"销售部""技术部""财务部"几张表,每张只有自己部门的数据,表头也带上了。

案例 2(中等):运行时任你选"按第几列"拆分

功能说明:案例 1 写死了"按第 1 列"。这个版本运行时弹个小框,问你"要按第几列拆分",你输入 1、2、3……就能按任意列拆,不用改代码。更灵活,适合列位置不固定的表。

代码:

Sub 一键拆分_中等()    Dim 主表 As Worksheet    Dim 清单表 As Worksheet    Dim 最后行 As Long, i As Long, j As Long, k As Long    Dim 拆分列 As Long    Dim 当前值 As String    Dim 清单行 As Long    Dim 已记录 As Boolean    Dim 目标表 As Worksheet    Dim 目标行 As Long    Set 主表 = ActiveSheet    ' 运行时让你输入按第几列拆分(A=1, B=2, C=3...)    拆分列 = Val(InputBox("要按第几列拆分?" & vbCrLf & "A 列输入 1,B 列输入 2,以此类推:", "选择拆分列"))    If 拆分列 < 1 Then        MsgBox "已取消或输入无效,请重新运行并输入数字。", vbExclamation        Exit Sub    End If    最后行 = 主表.Cells(主表.Rows.Count, 拆分列).End(xlUp).Row    Set 清单表 = Sheets.Add    清单表.Name = "临时清单"    清单行 = 1    For i = 2 To 最后行        当前值 = CStr(主表.Cells(i, 拆分列).Value)        If 当前值 <> "" Then            已记录 = False            For j = 1 To 清单行 - 1                If CStr(清单表.Cells(j, 1).Value) = 当前值 Then                    已记录 = True                    Exit For                End If            Next j            If 已记录 = False Then                清单表.Cells(清单行, 1).Value = 当前值                清单行 = 清单行 + 1            End If        End If    Next i    Application.DisplayAlerts = False    For j = 1 To 清单行 - 1        For k = Sheets.Count To 1 Step -1            If Sheets(k).Name = 清洗表名(CStr(清单表.Cells(j, 1).Value)) Then                Sheets(k).Delete            End If        Next k    Next j    Application.DisplayAlerts = True    For j = 1 To 清单行 - 1        当前值 = CStr(清单表.Cells(j, 1).Value)        Set 目标表 = Sheets.Add(After:=Sheets(Sheets.Count))        目标表.Name = 清洗表名(当前值)        主表.Rows(1).Copy 目标表.Rows(1)        目标行 = 2        For i = 2 To 最后行            If CStr(主表.Cells(i, 拆分列).Value) = 当前值 Then                主表.Rows(i).Copy 目标表.Rows(目标行)                目标行 = 目标行 + 1            End If        Next i        目标表.Columns.AutoFit    Next j    Application.DisplayAlerts = False    清单表.Delete    Application.DisplayAlerts = True    主表.Activate    MsgBox "拆分完成!共生成 " & (清单行 - 1) & " 张表。", vbInformationEnd SubFunction 清洗表名(名称 As String) As String    清洗表名 = Replace(Replace(Replace(Replace(Replace(Replace(名称, "/", " "), "\", " "), "?", " "), "*", " "), "[", " "), "]", " ")    清洗表名 = Left(清洗表名, 31)End Function

操作步骤:

  1. 准备一张表,这次类别可能在第 2 列(B 列)或第 3 列(C 列)。
  2. 粘贴代码后按 F5 运行。
  3. 弹出输入框,比如类别在 B 列就输入 2,回车。
  4. 立刻按你选的列拆好;弹窗告诉你生成了几张表。

案例 3(实用小案例):拆分完再送你一张"拆分汇总"

功能说明:光拆开还不够,领导往往还要看"每个类别各多少行"。这个版本在拆完后,自动在最前面生成一张「拆分汇总」表,列出每个类别名和对应行数(用 CountIf 统计)。一发就是"各部门明细 + 一张总览",特别适合月底分发和汇报。

代码:

Sub 一键拆分_带汇总()    Dim 主表 As Worksheet    Dim 清单表 As Worksheet    Dim 汇总表 As Worksheet    Dim 最后行 As Long, i As Long, j As Long, k As Long    Dim 拆分列 As Long    Dim 当前值 As String    Dim 清单行 As Long    Dim 已记录 As Boolean    Dim 目标表 As Worksheet    Dim 目标行 As Long    Dim 行数 As Long    Set 主表 = ActiveSheet    拆分列 = 2   ' 本例默认按第 2 列(B 列)拆分,可改成别的列    最后行 = 主表.Cells(主表.Rows.Count, 拆分列).End(xlUp).Row    Set 清单表 = Sheets.Add    清单表.Name = "临时清单"    清单行 = 1    For i = 2 To 最后行        当前值 = CStr(主表.Cells(i, 拆分列).Value)        If 当前值 <> "" Then            已记录 = False            For j = 1 To 清单行 - 1                If CStr(清单表.Cells(j, 1).Value) = 当前值 Then                    已记录 = True                    Exit For                End If            Next j            If 已记录 = False Then                清单表.Cells(清单行, 1).Value = 当前值                清单行 = 清单行 + 1            End If        End If    Next i    Application.DisplayAlerts = False    For j = 1 To 清单行 - 1        For k = Sheets.Count To 1 Step -1            If Sheets(k).Name = 清洗表名(CStr(清单表.Cells(j, 1).Value)) Then                Sheets(k).Delete            End If        Next k    Next j    ' 若已有一张"拆分汇总",也先删掉    For k = Sheets.Count To 1 Step -1        If Sheets(k).Name = "拆分汇总" Then            Sheets(k).Delete        End If    Next k    Application.DisplayAlerts = True    For j = 1 To 清单行 - 1        当前值 = CStr(清单表.Cells(j, 1).Value)        Set 目标表 = Sheets.Add(After:=Sheets(Sheets.Count))        目标表.Name = 清洗表名(当前值)        主表.Rows(1).Copy 目标表.Rows(1)        目标行 = 2        For i = 2 To 最后行            If CStr(主表.Cells(i, 拆分列).Value) = 当前值 Then                主表.Rows(i).Copy 目标表.Rows(目标行)                目标行 = 目标行 + 1            End If        Next i        目标表.Columns.AutoFit    Next j    ' 生成"拆分汇总"表:类别名 + 行数    Set 汇总表 = Sheets.Add(Before:=Sheets(1))    汇总表.Name = "拆分汇总"    汇总表.Range("A1").Value = "类别"    汇总表.Range("B1").Value = "行数"    汇总表.Range("A1:B1").Font.Bold = True    For j = 1 To 清单行 - 1        当前值 = CStr(清单表.Cells(j, 1).Value)        行数 = WorksheetFunction.CountIf(主表.Range(主表.Cells(2, 拆分列), 主表.Cells(最后行, 拆分列)), 当前值)        汇总表.Cells(j + 1, 1).Value = 当前值        汇总表.Cells(j + 1, 2).Value = 行数    Next j    汇总表.Columns.AutoFit    Application.DisplayAlerts = False    清单表.Delete    Application.DisplayAlerts = True    主表.Activate    MsgBox "拆分完成!生成 " & (清单行 - 1) & " 张明细表,外加 1 张「拆分汇总」。", vbInformationEnd SubFunction 清洗表名(名称 As String) As String    清洗表名 = Replace(Replace(Replace(Replace(Replace(Replace(名称, "/", " "), "\", " "), "?", " "), "*", " "), "[", " "), "]", " ")    清洗表名 = Left(清洗表名, 31)End Function

操作步骤:

  1. 准备一张表,类别放在 B 列(想换列就改代码里的 拆分列 = 2)。
  2. 粘贴代码按 F5 运行。
  3. 看结果:每张部门明细表照常生成;最前面还多了一张「拆分汇总」,A 列是类别、B 列是行数(例如"销售部 | 12")。
  4. 把整本工作簿发给领导,他先看汇总、再点进明细,清清楚楚。

本篇小结

  • 拆分核心就一句:找出拆分列里的不同类别 → 每类建一张表 → 把对应行整行搬过去。
  • 案例 1 按固定第 1 列拆;案例 2 用 InputBox 让你临时选列,更灵活;案例 3 额外生成「拆分汇总」用 CountIf 统计每类行数,适合汇报。
  • Sheets.Add 建新表,主表.Rows(i).Copy 目标表.Rows(目标行) 整行搬运,目标表.Columns.AutoFit 自动调宽列。
  • 清洗表名 函数负责把类别名整理成合法表名(去掉 / \ ? * [ ] 并截到 31 字),类别名里最好别带这些符号。
  • 每次运行前会自动删掉同名的旧表,所以可以反复运行、越跑越干净。

下一篇预告

Excel VBA编程-一键批量生成工资条:把一行员工信息,自动变成每人一张、带表头的工资条,批量打印不发愁。

相关学习资料