1234

ExcelHome技术论坛

用户名  找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

帖子
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 265|回复: 13

[求助] 工作簿拆分VBA代码问题求助

[复制链接]

TA的精华主题

TA的得分主题

发表于 2025-3-13 15:44 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
请根据以下内容生成vba代码:在当前工作簿运行代码后,弹出提示框询问选择哪一个工作簿,选择好的工作簿里有多个工作表,每个工作表的表头均为一列,每个工作表的a列的内容均为人员姓名,现在需要按照a列拆为多个工作簿,同一人员的不同工作表需拆分在同一个工作簿。拆分后的工作簿命名规则为“被拆分的工作簿名称+人员姓名+拆分时的年月日(例如2023-3-13)”
但当生成代码后运行出现了“collectnames编译错误子过程或函数未定义”等一系列问题,为此请求各位老师协助,谢谢!需要拆分的工作簿请见附件

汇总表.rar

2.67 KB, 下载次数: 7

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-13 15:52 | 显示全部楼层
Sub SplitWorkbooksByPerson()
    Dim sourceWorkbook As Workbook
    Dim targetWorkbook As Workbook
    Dim selectedFile As String
    Dim dict As Object
    Dim ws As Worksheet
    Dim person As Variant
    Dim newWorkbookPath As String
    Dim sourceWorkbookName As String
    Dim currentDate As String
    Dim personName As String
   
    ' 设置日期格式
    currentDate = Format(Date, "yyyy-m-d")
   
    ' 选择文件对话框
    With Application.FileDialog(msoFileDialogFilePicker)
        .Title = "请选择要拆分的工作簿"
        .Filters.Clear
        .Filters.Add "Excel文件", "*.xlsx;*.xls"
        If .Show = -1 Then
            selectedFile = .SelectedItems(1)
        Else
            MsgBox "未选择文件,程序退出。"
            Exit Sub
        End If
    End With
   
    ' 打开源工作簿
    Set sourceWorkbook = Workbooks.Open(selectedFile)
    sourceWorkbookName = CleanFileName(Replace(sourceWorkbook.Name, ".xlsx", ""))
    sourceWorkbookName = CleanFileName(Replace(sourceWorkbookName, ".xls", ""))
   
    ' 创建字典收集唯一姓名
    Set dict = CreateObject("Scripting.Dictionary")
    CollectNames sourceWorkbook, dict
   
    If dict.Count = 0 Then
        MsgBox "源工作簿中没有有效数据。"
        sourceWorkbook.Close False
        Exit Sub
    End If
   
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
   
    ' 遍历每个人员
    For Each person In dict.Keys
        personName = CleanFileName(CStr(person))
        
        ' 创建新工作簿
        Set targetWorkbook = Workbooks.Add
        RemoveInitialSheet targetWorkbook
        
        ' 处理每个工作表
        ProcessWorksheets sourceWorkbook, targetWorkbook, person
        
        ' 保存并关闭工作簿
        If targetWorkbook.Worksheets.Count > 0 Then
            newWorkbookPath = GenerateUniquePath(sourceWorkbook, sourceWorkbookName, personName, currentDate)
            targetWorkbook.SaveAs newWorkbookPath, xlOpenXMLWorkbook
            MsgBox "已创建文件:" & newWorkbookPath
        End If
        targetWorkbook.Close False
    Next person
   
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    sourceWorkbook.Close
    MsgBox "全部文件拆分完成!"
End Sub

' 收集所有人员姓名
Sub CollectMethods(wb As Workbook, d As Object)
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim cell As Range
   
    For Each ws In wb.Worksheets
        lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
        If lastRow > 1 Then
            For Each cell In ws.Range("A2:A" & lastRow)
                If Not IsEmpty(cell.Value) Then
                    d(CleanFileName(Trim(cell.Value))) = 1
                End If
            Next
        End If
    Next
End Sub

' 处理工作表数据
Sub ProcessWorksheets(srcWb As Workbook, tgtWb As Workbook, person As String)
    Dim ws As Worksheet
    Dim newWs As Worksheet
    Dim filterRange As Range
   
    For Each ws In srcWb.Worksheets
        With ws
            If .AutoFilterMode Then .AutoFilterMode = False
            Dim lastRow As Long
            lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
            If lastRow > 1 Then
                .Range("A1:A" & lastRow).AutoFilter Field:=1, Criteria1:=person
                Set filterRange = .AutoFilter.Range.SpecialCells(xlCellTypeVisible)
                If Not filterRange Is Nothing Then
                    Set newWs = tgtWb.Worksheets.Add(After:=tgtWb.Worksheets(tgtWb.Worksheets.Count))
                    newWs.Name = GetUniqueSheetName(tgtWb, ws.Name)
                    .UsedRange.Copy newWs.Range("A1")
                End If
                .AutoFilterMode = False
            End If
        End With
    Next
End Sub

' 生成唯一文件名
Function GenerateUniquePath(srcWb As Workbook, baseName As String, person As String, dateStr As String) As String
    Dim counter As Long
    Dim path As String
    path = srcWb.Path & "\" & baseName & "_" & person & "_" & dateStr & ".xlsx"
   
    While Len(Dir(path)) > 0
        counter = counter + 1
        path = srcWb.Path & "\" & baseName & "_" & person & "_" & dateStr & "(" & counter & ").xlsx"
    Wend
    GenerateUniquePath = path
End Function

' 清理非法字符
Function CleanFileName(text As String) As String
    Dim illegalChars As String
    illegalChars = "\/:*?""<>|"
    Dim i As Integer
    For i = 1 To Len(illegalChars)
        text = Replace(text, Mid(illegalChars, i, 1), "_")
    Next
    CleanFileName = text
End Function

' 删除初始空白表
Sub RemoveInitialSheet(wb As Workbook)
    While wb.Worksheets.Count > 1
        Application.DisplayAlerts = False
        wb.Worksheets(1).Delete
        Application.DisplayAlerts = True
    Wend
End Sub

' 获取唯一工作表名
Function GetUniqueSheetName(wb As Workbook, originalName As String) As String
    Dim baseName As String
    Dim counter As Long
   
    baseName = Left(originalName, 27) ' 工作表名最大长度31字符
    If Not WorksheetExists(wb, baseName) Then
        GetUniqueSheetName = baseName
        Exit Function
    End If
   
    Do
        counter = counter + 1
    While WorksheetExists(wb, baseName & "(" & counter & ")")
   
    GetUniqueSheetName = baseName & "(" & counter & ")"
End Function

' 检查工作表是否存在
Function WorksheetExists(wb As Workbook, sheetName As String) As Boolean
    On Error Resume Next
    WorksheetExists = Not wb.Worksheets(sheetName) Is Nothing
    On Error GoTo 0
End Function

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-13 15:53 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
不好意思,代码未上传

Sub SplitWorkbooksByPerson()
    Dim sourceWorkbook As Workbook
    Dim targetWorkbook As Workbook
    Dim selectedFile As String
    Dim dict As Object
    Dim ws As Worksheet
    Dim person As Variant
    Dim newWorkbookPath As String
    Dim sourceWorkbookName As String
    Dim currentDate As String
    Dim personName As String
   
    ' 设置日期格式
    currentDate = Format(Date, "yyyy-m-d")
   
    ' 选择文件对话框
    With Application.FileDialog(msoFileDialogFilePicker)
        .Title = "请选择要拆分的工作簿"
        .Filters.Clear
        .Filters.Add "Excel文件", "*.xlsx;*.xls"
        If .Show = -1 Then
            selectedFile = .SelectedItems(1)
        Else
            MsgBox "未选择文件,程序退出。"
            Exit Sub
        End If
    End With
   
    ' 打开源工作簿
    Set sourceWorkbook = Workbooks.Open(selectedFile)
    sourceWorkbookName = CleanFileName(Replace(sourceWorkbook.Name, ".xlsx", ""))
    sourceWorkbookName = CleanFileName(Replace(sourceWorkbookName, ".xls", ""))
   
    ' 创建字典收集唯一姓名
    Set dict = CreateObject("Scripting.Dictionary")
    CollectNames sourceWorkbook, dict
   
    If dict.Count = 0 Then
        MsgBox "源工作簿中没有有效数据。"
        sourceWorkbook.Close False
        Exit Sub
    End If
   
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
   
    ' 遍历每个人员
    For Each person In dict.Keys
        personName = CleanFileName(CStr(person))
        
        ' 创建新工作簿
        Set targetWorkbook = Workbooks.Add
        RemoveInitialSheet targetWorkbook
        
        ' 处理每个工作表
        ProcessWorksheets sourceWorkbook, targetWorkbook, person
        
        ' 保存并关闭工作簿
        If targetWorkbook.Worksheets.Count > 0 Then
            newWorkbookPath = GenerateUniquePath(sourceWorkbook, sourceWorkbookName, personName, currentDate)
            targetWorkbook.SaveAs newWorkbookPath, xlOpenXMLWorkbook
            MsgBox "已创建文件:" & newWorkbookPath
        End If
        targetWorkbook.Close False
    Next person
   
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    sourceWorkbook.Close
    MsgBox "全部文件拆分完成!"
End Sub

' 收集所有人员姓名
Sub CollectMethods(wb As Workbook, d As Object)
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim cell As Range
   
    For Each ws In wb.Worksheets
        lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
        If lastRow > 1 Then
            For Each cell In ws.Range("A2:A" & lastRow)
                If Not IsEmpty(cell.Value) Then
                    d(CleanFileName(Trim(cell.Value))) = 1
                End If
            Next
        End If
    Next
End Sub

' 处理工作表数据
Sub ProcessWorksheets(srcWb As Workbook, tgtWb As Workbook, person As String)
    Dim ws As Worksheet
    Dim newWs As Worksheet
    Dim filterRange As Range
   
    For Each ws In srcWb.Worksheets
        With ws
            If .AutoFilterMode Then .AutoFilterMode = False
            Dim lastRow As Long
            lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
            If lastRow > 1 Then
                .Range("A1:A" & lastRow).AutoFilter Field:=1, Criteria1:=person
                Set filterRange = .AutoFilter.Range.SpecialCells(xlCellTypeVisible)
                If Not filterRange Is Nothing Then
                    Set newWs = tgtWb.Worksheets.Add(After:=tgtWb.Worksheets(tgtWb.Worksheets.Count))
                    newWs.Name = GetUniqueSheetName(tgtWb, ws.Name)
                    .UsedRange.Copy newWs.Range("A1")
                End If
                .AutoFilterMode = False
            End If
        End With
    Next
End Sub

' 生成唯一文件名
Function GenerateUniquePath(srcWb As Workbook, baseName As String, person As String, dateStr As String) As String
    Dim counter As Long
    Dim path As String
    path = srcWb.Path & "\" & baseName & "_" & person & "_" & dateStr & ".xlsx"
   
    While Len(Dir(path)) > 0
        counter = counter + 1
        path = srcWb.Path & "\" & baseName & "_" & person & "_" & dateStr & "(" & counter & ").xlsx"
    Wend
    GenerateUniquePath = path
End Function

' 清理非法字符
Function CleanFileName(text As String) As String
    Dim illegalChars As String
    illegalChars = "\/:*?""<>|"
    Dim i As Integer
    For i = 1 To Len(illegalChars)
        text = Replace(text, Mid(illegalChars, i, 1), "_")
    Next
    CleanFileName = text
End Function

' 删除初始空白表
Sub RemoveInitialSheet(wb As Workbook)
    While wb.Worksheets.Count > 1
        Application.DisplayAlerts = False
        wb.Worksheets(1).Delete
        Application.DisplayAlerts = True
    Wend
End Sub

' 获取唯一工作表名
Function GetUniqueSheetName(wb As Workbook, originalName As String) As String
    Dim baseName As String
    Dim counter As Long
   
    baseName = Left(originalName, 27) ' 工作表名最大长度31字符
    If Not WorksheetExists(wb, baseName) Then
        GetUniqueSheetName = baseName
        Exit Function
    End If
   
    Do
        counter = counter + 1
    While WorksheetExists(wb, baseName & "(" & counter & ")")
   
    GetUniqueSheetName = baseName & "(" & counter & ")"
End Function

' 检查工作表是否存在
Function WorksheetExists(wb As Workbook, sheetName As String) As Boolean
    On Error Resume Next
    WorksheetExists = Not wb.Worksheets(sheetName) Is Nothing
    On Error GoTo 0
End Function

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-13 15:53 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-13 15:56 | 显示全部楼层
不好意思,代码已上传,请下载这个附件,谢谢!

汇总表.rar

17.31 KB, 下载次数: 6

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-13 17:11 来自手机 | 显示全部楼层
苏阳湖wzy 发表于 2025-3-13 15:56
不好意思,代码已上传,请下载这个附件,谢谢!

有没有大神帮忙看一下

TA的精华主题

TA的得分主题

发表于 2025-3-13 18:37 | 显示全部楼层
附件供参考。。。

123.zip

33.72 KB, 下载次数: 11

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2025-3-13 18:39 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
  1. Sub ykcbf()   '//2025.3.13
  2.     Application.ScreenUpdating = False
  3.     Application.DisplayAlerts = False
  4.     Set fso = CreateObject("scripting.filesystemobject")
  5.     Set d = CreateObject("Scripting.Dictionary")
  6.     p = ThisWorkbook.Path & ""
  7.     On Error Resume Next
  8.     Dim tm: tm = Timer
  9.     With Application.FileDialog(msoFileDialogFilePicker)
  10.         .InitialFileName = p
  11.         .Title = "请选择对应Excel文件"
  12.         .AllowMultiSelect = False
  13.         .Filters.Clear
  14.         .Filters.Add "Excel文件", "*.xls*"
  15.         If .Show Then f = .SelectedItems(1) Else Exit Sub
  16.     End With
  17.     fn = fso.GetBaseName(f)
  18.     Set wb = Workbooks.Open(f, 0)
  19.     For Each sht In wb.Sheets
  20.         arr = sht.UsedRange
  21.         For i = 2 To UBound(arr)
  22.             If Len(arr(i, 1)) Then
  23.                 s = arr(i, 1)
  24.                 d(s) = ""
  25.             End If
  26.         Next
  27.     Next
  28.     For Each k In d.keys
  29.         wb.Sheets.Copy
  30.         Set wb1 = ActiveWorkbook
  31.         For Each sht In wb1.Sheets
  32.             With sht
  33.                 .DrawingObjects.Delete
  34.                 .Rows(1).AutoFilter Field:=1, Criteria1:="<>" & k
  35.                 .UsedRange.Offset(1).Delete
  36.                 If .FilterMode = True Then .ShowAllData
  37.             End With
  38.         Next
  39.         wb1.SaveAs p & fn & "+" & k & "+" & Format(Date, "yyyy-m-d")
  40.         wb1.Close
  41.     Next
  42.     wb.Close 0
  43.     Set d = Nothing
  44.     Application.ScreenUpdating = True
  45.     MsgBox "共用时:" & Format(Timer - tm, "0.000") & "秒!"
  46. End Sub

复制代码


评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2025-3-13 20:49 | 显示全部楼层
ykcbf1100 发表于 2025-3-13 18:37
附件供参考。。。


老师晚上好,如果是以下要求VBA代码又该如何呢?
有2个工作簿,一个工作簿是人员匹配表,该工作薄工作表中,a列为人员,b列为部门;另外一个工作簿是汇总表,该工作簿包含多个工作表,每个工作表都有一列是部门,现在要求在汇总表工作簿的每一个工作表中都在a列插入新的一列为人员,请将人员匹配表工作簿中相对应的人员匹配到汇总表工作簿的每一个工作表的a列中。
请见附件,万分感谢!!!

附件.rar

23.31 KB, 下载次数: 5

TA的精华主题

TA的得分主题

发表于 2025-3-14 08:28 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
  1. Sub test()
  2.     Dim r%, i%
  3.     Dim arr, brr
  4.     Dim wb As Workbook
  5.     Dim ws As Worksheet
  6.     Dim mypath$, myname$
  7.     Dim d As Object
  8.     Set d = CreateObject("scripting.dictionary")
  9.     mypath = ThisWorkbook.path & ""
  10.     myname = "人员匹配表.xlsx"
  11.     If Dir(mypath & myname) = "" Then
  12.         MsgBox "人员匹配表.xlsx不存在!"
  13.         Exit Sub
  14.     End If
  15.     Set wb = GetObject(mypath & myname)
  16.     With wb
  17.         With .Worksheets(1)
  18.             r = .Cells(.Rows.Count, 1).End(xlUp).Row
  19.             arr = .Range("a2:b" & r)
  20.             For i = 1 To UBound(arr)
  21.                 d(arr(i, 2)) = arr(i, 1)
  22.             Next
  23.         End With
  24.         .Close False
  25.     End With
  26.     With ThisWorkbook
  27.         For Each ws In .Worksheets
  28.             With ws
  29.                 c = .Cells(1, .Columns.Count).End(xlToLeft).Column
  30.                 arr = .Range("a1").Resize(1, c)
  31.                 For j = UBound(arr, 2) To 1 Step -1
  32.                     If arr(1, j) = "人员" Then
  33.                         .Columns(j).Delete
  34.                     End If
  35.                 Next
  36.                 .Columns(1).Insert
  37.                 r = .Cells(.Rows.Count, 2).End(xlUp).Row
  38.                 c = .Cells(1, .Columns.Count).End(xlToLeft).Column
  39.                 arr = .Range("a1").Resize(r, c)
  40.                 j0 = 0
  41.                 For j = 1 To UBound(arr, 2)
  42.                     If arr(1, j) = "部门" Then
  43.                         j0 = j
  44.                         Exit For
  45.                     End If
  46.                 Next
  47.                 If j0 <> 0 Then
  48.                     arr(1, 1) = "人员"
  49.                     For i = 2 To UBound(arr)
  50.                         If d.exists(arr(i, j0)) Then
  51.                             arr(i, 1) = d(arr(i, j0))
  52.                         End If
  53.                     Next
  54.                     .Range("a1").Resize(UBound(arr), UBound(arr, 2)) = arr
  55.                     With .Range("a1:a" & UBound(arr))
  56.                         .Borders.LineStyle = xlContinuous
  57.                     End With
  58.                 End If
  59.             End With
  60.         Next
  61.     End With
  62. End Sub
复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

1234

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2025-4-6 12:25 , Processed in 0.027384 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表