当前位置:首页 > 办公设计 > Office教程 > 写几段代码,将总表按任意列拆分为多个工作簿

写几段代码,将总表按任意列拆分为多个工作簿

1年前 (2025-05-24)Office教程1340

大家好,我是星光。
今天和大家分享的VBA小代码是:一键将总表按任意列拆分为多个工作簿

什么意思呢?举个小栗子。
如下图所示,是一张总表,现在需要按任意列,比如班级列吧,将它拆分为多个工作簿。

动画演示如下:

VBA代码如下:

Sub SplitShByArr()
Dim shtAct As Worksheet, sht As Worksheet, wb As Workbook
Dim rngData As Range, rngGistC As Range, rngTemp As Range
Dim d As Object, aData, aKeys, vnt
Dim intTitCount, strKey As String, strName As String
Dim strADS As String, rngTit As Range
Dim i As Long, j As Long, intFirstR As Long, intLastR As Long
Dim k As Long, x As Long, intActR As Long
Dim intFirstC As Long, intGistC As Long
Dim strPath As String
On Error Resume Next '忽略错误继续运行程序
'
strPath = getStrPath() '用户选择文件保存路径
If strPath = "" Then Exit Sub
'
'获取用户输入的标题行数▼
intTitCount = getTitCount()
If intTitCount = False Then Exit Sub
'
'获取拆分依据列▼
Set rngGistC = GetRngGistC()
If Err.Number Then GoTo errDescript
'
Call disAppSet '取消屏幕刷新等系统设置
'
Set shtAct = ActiveSheet '当前工作表
If shtAct.FilterMode = True Then shtAct.Cells.AutoFilter '取消筛选状态
Set rngData = shtAct.UsedRange '实际区域
aData = rngData.Value '总表数据存入数组aData
intFirstC = rngData.Column '实际区域开始列
intGistC = rngGistC.Column - intFirstC + 1 '依据列在aData中的序列
intFirstR = rngData.Row '实际区域开始行
intActR = intTitCount - intFirstR + 2 '扣除标题的数组开始行
intLastR = GetintLastR(shtAct) '实际区域结束行
With shtAct '标题区域
Set rngTit = .Range(.Cells(1, 1), _
.Cells(intTitCount, _
UBound(aData, 2) + intFirstC - 1))
End With
'
'参数数组,修正异常数据▼
Set d = CreateObject("scripting.dictionary") '后期字典
ReDim aRef(1 To intLastR) '数组aRef,修正拆分列特殊数据
For i = intActR To UBound(aData)
If i > intLastR Then Exit For '如果大于有效数据最大行则退出循环
vnt = aData(i, intGistC)
If IsError(vnt) Then
aRef(i) = "错误值"
ElseIf vnt = "" Then
aRef(i) = "空白单元格"
ElseIf IsDate(vnt) Then '避免日期斜杠格式无法创建工作簿/表
aRef(i) = Format(vnt, "yyyy-m-d")
Else
aRef(i) = vnt
End If
strKey = aRef(i)
d(strKey) = d(strKey) + 1 '记录不同拆分关键字的数量
Next
'
'通过前8行数据来判断该列是否为特殊的文本数值
For j = 1 To UBound(aData, 2) '遍历列
For i = intActR To UBound(aData) '遍历前8行
If i > 8 Then Exit For
vnt = aData(i, j)
If IsNumeric(vnt) Then '是否数值
If VarType(aData(i, j)) = 8 Then '是否文本
strADS = strADS & "," & Cells(1, j + intFirstC - 1).Address
Exit For
End If
End If
Next
Next
strADS = Mid(strADS, 2) '需要设置文本格式的单元格地址
'
aKeys = d.keys '字典Keys,拆分关键字数组
For i = 0 To UBound(aKeys) '遍历关键字
strName = aKeys(i) '关键字
ReDim aRes(1 To d(strName), 1 To UBound(aData, 2)) '结果数组
k = 0 '计数器归0
'
'筛选符合条件的记录存入结果数组
For x = 1 To UBound(aRef)
If aRef(x) = strName Then '如果关键字符合
k = k + 1 '累加符合条件的行
For j = 1 To UBound(aData, 2) '遍历列
aRes(k, j) = aData(x, j) '数据存入结果数组
Next
End If
Next
'
'建立新工作簿,存放结果数组
Set wb = Workbooks.Add
With wb.Worksheets(1)
.Name = strName '命名
If Err.Number Then '如果名称有特殊字符,则退出程序
.Delete
wb.Close False
GoTo errDescript
End If
If Len(strADS) Then
.Range(strADS).EntireColumn.NumberFormat = "@" '特殊列设置为文本格式
End If
With .Cells(intTitCount + 1, intFirstC).Resize(k, UBound(aRes, 2))
.Value = aRes '结果数组数据写入工作表
End With
.UsedRange.Borders.LineStyle = 1 '设置边框线
rngTit.Copy
.Range("a1").PasteSpecial xlPasteColumnWidths '粘贴列宽
.Range("a1").PasteSpecial xlPasteAll '粘贴标题
End With
wb.SaveAs strPath & strName
wb.Close False
Next
errDescript:
shtAct.Select
Call reAppSet '恢复屏幕刷新等系统设置
Set d = Nothing '释放字典内存
If Err.Number Then
MsgBox Err.Description
Else
MsgBox "拆分完成。"
End If
End Sub

'用户选择文件夹路径
Function getStrPath() As String
Dim strPath As String
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show Then
strPath = .SelectedItems(1)
Else '如用户为选中文件夹则退出
Exit Function
End If
End With
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
getStrPath = strPath
End Function

'获取用户输入的标题行数
Function getTitCount()
Dim intTitCount
intTitCount = InputBox("请输入标题行的行数", _
Title:="公众号Excel星球", _
Default:=1)
If StrPtr(intTitCount) = False Then
getTitCount = False
Exit Function
End If
If IsNumeric(intTitCount) = False Then
MsgBox "标题行的行数只能输入数字。"
getTitCount = False
Exit Function
End If
If intTitCount < 0 Then MsgBox "标题行数不能为负数。" getTitCount = False Exit Function End If getTitCount = intTitCount End Function '用户选择拆分依据列 Function GetRngGistC() As Range Dim rngGistC As Range Set rngGistC = Application.InputBox("请选择拆分依据列。", _ Title:="公众号Excel星球", _ Default:=Selection.Address, _ Type:=8) If rngGistC Is Nothing Then Exit Function End If If rngGistC.Columns.Count > 1 Then
MsgBox "拆分依据列只能是单列。"
Exit Function
End If
Set GetRngGistC = rngGistC
End Function

'取消屏幕刷新,公式重算等
Sub disAppSet()
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
.DisplayAlerts = False
End With
End Sub

'恢复屏幕刷新等
Sub reAppSet()
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.DisplayAlerts = True
End With
End Sub

'最大数据有效行
Function GetintLastR(ByVal sht As Worksheet)
GetintLastR = sht.Cells.Find("*", _
LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
End Function

代码详细解释见注释,概要说明如下▼

第13至第14行代码,调用getStrPath函数过程,打开文件浏览对话框,允许用户选择任意文件夹作为数据源;如果用户未选取文件夹,则退出程序。

第17至第18行代码,调用getTitCount过程,允许用户输入指定行数的标题行。

第21至第22行代码,调用GetRngGistC过程,允许用户选择拆分依据列。

第24行代码,调用disAppSet过程,取消屏幕刷新等系统设置。

第26至第34行代码将总表数据存入数组aData,并获取获取总表实际存在数据的区域、首列、拆分依据列在实际区域中的第几列、首行和尾行等重要数据。这是由于首行首列未必是第一行第一列,比如本例所示的数据,也就导致拆分依据列的列标未必是实际处理数据的列标。

第35至第39行代码计算标题区域,并赋值变量rngTit。

第41行至第58行代码遍历拆分依据列,处理异常值,比如空格、错误值和可能以”/”为格式的日期值。

第61至第72行代码通过前8行数据判断相关列是否为文本格式,避免文本型数值,比如身份证,在拆分后变形。代码将文本型数值所在的单元格地址赋值变量strADS。

第75至第113行代码按关键字拆分总表数据。其中第82至第89行代码遍历数据源将符合条件的数据存入数组aRes。第92至110行代码新建工作簿,并将结果数组的数据写入该工作簿的首个工作表,并设置标题行。

第118至第122行代码使用MsgBox函数以消息框的形式显示数据拆分结果信息。

……

示例下载,百度网盘▼
https://pan.baidu.com/s/1L2n62GIfURP09QXlIuzOwQ
提取码: tejq

扫描二维码推送至手机访问。

欢迎转载或分享本篇文章。

本文链接:https://www.jcba123.com/article/1625

分享给朋友:

“写几段代码,将总表按任意列拆分为多个工作簿” 的相关文章

Excel基础排序法,怎么进行升序、降序排序

Excel基础排序法,怎么进行升序、降序排序

Excel中的排序功能是非常强大的,它能够解决我们日常办公中许多问题。例如,成绩排名、公司业绩排名等这些数据表格,我们可以通过排序功能轻松的帮助我们搞定。这里,我们先来学习第一课,Excel排序的基础用法,升序、降序的使用技巧。     原始表格 如下图所示,这...

Excel数据在同一单元格中该如何运算公式求和?

Excel数据在同一单元格中该如何运算公式求和?

在一些表格中我们需要将所有的数据都录入到一个单元格中运算公式,而一般的公式都是在不同单元格运算的,这种情况我们应该如何运算呢?这里小汪老师就给大家分享几种常用的方法。   1、自定义名称 首先,进入「公式」-「定义的名称」-「定义名称」,在名称中随便输入一个名字,这里我就输入「求...

Excel常用函数公式20例

Excel常用函数公式20例

下面是一组常用Excel函数公式的用法,学会这些套路,让工作效率再高一丢丢。 1、IF函数条件判断 IF函数是最常用的判断类函数之一,能完成非此即彼的判断。 如下图,考核得分的标准为9分,要判断B列的考核成绩是否合格。 =IF(B4>=9,”合格”,”不合格”) IF,相当于普通...

将多列的区域或数组合并成一列,就用TOCOL函数

将多列的区域或数组合并成一列,就用TOCOL函数

今天分享TOCOL函数的几个典型应用。 这个函数目前可以在Excel 365和最新的WPS表格中使用,作用是将多列的区域或数组转换为单列。函数用法为: =TOCOL(要转换的数组或引用, [是否忽略指定类型的值], [按行/列扫描]) 其中第二参数为0或者省略该参数时,表示保留所有值。为1表示忽略空...

PPT屏外取色使用指南

PPT屏外取色使用指南

先,打开PPT软件并创建一个新的空白演示文稿。接着,新建幻灯片并插入一个圆形。选中该圆形,点击形状填充选项中的"取色器"。现在,只需按住鼠标左键不放,您就可以将取色器拖动到幻灯片以外,甚至是屏幕以外的任何位置,轻松获取所需的颜色。这一便捷功能将大大提升您在PPT制作过程中的工作效率。...

打造复古3D科技海报PPT设计教程

打造复古3D科技海报PPT设计教程

第一步:打开PPT软件,创建一个空白演示文稿,新建幻灯片,并填充黑色背景.点击工具栏的插入——文本框,输入英文文字“RETURN ORIGIN”(如图1-1),在选择字体上建议笔划粗,且棱角尖锐的比较好看,我选择的字体是Lemon/Milk,你也可以根据喜好选择其他字体。接着给英文设置倾斜效...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。