ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[求助] 表格拆分问题

[复制链接]

TA的精华主题

TA的得分主题

发表于 2024-8-28 07:20 | 显示全部楼层
按月份拆分
  1. Sub ykcbf2()   '//2024.8.28    按月份拆分
  2.     Application.ScreenUpdating = False
  3.     Application.DisplayAlerts = False
  4.     Dim tm: tm = Timer
  5.     Set fso = CreateObject("Scripting.FileSystemObject")
  6.     Set d = CreateObject("Scripting.Dictionary")
  7.     p = ThisWorkbook.Path & ""
  8.     Set ws = ThisWorkbook
  9.     Set sh = ws.Sheets("汇总表")
  10.     On Error Resume Next
  11.     arr = sh.UsedRange
  12.     For i = 2 To UBound(arr)
  13.         s = CStr(arr(i, 4)): ss = arr(i, 1)
  14.         If Not d.exists(s) Then Set d(s) = CreateObject("Scripting.Dictionary")
  15.         If Not d(s).exists(ss) Then
  16.             d(s)(ss) = Array(arr(i, 2), arr(i, 3))
  17.         Else
  18.             t = d(s)(ss)
  19.             t(0) = t(0) + arr(i, 2)
  20.             t(1) = t(1) + arr(i, 3)
  21.             d(s)(ss) = t
  22.         End If
  23.     Next
  24.     For Each k In d.keys
  25.         Application.SheetsInNewWorkbook = d(k).Count
  26.         Set wb = Workbooks.Add
  27.         m = 0
  28.         For Each kk In d(k).keys
  29.             m = m + 1
  30.             t = d(k)(kk)
  31.             ws.Sheets("拆分模板").Cells.Copy wb.Sheets(m).[a1]
  32.             With wb.Sheets(m)
  33.                 .Name = kk
  34.                 .[c2] = k
  35.                 .[b4] = kk
  36.                 .[d4] = t(0)
  37.                 .[b6] = t(1)
  38.             End With
  39.         Next
  40.         wb.SaveAs p & k
  41.         wb.Close
  42.     Next
  43.     Set d = Nothing
  44.     Application.ScreenUpdating = True
  45.     MsgBox "拆分完毕,共用时:" & Format(Timer - tm) & "秒!"
  46. End Sub


复制代码


评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-28 09:20 | 显示全部楼层
Qs18 发表于 2024-8-28 07:12
Sub qs()
Dim arr, i, dic, sht As Worksheet, xb As Workbook
Application.DisplayAlerts = False: Appl ...

感谢大佬,但是运行结束以后没数据

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-28 09:23 | 显示全部楼层
ykcbf1100 发表于 2024-8-28 07:18
按部门拆分和按月份拆分都写了。

附件供参考。。。

完美解决我的问题,就是想要扩展一下弄成一个通用型的就更好了

TA的精华主题

TA的得分主题

发表于 2024-8-28 10:13 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
·遁去的一· 发表于 2024-8-28 09:20
感谢大佬,但是运行结束以后没数据

哦,还需要把数据填进去,我以为只拆开

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-28 11:08 | 显示全部楼层
Sub UniversalSplit()
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
   
    Dim startTime As Double
    startTime = Timer ' 记录开始时间
   
    Dim fso As Object
    Dim d As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set d = CreateObject("Scripting.Dictionary")
   
    Dim path As String
    path = ThisWorkbook.Path & "\" ' 获取当前工作簿路径
   
    Dim ws As Workbook
    Set ws = ThisWorkbook
    Dim sh As Worksheet
    Set sh = ws.Sheets("汇总表") ' 设置汇总表为目标工作表
   
    On Error Resume Next
    Dim arr As Variant
    arr = sh.UsedRange ' 获取汇总表的所有数据

    ' 获取用户输入的部门列和子键列
    Dim departmentCol As Long
    Dim subKeyCol As Long
    departmentCol = Application.InputBox("请输入部门列的列号(例如 A=1, B=2 等):", Type:=1)
    subKeyCol = Application.InputBox("请输入子键列的列号(例如 A=1, B=2 等):", Type:=1)

    ' 获取列数
    Dim totalCols As Long
    totalCols = UBound(arr, 2)

    ' 创建一个数组来存储用户输入的新单元格地址
    Dim newCellAddresses() As String
    ReDim newCellAddresses(1 To totalCols)

    ' 遍历每一列,获取用户输入的新单元格地址
    Dim colIndex As Long
    For colIndex = 1 To totalCols
        newCellAddresses(colIndex) = Application.InputBox("请输入要写入 '" & arr(1, colIndex) & "' 的单元格地址(例如 A1):", Type:=2)
    Next colIndex

    ' 遍历汇总表的数据
    Dim i As Long
    For i = 2 To UBound(arr, 1) ' 从第二行开始
        Dim department As String
        Dim subKey As Variant
        Dim values() As Variant
        
        department = CStr(arr(i, departmentCol)) ' 使用用户指定的部门列
        subKey = arr(i, subKeyCol) ' 使用用户指定的子键列

        ' 如果字典中不存在该部门,则添加
        If Not d.Exists(department) Then
            Set d(department) = CreateObject("Scripting.Dictionary")
        End If
        
        ' 如果该部门的字典中不存在子键,则添加
        If Not d(department).Exists(subKey) Then
            ReDim values(1 To totalCols - 2) ' 根据列数调整数组大小
            For colIndex = 1 To totalCols
                If colIndex <> departmentCol And colIndex <> subKeyCol Then
                    values(colIndex - 2) = arr(i, colIndex) ' 存储除部门列和子键列外的值
                End If
            Next colIndex
            d(department)(subKey) = values
        Else
            ' 如果子键已存在,则累加对应的值
            values = d(department)(subKey)
            For colIndex = 1 To totalCols
                If colIndex <> departmentCol And colIndex <> subKeyCol Then
                    values(colIndex - 2) = values(colIndex - 2) + arr(i, colIndex) ' 累加非部门列和子键列的值
                End If
            Next colIndex
            d(department)(subKey) = values
        End If
    Next i

    ' 遍历字典,创建新的工作簿
    Dim k As Variant
    For Each k In d.Keys
        Application.SheetsInNewWorkbook = d(k).Count ' 设置新工作簿的工作表数量
        Dim wb As Workbook
        Set wb = Workbooks.Add
        Dim m As Long
        m = 0
        
        Dim kk As Variant
        For Each kk In d(k).Keys
            m = m + 1
            values = d(k)(kk)
            ws.Sheets("拆分模板").Cells.Copy wb.Sheets(m).[A1] ' 复制模板
            
            With wb.Sheets(m)
                .Name = kk ' 设置工作表名为子键
                ' 遍历所有列,写入用户指定的新单元格地址
                For colIndex = 1 To totalCols
                    If colIndex <> departmentCol And colIndex <> subKeyCol Then
                        .Range(newCellAddresses(colIndex)).Value = values(colIndex - 2) ' 写入累加值
                    End If
                Next colIndex
                .Range(newCellAddresses(departmentCol)).Value = k ' 在指定的单元格中写入部门名
                .Range(newCellAddresses(subKeyCol)).Value = kk ' 在指定的单元格中写入子键
            End With
        Next kk
        
        wb.SaveAs path & k & ".xlsx" ' 按部门名称保存工作簿
        wb.Close False ' 关闭工作簿
    Next k
   
    Set d = Nothing
    Application.ScreenUpdating = True
   
    MsgBox "拆分完毕,共用时:" & Format(Timer - startTime, "0.00") & "秒!"
End Sub

以上是AI修改后的代码,可以运行但是不方便,指定新位置时要记得模板表格,运行后第二列的数据全部为空,不知道是什么原因

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-28 18:33 | 显示全部楼层
ykcbf1100 发表于 2024-8-28 07:18
按部门拆分和按月份拆分都写了。

附件供参考。。。

大佬能把个改成一个通用的拆分表吗,就是指定任意两列拆分,拆分模板可以由用户随意修改,再指定源表和拆分表之间的数据联系

TA的精华主题

TA的得分主题

发表于 2024-8-28 19:12 | 显示全部楼层
本帖最后由 ykcbf1100 于 2024-8-28 19:29 编辑
·遁去的一· 发表于 2024-8-28 18:33
大佬能把个改成一个通用的拆分表吗,就是指定任意两列拆分,拆分模板可以由用户随意修改,再指定源表和拆 ...

就附件而言,应该是可以的

表格拆分.zip

33.1 KB, 下载次数: 0

TA的精华主题

TA的得分主题

发表于 2024-8-28 19:30 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
拆分通用版
  1. Sub ykcbf()   '//2024.8.28    按部门或月份拆分,通用版
  2.     Application.ScreenUpdating = False
  3.     Application.DisplayAlerts = False
  4.     Dim tm: tm = Timer
  5.     Set fso = CreateObject("Scripting.FileSystemObject")
  6.     Set d = CreateObject("Scripting.Dictionary")
  7.     p = ThisWorkbook.Path & ""
  8.     fs = Val(Application.InputBox("请输入拆分方式:1、部门为主月份为辅;2、月份为主部门为辅。", "输入1或者2即可", "1"))
  9.     Set ws = ThisWorkbook
  10.     Set sh = ws.Sheets("汇总表")
  11.     On Error Resume Next
  12.     arr = sh.UsedRange
  13.     For i = 2 To UBound(arr)
  14.         If Val(fs) = 1 Then
  15.             s = CStr(arr(i, 1)): ss = arr(i, 4)
  16.         Else
  17.             ss = CStr(arr(i, 1)): s = arr(i, 4)
  18.         End If
  19.         If Not d.exists(s) Then Set d(s) = CreateObject("Scripting.Dictionary")
  20.         If Not d(s).exists(ss) Then
  21.             d(s)(ss) = Array(arr(i, 2), arr(i, 3))
  22.         Else
  23.             t = d(s)(ss)
  24.             t(0) = t(0) + arr(i, 2)
  25.             t(1) = t(1) + arr(i, 3)
  26.             d(s)(ss) = t
  27.         End If
  28.     Next
  29.     For Each k In d.keys
  30.         Application.SheetsInNewWorkbook = d(k).Count
  31.         Set wb = Workbooks.Add
  32.         m = 0
  33.         For Each kk In d(k).keys
  34.             m = m + 1
  35.             t = d(k)(kk)
  36.             ws.Sheets("拆分模板").Cells.Copy wb.Sheets(m).[a1]
  37.             With wb.Sheets(m)
  38.                 .Name = kk
  39.                 If Val(fs) = 1 Then
  40.                     .[c2] = kk
  41.                     .[b4] = k
  42.                 Else
  43.                     .[c2] = k
  44.                     .[b4] = kk
  45.                 End If
  46.                 .[d4] = t(0)
  47.                 .[b6] = t(1)
  48.             End With
  49.         Next
  50.         wb.SaveAs p & k
  51.         wb.Close
  52.     Next
  53.     Set d = Nothing
  54.     Application.ScreenUpdating = True
  55.     MsgBox "拆分完毕,共用时:" & Format(Timer - tm) & "秒!"
  56. End Sub
复制代码


TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-28 22:16 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

感谢大佬的再次修改,最难的部分应该是如何让用户指定源表数据在新表的位置(按模板拆分),现在这个版本数据的列数是固定写死的,如果数据列数发生增减,拆分模板格式发生变动如何修改呢

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-29 01:48 | 显示全部楼层
参照大佬ykcbf1100的代码,经AI修改后基本达到通用,分享一下,并请大佬进行优化,再次感谢各位大佬

按模板拆分表格.zip

22.14 KB, 下载次数: 6

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-18 18:43 , Processed in 0.037832 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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