ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 321|回复: 12

[求助] 关于按条件带格式拆分数据表的问题

[复制链接]

TA的精华主题

TA的得分主题

发表于 2024-4-17 15:25 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
各位老师,求助查错或重写:
因工作需要,定期需要拆分大师数据表并另存。用AI写了一个,运行时提醒类型不匹配错误。
以下为代码片断:


'For Each cell In columnRange
'            If Trim(cell.Value) <> "" Then
'                cellValue = Trim(cell.Value)

功能主要要求:


1、根据表格中选定列的内容,进行表格拆分和另存操作,要求保留原有数据格式(如身份证号要保留为文本)。

具体如附件。

非常感谢!

209901拆分另存模板.zip

33.31 KB, 下载次数: 5

TA的精华主题

TA的得分主题

发表于 2024-4-17 19:03 | 显示全部楼层
关键字:distinct
GIF 2024-04-17 19-01-42.gif

limonet.zip

30.82 KB, 下载次数: 12

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-4-17 19:04 | 显示全部楼层
Sub limonet()
    Dim S$, Cn As Object, StrSQL$, Arr As Variant, i%, FileFN$
    S = Application.InputBox("请选择条件列", , "省份")
    Set Cn = CreateObject("Adodb.Connection")
    Cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0;Data Source=" & ThisWorkbook.FullName
    Arr = Cn.Execute("Select Distinct " & S & " From [总表$A:G]").GetRows
    For i = 0 To UBound(Arr, 2)
        Cn.Close
        FileFN = ThisWorkbook.Path & "\" & Arr(0, i) & ".xlsx"
        StrCn = "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0 XML;Data Source=" & FileFN
        Cn.Open StrCn
        StrSQL = "Select * Into Sheet1 From [Excel 12.0;DataBase=" & ThisWorkbook.FullName & "].[总表$A:G] Where " & S & "='" & Arr(0, i) & "'"
        Cn.Execute (StrSQL)
    Next i
End Sub

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-4-17 19:24 | 显示全部楼层
附件供参考,2级字典

209901拆分另存模板.7z

28.98 KB, 下载次数: 10

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-4-17 19:25 | 显示全部楼层
本帖最后由 baofa2 于 2024-4-17 19:36 编辑

209901拆分另存模板.zip (38.96 KB, 下载次数: 10)

  1. Option Explicit

  2. Sub test0()
  3.   
  4.   Dim titleRow As Long, splitCol As Long
  5.   Dim Conn As Object, rs As Object, SQL As String
  6.   Dim strPath As String, strFullName As String, strField As String, strValue As String
  7.   
  8.   titleRow = 1
  9.   splitCol = 5
  10.   strField = "[" & Cells(1, splitCol).Value & "]"
  11.   
  12.   strPath = ThisWorkbook.Path & "\分簿"
  13.   If Dir(strPath, vbDirectory) = "" Then MkDir strPath
  14.   
  15.   Set Conn = CreateObject("ADODB.Connection")
  16.   Set rs = CreateObject("ADODB.Recordset")
  17.   Conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0 XML;Data Source=" & ThisWorkbook.FullName
  18.   
  19.   SQL = "SELECT DISTINCT " & strField & " FROM [" & ActiveSheet.Name & "$] WHERE LEN(" & strField & ")"
  20.   rs.Open SQL, Conn, 1, 3
  21.   
  22.   While Not rs.EOF
  23.     strValue = rs.Fields(0).Value
  24.     strFullName = strPath & Application.PathSeparator & strValue & ".xlsx"
  25.     If Dir(strFullName) <> "" Then Kill strFullName
  26.     Conn.Execute "SELECT * INTO [" & strFullName & "].[" & strValue & "] FROM [" & ActiveSheet.Name & "$A:G] WHERE " & strField & "='" & strValue & "'"
  27.     rs.MoveNext
  28.   Wend
  29.   
  30.   rs.Close
  31.   Set rs = Nothing
  32.   Conn.Close
  33.   Set Conn = Nothing
  34.   Beep
  35. End Sub

  36. Sub test1()
  37.   Dim ar, Dict As Object, titleRow As Long, splitCol As Long
  38.   Dim strPath As String, strKey As String, colSize As Long, i As Long
  39.   
  40.   Application.ScreenUpdating = False
  41.   
  42.   titleRow = 1
  43.   splitCol = 5
  44.   'splitCol = InputBox("请输入 拆分列号", "输入提示:", 3): If Val(splitCol) = 0 Then Exit Sub
  45.   'titleRow = InputBox("请输入 标题行数", "输入提示:", 6): If Val(titleRow) = 0 Then Exit Sub
  46.   
  47.   strPath = ThisWorkbook.Path & "\分簿"
  48.   If Dir(strPath, vbDirectory) = "" Then MkDir strPath
  49.   strPath = strPath & "\"
  50.   
  51.   Set Dict = CreateObject("Scripting.Dictionary")
  52.   With Worksheets("总表")
  53.     ar = .Range("A1").CurrentRegion
  54.     colSize = UBound(ar, 2)
  55.     For i = titleRow + 1 To UBound(ar)
  56.       strKey = Trim(ar(i, splitCol))
  57.       If Len(strKey) Then
  58.         If Not Dict.Exists(strKey) Then Set Dict(strKey) = .Range("A1").Resize(titleRow, colSize)
  59.         Set Dict(strKey) = Union(Dict(strKey), .Cells(i, 1).Resize(, colSize))
  60.       End If
  61.     Next
  62.   End With
  63.   
  64.   Application.DisplayAlerts = False
  65.   For i = 0 To Dict.Count - 1
  66.     With Workbooks.Add
  67.       With .Worksheets(1)
  68.         .Name = Dict.Keys()(i)
  69.         Dict.Items()(i).Copy .Range("A1")
  70.         .DrawingObjects.Delete
  71.         .Columns.AutoFit
  72.       End With
  73.       .SaveAs strPath & Dict.Keys()(i), 51
  74.       .Close
  75.     End With
  76.   Next
  77.   
  78.   Set Dict = Nothing
  79.   
  80.   Application.DisplayAlerts = True
  81.   Application.ScreenUpdating = True
  82.   Beep
  83. End Sub

  84. Sub test2() '字典定位 数组嵌套
  85.   Dim data, temp() As String, results(), Dict As Object, wks As Worksheet
  86.   Dim i As Long, j As Long, posRow As Long, strPath As String
  87.   Dim titleRow As Long, splitCol As Long
  88.   
  89.   titleRow = 1  '标题所在 行
  90.   splitCol = 5  '拆分依据 列
  91.   
  92.   DoApp False
  93.   
  94.   strPath = ThisWorkbook.Path & Application.PathSeparator & "分簿"
  95.   If Dir(strPath, vbDirectory) = "" Then MkDir strPath
  96.   strPath = strPath & Application.PathSeparator
  97.   
  98. '  Worksheets("总表").Activate
  99.   Set wks = ActiveSheet
  100.   Set Dict = CreateObject("Scripting.Dictionary")
  101.   
  102.   data = Range("A1").CurrentRegion
  103.   ReDim temp(1 To UBound(data), 1 To UBound(data, 2))
  104.   For j = 1 To UBound(data, 2)
  105.     For i = 1 To titleRow
  106.       temp(i, j) = data(i, j)
  107.     Next
  108.   Next
  109.   
  110.   For i = titleRow + 1 To UBound(data)
  111.     If Not Dict.Exists(data(i, splitCol)) Then Dict(data(i, splitCol)) = Dict.Count + 1
  112.   Next
  113.   
  114.   ReDim results(1 To Dict.Count, 1 To 2)
  115.   For i = 1 To Dict.Count
  116.     results(i, 1) = titleRow
  117.     results(i, 2) = temp
  118.   Next
  119.   
  120.   For i = titleRow + 1 To UBound(data)
  121.     posRow = Dict(data(i, splitCol))
  122.     results(posRow, 1) = results(posRow, 1) + 1
  123.     For j = 1 To UBound(data, 2)
  124.       results(posRow, 2)(results(posRow, 1), j) = data(i, j)
  125.     Next
  126.   Next
  127.   
  128.   For i = 1 To Dict.Count
  129.     wks.Copy
  130.     With ActiveWorkbook
  131.       With .Worksheets(1)
  132.         .Name = results(i, 2)(titleRow + 1, splitCol)
  133.         .Range("A1").Resize(results(i, 1), UBound(data, 2)) = results(i, 2)
  134.         .DrawingObjects.Delete
  135.         .UsedRange.Offset(, UBound(data, 2)).Clear
  136.         .UsedRange.Offset(results(i, 1)).Clear
  137.       End With
  138.       .SaveAs strPath & results(i, 2)(titleRow + 1, splitCol), 51
  139.       .Close
  140.     End With
  141.   Next
  142.   
  143.   Set Dict = Nothing
  144.   
  145.   DoApp
  146.   Beep
  147. End Sub

  148. Sub test3()
  149.   Dim splitCol As Long, titleRow As Long
  150.   
  151.   titleRow = 1
  152.   splitCol = 5
  153. '  splitCol = InputBox("请输入 拆分列号", "输入提示:", 1): If Val(splitCol) = 0 Then Exit Sub
  154. '  titleRow = InputBox("请输入 标题行数", "输入提示:", 2): If Val(titleRow) = 0 Then Exit Sub
  155.   DoApp False
  156.   
  157.   Dim ar, i As Long, j As Long, rowSize As Long, lastRow As Long
  158.   Dim strPath As String, strName As String, wks As Worksheet
  159.   
  160.   strPath = ThisWorkbook.Path & Application.PathSeparator & "分簿"
  161.   If Dir(strPath, vbDirectory) = "" Then MkDir strPath
  162.   strPath = strPath & Application.PathSeparator
  163.   
  164. '  Worksheets("总表").Activate
  165.   Set wks = ActiveSheet
  166.   With wks.Range("A1").CurrentRegion
  167.     lastRow = .Rows.Count
  168.     ar = .Resize(lastRow + 1)
  169.   End With

  170.   With CreateObject("Excel.Sheet")
  171.     With .ActiveSheet.Range("A1").Resize(UBound(ar), UBound(ar, 2))
  172.       .Value = ar
  173.       With Intersect(.Offset(0), .Offset(titleRow))
  174.         .Sort .Item(splitCol), xlDescending, , , , , , xlYes
  175.       End With
  176.       ar = .Value
  177.     End With
  178.     .Close
  179.   End With
  180.   
  181. '  QuickSort ar, titleRow + 1, lastRow, 1, UBound(ar, 2), splitCol
  182.   
  183.   rowSize = titleRow
  184.   For i = titleRow + 1 To lastRow
  185.     rowSize = rowSize + 1
  186.     For j = 1 To UBound(ar, 2)
  187.       ar(rowSize, j) = ar(i, j)
  188.     Next
  189.     If ar(i, splitCol) <> ar(i + 1, splitCol) Then
  190.       strName = ar(i, splitCol)
  191.       wks.Copy
  192.       With ActiveWorkbook
  193.         With .Worksheets(1)
  194.           .Range("A1").Resize(rowSize, 3).NumberFormatLocal = "@"
  195.           .Range("A1").Resize(rowSize, j - 1) = ar
  196.           .UsedRange.Offset(, j - 1).Clear
  197.           .UsedRange.Offset(rowSize).Clear
  198.           .DrawingObjects.Delete
  199.           .Name = strName
  200.         End With
  201.         .SaveAs strPath & strName, 51
  202.         .Close
  203.       End With
  204.       rowSize = titleRow
  205.     End If
  206.   Next
  207.   
  208.   Set wks = Nothing
  209.   DoApp
  210.   Beep
  211. End Sub

  212. Function DoApp(Optional b As Boolean = True)
  213.   With Application
  214.     .ScreenUpdating = b
  215.     .DisplayAlerts = b
  216.     .Calculation = -b * 30 - 4135
  217.   End With
  218. End Function

  219. Function QuickSort(ar, u As Long, d As Long, l As Long, r As Long, pos As Long)
  220.   Dim t As Long, b As Long, x As Long, pivot As String, swap
  221.   t = u
  222.   b = d
  223.   pivot = ar((u + d) \ 2, pos)
  224.   While t <= b
  225.     Do While t < d
  226.       If StrComp(ar(t, pos), pivot, vbTextCompare) = -1 Then t = t + 1 Else Exit Do
  227.     Loop
  228.     Do While b > u
  229.       If StrComp(pivot, ar(b, pos), vbTextCompare) = -1 Then b = b - 1 Else Exit Do
  230.     Loop
  231.     If t < b Then
  232.       For x = l To r
  233.         swap = ar(t, x): ar(t, x) = ar(b, x): ar(b, x) = swap
  234.       Next
  235.       t = t + 1: b = b - 1
  236.     Else
  237.       If t = b Then t = t + 1: b = b - 1
  238.     End If
  239.   Wend
  240.   If u < b Then QuickSort ar, u, b, l, r, pos
  241.   If t < d Then QuickSort ar, t, d, l, r, pos
  242. End Function
复制代码


评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-4-17 19:25 | 显示全部楼层
参与一下。。。

  1. Sub ykcbf2()   '//2024.4.17
  2.     Dim wb, arr, sh
  3.     Application.ScreenUpdating = False
  4.     Application.DisplayAlerts = False
  5.     p = ThisWorkbook.Path & ""
  6.     Set d = CreateObject("Scripting.Dictionary")
  7.     Set sh = ThisWorkbook.Sheets("总表")
  8.     arr = sh.UsedRange
  9.     bt = 1        '//标题行数
  10.     col = 5       '//拆分列号
  11.     For i = bt + 1 To UBound(arr)
  12.         s = arr(i, col)
  13.         If Not d.exists(s) Then Set d(s) = CreateObject("Scripting.Dictionary")
  14.         d(s)(i) = Application.Index(arr, i)
  15.     Next
  16.     For Each k In d.keys
  17.         sh.Copy
  18.         Set wb = ActiveWorkbook
  19.         m = d(k).Count
  20.         With wb.Sheets(1)
  21.             .Name = k
  22.             .DrawingObjects.Delete
  23.             .UsedRange.Offset(bt + m).Clear
  24.             .Cells(bt + 1, 1).Resize(m, UBound(arr, 2)) = Application.Rept(d(k).Items, 1)
  25.         End With
  26.         wb.SaveAs p & k
  27.         wb.Close 1
  28.     Next
  29.     Application.ScreenUpdating = True
  30.     MsgBox "OK!"
  31. End Sub
复制代码


评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-4-17 20:08 | 显示全部楼层
  1. import pandas as pd

  2. df = pd.read_excel('209901拆分另存模板.xlsm', header=0)
  3. for key, value in df.groupby('公司'):
  4.         value.to_excel(f'{key}.xlsx', index=False)
复制代码

TA的精华主题

TA的得分主题

发表于 2024-4-17 22:16 | 显示全部楼层
楼主代码修改版 209901拆分另存模板.zip (39.29 KB, 下载次数: 3)
AI的代码也值得学习,比如:
dict.Add cellValue, Sheets.Add(After:=Sheets(Sheets.Count))
dict(cellValue).Name = cellValue

评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-4-18 08:51 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
修改内容较多,辛苦各位老师了,内容我消化下,有问题再请教!谢谢!

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-4-18 12:01 | 显示全部楼层
limonet 发表于 2024-4-17 19:04
Sub limonet()
    Dim S$, Cn As Object, StrSQL$, Arr As Variant, i%, FileFN$
    S = Application.I ...

老师的程序是真的短和快,代码数量可见的少,用3000条数据拆分测试,人工计时测试,用时约为其他代码的10%。我想知道是哪一块程序让速度差异这么多呢?太牛了!
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-5-2 18:29 , Processed in 0.039026 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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