ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[求助] 想做一个动态人员花名册,遇到了一点问题,求大神帮助指导

[复制链接]

TA的精华主题

TA的得分主题

发表于 2024-8-20 18:51 | 显示全部楼层 |阅读模式
主要想要这个VBA宏代码实现:从一个名为"所有人员名单"的源工作表中提取不重复的姓名,并将它们填充到另一个名为"Sheet1"的目标工作表中,它通过排除已存在的姓名,将新的不重复的姓名填充到目标工作表中,以避免重复和遗漏。并用F2的值在excel簿中另存这张表。

以下是部分需求:
设置源和目标工作表:将"所有人员名单"设置为源工作表,"Sheet1"设置为目标工作表。
定义源数据和排除数据的范围:源数据范围是源工作表的A1到A58单元格,排除数据范围是目标工作表的C24到C40单元格。
提取排除姓名:排除范围中的每个单元格,按"、"分隔符分割姓名,并将它们添加到排除字典中。(同名的问题没想到怎么解决)
消息框提示:显示一个消息框,告知用户填充完成,并显示填充了多少个姓名。并另存为新表完毕(未完成)

以下VBA函数是我结合Kimi折腾出来的,虽然能完成数据的填充,但是运行会提示下标越界

  1. Sub FillSheet1ColumnByColumnWithExclusionCriteria()
  2.     ' 声明变量
  3.     Dim sourceWs As Worksheet
  4.     Dim destWs As Worksheet
  5.     Dim sourceRange As Range
  6.     Dim exclusionRange As Range
  7.     Dim cell As Range
  8.     Dim exclusionCell As Range
  9.     Dim dictNames As Object
  10.     Dim dictExclusions As Object
  11.     Dim namesArray() As Variant
  12.     Dim currentNameIndex As Long
  13.     Dim col As Integer
  14.     Dim row As Long

  15.     ' 设置源工作表和目标工作表
  16.     Set sourceWs = ThisWorkbook.Sheets("所有人员名单") ' 源数据工作表
  17.     Set destWs = ThisWorkbook.Sheets("Sheet1") ' 目标工作表

  18.     ' 创建字典对象来存储不重复的姓名和排除的姓名列表
  19.     Set dictNames = CreateObject("Scripting.Dictionary")
  20.     Set dictExclusions = CreateObject("Scripting.Dictionary")

  21.     ' 定义源数据的范围和排除数据的范围
  22.     Set sourceRange = sourceWs.Range("A1:A58")
  23.     Set exclusionRange = destWs.Range("C24:C40")

  24.     ' 从排除范围中提取姓名并存储在字典中
  25.     For Each exclusionCell In exclusionRange
  26.         If Not IsEmpty(exclusionCell.Value) Then
  27.             Dim exclusionNames As Variant
  28.             exclusionNames = Split(exclusionCell.Value, "、") ' 确保使用正确的分隔符
  29.             Dim name As Variant
  30.             For Each name In exclusionNames
  31.                 If Trim(name) <> "" Then
  32.                     dictExclusions.Add Trim(name), True ' 使用Add而不是Exists
  33.                 End If
  34.             Next name
  35.         End If
  36.     Next exclusionCell

  37.     ' 从源数据中提取不重复的姓名
  38.     For Each cell In sourceRange
  39.         If cell.Value <> "" Then
  40.             dictNames(cell.Value) = True
  41.         End If
  42.     Next cell

  43.     ' 将不重复的姓名列表转换为数组
  44.     namesArray = dictNames.Keys()

  45.     ' 初始化当前姓名索引
  46.     currentNameIndex = LBound(namesArray)

  47.     ' 按列遍历目标范围 "A4:F23"
  48.     For col = 1 To destWs.Range("A4:F23").Columns.Count
  49.         ' 遍历目标列的每一行
  50.         For row = 4 To 23
  51.             With destWs.Cells(row, col)
  52.                 If IsEmpty(.Value) Then
  53.                     ' 找到不在排除列表中的姓名并填充
  54.                     While currentNameIndex <= UBound(namesArray) And _
  55.                         dictExclusions.Exists(namesArray(currentNameIndex))
  56.                         currentNameIndex = currentNameIndex + 1
  57.                     Wend
  58.                     If currentNameIndex <= UBound(namesArray) Then
  59.                         .Value = namesArray(currentNameIndex)
  60.                         currentNameIndex = currentNameIndex + 1 ' 准备填充下一个空单元格
  61.                     End If
  62.                 End If
  63.             End With
  64.         Next row
  65.     Next col

  66.     ' 清理
  67.     Set sourceWs = Nothing
  68.     Set destWs = Nothing
  69.     Set sourceRange = Nothing
  70.     Set exclusionRange = Nothing
  71.     Set dictNames = Nothing
  72.     Set dictExclusions = Nothing

  73.     MsgBox "填充完成,共填充了 " & (currentNameIndex - LBound(namesArray)) & " 个姓名。"
  74.     ' 检查F2单元格是否包含文本
  75.     If Not IsEmpty(destWs.Range("F2").Value) Then
  76.         ' 定义新工作表的名称
  77.         Dim newSheetName As String
  78.         newSheetName = destWs.Range("F2").Value
  79.         
  80.         ' 创建一个新的工作表并命名
  81.         Dim newWs As Worksheet
  82.         Set newWs = ThisWorkbook.Worksheets.Add
  83.         newWs.Name = newSheetName
  84.         
  85.         ' 复制源工作表的内容到新工作表
  86.         destWs.Cells.Copy newWs.Cells
  87.         
  88.         ' 可选:删除源工作表
  89.         ' destWs.Delete
  90.         
  91.         ' 显示消息框,告知用户新工作表已创建
  92.         MsgBox "新工作表 '" & newSheetName & "' 已创建。"
  93.     Else
  94.         MsgBox "F2 单元格为空,无法创建新工作表。"
  95.     End If
  96. End Sub
复制代码
求大佬帮忙!!!!
点名册.rar (18.12 KB, 下载次数: 9)

TA的精华主题

TA的得分主题

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

  1. Sub ykcbf()  '//2024.8.22   另存新表
  2.     Application.ScreenUpdating = False
  3.     Set d = CreateObject("Scripting.Dictionary")
  4.     Set d1 = CreateObject("Scripting.Dictionary")
  5.     With Sheets("Sheet1")
  6.         brr = .[c24:c28].Value
  7.         fn = Format(.[f2].Value, "m月d日")
  8.         For Each k In brr
  9.             If k <> Empty Then
  10.                 st = st & "、" & k
  11.             End If
  12.         Next
  13.         brr = Split(Mid(st, 2), "、")
  14.         For Each k In brr
  15.             d1(k) = ""
  16.         Next
  17.     End With
  18.     With Sheets("所有人员名单")
  19.         r = .Cells(Rows.Count, 1).End(3).row
  20.         arr = .[a1].Resize(r, 1)
  21.         For i = 1 To UBound(arr)
  22.             s = arr(i, 1)
  23.             If Not d1.exists(s) Then d(s) = ""
  24.         Next
  25.     End With
  26.     With Sheets("Sheet1")
  27.         m = 3: n = 2
  28.         For Each k In d.keys
  29.             m = m + 1
  30.             .Cells(m, n) = k
  31.             If m = 23 Then m = 3: n = n + 2
  32.         Next
  33.     End With
  34.     On Error Resume Next
  35.     Set sht = Worksheets(fn)
  36.     Sheets("Sheet1").Cells.Copy sht.[a1]
  37.     sht.DrawingObjects.Delete
  38.     If Err.Number <> 0 Then
  39.         Sheets("Sheet1").Copy After:=Sheets(Sheets.Count)
  40.         Set sht = Sheets(Sheets.Count)
  41.         sht.name = fn
  42.         sht.DrawingObjects.Delete
  43.     End If
  44.     Set d = Nothing
  45.     Set d1 = Nothing
  46.     Application.ScreenUpdating = True
  47.     MsgBox "OK!"
  48. End Sub
复制代码


TA的精华主题

TA的得分主题

发表于 2024-8-20 19:52 | 显示全部楼层
附件供参考。。。

点名册2.zip

22.63 KB, 下载次数: 20

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-8-20 19:52 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
代码供参考。。。

9549f48d-c485-4f39-9eb0-a4a0e25d5158.png

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-8-20 20:20 | 显示全部楼层
本帖最后由 gwjkkkkk 于 2024-8-20 20:29 编辑


Option Explicit
Sub TEST6()
    Dim ar, br, i&, j&, n&, iPosCol&, dic As Object, strFileName$
   
    With Worksheets(1).[F2]
        If .Value = Empty Then MsgBox "时间为空", vbCritical: Exit Sub
        strFileName = Format(.Value, "yyyy年m月d")
    End With
   
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Set dic = CreateObject("Scripting.Dictionary")
   
    ar = Worksheets("所有人员名单").[A1].CurrentRegion.Value
    For i = 2 To UBound(ar)
        dic(ar(i, 1)) = Empty
    Next i
    ar = Worksheets(1).[C24:C28].Value
    For i = 1 To UBound(ar)
        br = Split(ar(i, 1), "、")
        For j = 0 To UBound(br)
            If dic.exists(br(j)) Then dic.Remove br(j)
        Next j
    Next i
   
    ar = dic.keys: n = dic.Count
    ar = transArrToCol(ar, 20, 0, UBound(ar))
   
    Worksheets(1).Copy
    With ActiveWorkbook
        With .Worksheets(1)
            ReDim br(1 To UBound(ar), 0)
            For j = 1 To UBound(ar, 2)
                iPosCol = j * 2
                For i = 1 To UBound(ar)
                    br(i, 0) = ar(i, j)
                Next i
                .Cells(4, iPosCol).Resize(20) = br
            Next j
        End With
        .SaveAs ThisWorkbook.Path & "\" & strFileName
        .Close
    End With
   
    Set dic = Nothing
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    MsgBox "共填充" & n & "个姓名", vbInformation
    Beep
End Sub

Function transArrToCol(ByVal ar, ByVal iCutNum&, _
    ByVal iStartCol&, ByVal iEndCol&) As Variant()
    Dim br, j&, n&, y&, x&, iRowSize&
   
    If iStartCol < LBound(ar) Then iStartCol = LBound(ar)
    If iEndCol > UBound(ar) Then iEndCol = UBound(ar)

    n = -(Int(-(iEndCol - iStartCol + 1) / iCutNum))
    iRowSize = IIf(iEndCol - iStartCol + 1 < iCutNum, iEndCol - iStartCol + 1, iCutNum)
    ReDim br(1 To iRowSize, 1 To n)

    n = 0
    For j = iStartCol To iEndCol
        n = n + 1
        x = -Int(-n / iCutNum)
        y = IIf(n Mod iCutNum = 0, iCutNum, n Mod iCutNum)
        br(y, x) = ar(j)
    Next j
    transArrToCol = br
End Function

TA的精华主题

TA的得分主题

发表于 2024-8-20 20:21 | 显示全部楼层
本帖最后由 gwjkkkkk 于 2024-8-20 20:28 编辑

请参考附件。。。

点名册.rar

24.56 KB, 下载次数: 18

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-20 22:06 | 显示全部楼层
ykcbf1100 发表于 2024-8-20 19:52
附件供参考。。。

确实填充了,但是没有排除指定区域出现的人员,还有没有另存为新的表

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-20 22:08 | 显示全部楼层
gwjkkkkk 发表于 2024-8-20 20:21
请参考附件。。。

在当前excel簿中,另存一张sheet表(用F2区域的时间命名)就更完美了

TA的精华主题

TA的得分主题

发表于 2024-8-21 07:08 | 显示全部楼层
supper_idol 发表于 2024-8-20 22:06
确实填充了,但是没有排除指定区域出现的人员,还有没有另存为新的表

改好了。。。

点名册2.zip

25 KB, 下载次数: 20

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2024-8-21 07:08 | 显示全部楼层
改一下。。。

  1. Sub ykcbf()  '//2024.8.21
  2.     Application.ScreenUpdating = False
  3.     Set d = CreateObject("Scripting.Dictionary")
  4.     Set d1 = CreateObject("Scripting.Dictionary")
  5.     With Sheets("Sheet1")
  6.         brr = .[c24:c28].Value
  7.         For Each k In brr
  8.             If k <> Empty Then
  9.                 st = st & "、" & k
  10.             End If
  11.         Next
  12.         brr = Split(Mid(st, 2), "、")
  13.         For Each k In brr
  14.             d1(k) = ""
  15.         Next
  16.     End With
  17.     With Sheets("所有人员名单")
  18.         r = .Cells(Rows.Count, 1).End(3).row
  19.         arr = .[a1].Resize(r, 1)
  20.         For i = 1 To UBound(arr)
  21.             s = arr(i, 1)
  22.             If Not d1.exists(s) Then d(s) = ""
  23.         Next
  24.     End With
  25.     With Sheets("Sheet1")
  26.         m = 3: n = 2
  27.         For Each k In d.keys
  28.             m = m + 1
  29.             .Cells(m, n) = k
  30.             If m = 23 Then m = 3: n = n + 2
  31.         Next
  32.     End With
  33.     Sheets("Sheet1").Copy
  34.     Set wb = ActiveWorkbook
  35.     wb.Sheets(1).DrawingObjects.Delete
  36.     wb.SaveAs ThisWorkbook.Path & "\人员点名册"
  37.     wb.Close
  38.     Set d = Nothing
  39.     Set d1 = Nothing
  40.     Application.ScreenUpdating = True
  41.     MsgBox "OK!"
  42. End Sub
复制代码


TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-22 19:30 | 显示全部楼层

厉害厉害!
但是,老师,另存新表不是在同一个簿里面,而是生成了新的簿,也不是用的F2区域的文字命名的。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-18 16:48 , Processed in 0.049509 second(s), 15 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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