找到在 Excel 中部门中重叠的员工。

huangapple go评论120阅读模式
英文:

Finding overlapping employees in departments using excel

问题

我有我的参考数据,看起来像这样。

找到在 Excel 中部门中重叠的员工。

我试图创建一个日历,使用工作日和5个时间段,如下所示。

找到在 Excel 中部门中重叠的员工。

使用这个日历,我想要确定部门之间是否存在潜在的冲突。

我的意思是:

  1. 在任何特定的一天,如果员工在该部门工作(不管时间段),他们只能进入一次。
  2. 如果有两个部门在特定的一天工作,那么会返回一个错误消息,比如“税务与法务冲突”。

正如你从参考数据中看到的,员工在多个领域工作,我试图尽量减少部门之间的重叠/冲突。

期望的结果看起来像这样:

找到在 Excel 中部门中重叠的员工。

任何帮助/指导都将不胜感激!

英文:

I have my reference data which looks like this.

找到在 Excel 中部门中重叠的员工。

I'm trying to create a calendar using weekdays and 5 time slots as shown below.

找到在 Excel 中部门中重叠的员工。

Using the calendar, I want to identify if there are any potential clashes between departments.

What I mean by that is:

  1. On any particular day, an employee must only come in once if they work in the department (regardless of the time slot)
  2. If there are two two departments working in a particular day, then an error message such as "Tax clashes with Legal" is returned.

As you can see from the reference data, employees work in multiple fields and I'm trying to minimise the amount of overlaps/clashes between the departments.

Desired results would look something like this:

找到在 Excel 中部门中重叠的员工。

Any help/guidance is appreciated!

答案1

得分: 1

  1. Const calendarSheet As String = "calendar"
  2. Const calendarRange As String = "A2:E6"
  3. Const employeeSheet As String = "empl"
  4. Const employeeRange As String = "A2:F10"
  5. Sub clashOfJobs()
  6. ' ... (省略部分)
  7. End Sub
  8. Function employeeCol(ByVal arr As Variant) As Collection
  9. ' ... (省略部分)
  10. End Function
  11. Function uniqueDepts(ByVal arr As Variant) As Collection
  12. ' ... (省略部分)
  13. End Function
  14. Function clashes(ByVal employees As Collection, depts As Collection) As String
  15. ' ... (省略部分)
  16. End Function
  17. Sub showOptions()
  18. ' ... (省略部分)
  19. End Sub
  20. Private Sub Worksheet_Change(ByVal Target As Range)
  21. ' ... (省略部分)
  22. End Sub
英文:

Alright I think I understand what OP wants and here is my probably entirely unnecessarily complicated VBA solution:

First, setup:

Sheet "calendar", range A1:E6 looks like this:

Monday Tuesday Wednesday Thursday Friday
Tax Media Cyber
Legal Cyber Policy
Policy IT
Legal

Sheet "empl", range A1:F10 looks like this:

ployee ID Job 1 Job 2 Job 3 Job 4 Job 5
65465489 Tax Legal Cyber
46456464 IT Policy
56489789 IT Legal
64849489 IT International
55544664 Tax Media
19498794 IT Legal
21649849 Media Legal International
48855564 Tax Tax
654658246 Cyber Policy

Code in a "normal" VBA module:

  1. Const calendarSheet As String = "calendar"
  2. Const calendarRange As String = "A2:E6"
  3. Const employeeSheet As String = "empl"
  4. Const employeeRange As String = "A2:F10"
  5. Sub clashOfJobs()
  6. Dim employeeArr() As Variant, rng As Range, calendar As Variant
  7. Set rng = Worksheets(employeeSheet).Range(employeeRange)
  8. employeeArr = rng
  9. Set rng = Worksheets(calendarSheet).Range(calendarRange)
  10. calendar = rng
  11. Dim employees As Collection
  12. Set employees = employeeCol(employeeArr)
  13. Dim departments As Collection, dept As String
  14. For j = 1 To UBound(calendar, 2)
  15. Set departments = New Collection
  16. For i = 1 To UBound(calendar)
  17. dept = calendar(i, j)
  18. If dept <> "" Then
  19. departments.Add dept
  20. calendar(i, j) = clashes(employees, departments)
  21. 'Debug.Print clashes(employees, departments)
  22. End If
  23. Next i
  24. Next j
  25. rng = calendar
  26. End Sub
  27. Function employeeCol(ByVal arr As Variant) As Collection
  28. Set employeeCol = New Collection
  29. Dim empl As Employee
  30. For i = 1 To UBound(arr)
  31. Set empl = New Employee
  32. empl.id = arr(i, 1)
  33. If empl.id <> 0 Then
  34. For j = 2 To UBound(arr, 2)
  35. empl.addJob arr(i, j)
  36. Next j
  37. employeeCol.Add empl
  38. End If
  39. Next i
  40. End Function
  41. Function uniqueDepts(ByVal arr As Variant) As Collection
  42. Set uniqueDepts = New Collection
  43. For i = 1 To UBound(arr)
  44. For j = 2 To UBound(arr, 2)
  45. On Error Resume Next
  46. If arr(i, j) <> "" Then uniqueDepts.Add arr(i, j), arr(i, j)
  47. On Error GoTo 0
  48. Next j
  49. Next i
  50. End Function
  51. Function clashes(ByVal employees As Collection, depts As Collection) As String
  52. Dim separator As String
  53. separator = ", "
  54. Dim emp As Employee, dept As String, job As String, lastDept As String
  55. lastDept = depts(depts.Count)
  56. If depts.Count = 1 Then
  57. clashes = lastDept
  58. Exit Function
  59. End If
  60. Dim clashCounter As Integer
  61. For i = 1 To depts.Count - 1
  62. dept = depts(i)
  63. clashCounter = 0
  64. For Each emp In employees
  65. If emp.hasJob(dept) And emp.hasJob(lastDept) Then
  66. If clashCounter = 0 Then
  67. clashes = clashes & dept
  68. End If
  69. clashCounter = clashCounter + 1
  70. End If
  71. Next emp
  72. If clashCounter > 0 Then
  73. clashes = clashes & "(" & clashCounter & ")" & separator
  74. End If
  75. Next i
  76. If clashes <> vbNullString Then
  77. clashes = lastDept & " clashes with " & clashes
  78. clashes = Left(clashes, Len(clashes) - Len(separator))
  79. Else
  80. clashes = lastDept
  81. End If
  82. End Function
  83. Sub showOptions()
  84. Dim employeeArr() As Variant, rng As Range, calendar As Variant
  85. Set rng = Worksheets(employeeSheet).Range(employeeRange)
  86. employeeArr = rng
  87. Set rng = Worksheets(calendarSheet).Range(calendarRange)
  88. If Application.Intersect(Selection, rng) Is Nothing Then
  89. MsgBox "Please select a calendar cell"
  90. Exit Sub
  91. End If
  92. calendar = rng
  93. Dim employees As Collection, uniqueDepartments As Collection
  94. Set employees = employeeCol(employeeArr)
  95. Set uniqueDepartments = uniqueDepts(employeeArr)
  96. Dim calRow As Integer, calCol As Integer
  97. calRow = Selection.Row - rng.Row + 1
  98. calCol = Selection.Column - rng.Column + 1
  99. Dim departments As Collection, cdpt As String
  100. Set departments = New Collection
  101. For i = 1 To calRow - 1
  102. cdpt = calendar(i, calCol)
  103. If cdpt = "" Then
  104. MsgBox "There are empty cells above your selection, select different cell"
  105. Exit Sub
  106. End If
  107. departments.Add cdpt, cdpt
  108. Next i
  109. Dim clashesStr As String
  110. For Each dept In uniqueDepartments
  111. On Error GoTo skip
  112. departments.Add dept, dept
  113. clashesStr = clashesStr & clashes(employees, departments) & vbCrLf
  114. departments.Remove departments.Count
  115. skip:
  116. On Error GoTo -1
  117. Next dept
  118. MsgBox clashesStr
  119. End Sub

And finally, this has to be put in a CLASS module named "Employee":

  1. Private f_jobs As Collection
  2. Private f_id As Long
  3. Private Sub Class_Initialize()
  4. Set f_jobs = New Collection
  5. End Sub
  6. Public Sub addJob(ByVal job As String)
  7. On Error Resume Next
  8. If job <> "" Then jobs.Add job, job
  9. On Error GoTo 0
  10. End Sub
  11. Property Get jobs() As Collection
  12. Set jobs = f_jobs
  13. End Property
  14. Property Get id() As Long
  15. id = f_id
  16. End Property
  17. Property Let id(ByVal id As Long)
  18. f_id = id
  19. End Property
  20. Public Function hasJob(ByVal job As String) As Boolean
  21. hasJob = False
  22. For Each j In f_jobs
  23. If j = job Then
  24. hasJob = True
  25. Exit For
  26. End If
  27. Next j
  28. End Function

This is what the "Calendar" range looks like after running the "clashOfJobs" sub:

Monday Tuesday Wednesday Thursday Friday
Tax Media Cyber
Legal clashes with Tax Cyber Policy clashes with Cyber
Policy IT clashes with Policy
Legal clashes with Cyber, IT

*to have the code run automatically every time you change the calendar, you can add the following code into the SHEET module of the worksheet where your calendar is. You will have to modify the range again, same as with the code above.

  1. Private Sub Worksheet_Change(ByVal Target As Range)
  2. Application.EnableEvents = False
  3. If Not Application.Intersect(Worksheets("calendar").Range("A2:E6"), Target) Is Nothing Then
  4. clashOfJobs
  5. End If
  6. Application.EnableEvents = True
  7. End Sub

I also added another sub "showOptions", how to use:
select a cell in the calendar that you want to fill and run the macro. A messagebox will pop up, showing you all the possible departments for that slot and what departments that are already in the calendar they clash with.

huangapple
  • 本文由 发表于 2023年2月18日 09:25:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75490606.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定