英文:
Filter on multiple columns and compile value to main workbook
问题
以下是修改后的代码,可以根据合同日期和员工筛选数据:
Sub GetMaxWithFilter()
Dim FolderPath As String
Dim FileName As String
Dim wb As Workbook
Dim ws As Worksheet
Dim MaxValue As Date
Dim DatePart As String
Dim LastRow As Long
Dim arr
Application.ScreenUpdating = False
' Update your folder name
FolderPath = "D:\Temp\"
' Clean activesheet and set format
With ActiveSheet
.UsedRange.Clear
.[A1:C1].Value = Array("Date", "Latest Time", "Staff ID")
.Columns(1).NumberFormat = "mm/dd/yyyy"
.Columns(2).NumberFormat = "h:mm:ss AM/PM"
End With
' Retrieve files with "Workbook_*.xlsx"
FileName = Dir(FolderPath & "Workbook_*.xlsx")
Do While FileName <> ""
DatePart = Split(FileName, "_")(1)
Set wb = Workbooks.Open(FolderPath & FileName)
Set ws = wb.Sheets(1)
' Get max value of column B
arr = ws.UsedRange.Value
MaxValue = 0
If UBound(arr, 2) >= 4 Then
For i = 2 To UBound(arr)
If InStr("SYSTEM|VOID", UCase(arr(i, 4))) = 0 And arr(i, 2) = DateSerial(CInt(Mid(DatePart, 1, 4)), CInt(Mid(DatePart, 5, 2)), CInt(Mid(DatePart, 7, 2))) Then
If MaxValue < arr(i, 3) Then MaxValue = arr(i, 3)
End If
Next
End If
wb.Close SaveChanges:=False
With ThisWorkbook.Sheets(1)
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
If LastRow > 2 Or .Cells(LastRow, 1) <> "" Then LastRow = LastRow + 1
.Cells(LastRow, "A").Value = DateSerial(CInt(Mid(DatePart, 1, 4)), CInt(Mid(DatePart, 5, 2)), CInt(Mid(DatePart, 7, 2)))
.Cells(LastRow, "B").Value = MaxValue
.Cells(LastRow, "C").Value = arr(i, 1)
End With
FileName = Dir
Loop
Application.ScreenUpdating = True
End Sub
这个修改后的代码会根据合同日期和员工筛选数据,并将结果放入主工作簿的第一个工作表中的指定列中。希望这对你有所帮助!
英文:
I have multiple workbooks for each date e.g. Workbook_20230505 with data as below:
Staff ID | Time | Staff |
---|---|---|
34565 | 9:00:35 AM | SYSTEM |
23586 | 5:32:05 AM | SYSTEM |
46354 | 4:15:35 AM | ALEX |
46546 | 4:09:30 AM | CLARE |
98744 | 2:54:18 AM | JOHN |
34534 | 3:23:10 AM | SANDY |
87675 | 4:32:09 AM | MANDA |
35645 | 7:15:23 AM | VOID |
23423 | 6:15:23 AM | ALEX |
23423 | 3:46:15 AM | KEN |
34564 | 7:08:23 AM | KEAT |
I am able to compile the latest time given criteria (where Staff <> "SYSTEM" or "VOID") to a main workbook as below:
Update: The Date column has all the days of the month, but not all days there is a workbook. If there is no workbook for that day, leave the result at Latest Time as blank and move to the next day as below. Also, the table below shall start from C10.
Date | Latest Time | Staff ID |
---|---|---|
01/05/2023 | ||
02/05/2023 | ||
03/05/2023 | ||
04/05/2023 | ||
05/05/2023 | 7:08:23 AM | 34564 |
: | : | |
31/05/2023 |
This is the code:
Sub GetMax()
Dim FolderPath As String
Dim FileName As String
Dim wb As Workbook
Dim ws As Worksheet
Dim MaxValue As Date
Dim DatePart As String
Dim LastRow As Long
Dim arr
Application.ScreenUpdating = False
' Update your folder name
FolderPath = "D:\Temp\"
' Clean activesheet and set format
With ActiveSheet
.UsedRange.Clear
.[A1:B1].Value = Array("Date", "LatestTime")
.Columns(1).NumberFormat = "mm/dd/yyyy"
.Columns(2).NumberFormat = "h:mm:ss AM/PM"
End With
' Retrieve files with "Workbook_*.xlsx"
FileName = Dir(FolderPath & "Workbook_*.xlsx")
Do While FileName <> ""
DatePart = Split(FileName, "_")(1)
Set wb = Workbooks.Open(FolderPath & FileName)
Set ws = wb.Sheets(1)
' Get max value of column B
arr = ws.UsedRange.Value
MaxValue = 0
If UBound(arr, 2) >= 3 Then
For i = 2 To UBound(arr)
If InStr("SYSTEM|VOID", UCase(arr(i, 3))) = 0 Then
If MaxValue < arr(i, 2) Then MaxValue = arr(i, 2)
End If
Next
End If
wb.Close SaveChanges:=False
With ThisWorkbook.Sheets(1)
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
If LastRow > 1 Or .Cells(LastRow, 1) <> "" Then LastRow = LastRow + 1
.Cells(LastRow, "A").Value = DateSerial(CInt(Mid(DatePart, 1, 4)), CInt(Mid(DatePart, 5, 2)), CInt(Mid(DatePart, 7, 2)))
.Cells(LastRow, "B").Value = MaxValue
End With
FileName = Dir
Loop
Application.ScreenUpdating = True
End Sub
(Solution from https://stackoverflow.com/questions/76748131/compile-value-from-each-workbook-to-main-workbook/)
How do I modify the above code if I have an additional column for Contract Date, and wish to filter for Contract Date as well as Staff column?
I wish to filter the Contract Date according to the workbook date.
Note: My data starts on row 3 (row 2 is blank)
Staff ID | Contract Date | Time | Staff |
---|---|---|---|
34565 | 20230501 | 9:00:35 AM | SYSTEM |
23586 | 20230501 | 5:32:05 AM | SYSTEM |
46354 | 20230503 | 4:15:35 AM | ALEX |
46546 | 20230503 | 4:09:30 AM | CLARE |
98744 | 20230504 | 2:54:18 AM | JOHN |
34534 | 20230505 | 3:23:10 AM | SANDY |
87675 | 20230502 | 4:32:09 AM | MANDA |
35645 | 20230505 | 7:15:23 AM | VOID |
23423 | 20230505 | 6:15:23 AM | ALEX |
23423 | 20230501 | 3:46:15 AM | KEN |
34564 | 20230501 | 7:08:23 AM | KEAT |
Appreciate the help!
答案1
得分: 0
我已根据新的要求更新了代码。多行已被修改。字典对象用于存储最大值。
Sub GetMax()
Dim FolderPath As String
Dim FileName As String
Dim wb As Workbook
Dim ws As Worksheet
Dim MaxValue As Date
Dim DatePart As String
Dim LastRow As Long
Dim arr, dic, rngRes As Range
Set dic = CreateObject("scripting.dictionary")
Application.ScreenUpdating = False
' 更新文件夹路径
FolderPath = "D:\Temp\"
' 检索文件名匹配 "Workbook_*.xlsx" 的文件
FileName = Dir(FolderPath & "Workbook_*.xlsx")
Do While FileName <> ""
DatePart = Split(Split(FileName, "_")(1), ".")(0)
Set wb = Workbooks.Open(FolderPath & FileName)
Set ws = wb.Sheets(1)
' 从工作表获取数据
arr = ws.UsedRange.Value
MaxValue = 0
If UBound(arr, 2) >= 3 Then
For i = 3 To UBound(arr) ' 从第3行开始
' 过滤数据和员工
If InStr("SYSTEM|VOID", UCase(arr(i, 4))) = 0 And _
CStr(arr(i, 2)) = DatePart Then
arr(i, 3) = CDate(arr(i, 3))
If MaxValue < arr(i, 3) Then MaxValue = arr(i, 3)
End If
Next
End If
' 将 MaxValue 存储在字典中
dic(DatePart) = MaxValue
wb.Close SaveChanges:=False
FileName = Dir
Loop
With ActiveSheet
LastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
Set rngRes = .Range("C10:D" & LastRow)
rngRes.Columns(2).NumberFormat = "h:mm:ss AM/PM"
arr = rngRes.Value
For i = 2 To UBound(arr)
If VBA.IsDate(arr(i, 1)) Then
DatePart = Format(arr(i, 1), "yyyymmdd")
If dic.Exists(DatePart) Then
arr(i, 2) = dic(DatePart)
Else
arr(i, 2) = ""
End If
End If
Next
rngRes.Value = arr
End With
Set dic = Nothing
Application.ScreenUpdating = True
End Sub
英文:
I have updated the code based on the new requirements. Multiple lines have been modified. Dictionary object is used to store the maxvlue.
Sub GetMax()
Dim FolderPath As String
Dim FileName As String
Dim wb As Workbook
Dim ws As Worksheet
Dim MaxValue As Date
Dim DatePart As String
Dim LastRow As Long
Dim arr, dic, rngRes As Range
Set dic = CreateObject("scripting.dictionary")
Application.ScreenUpdating = False
' Update your folder name
FolderPath = "D:\Temp\"
' Retrieve files with "Workbook_*.xlsx"
FileName = Dir(FolderPath & "Workbook_*.xlsx")
Do While FileName <> ""
DatePart = Split(Split(FileName, "_")(1), ".")(0)
Set wb = Workbooks.Open(FolderPath & FileName)
Set ws = wb.Sheets(1)
' Get data from worksheet
arr = ws.UsedRange.Value
MaxValue = 0
If UBound(arr, 2) >= 3 Then
For i = 3 To UBound(arr) ' Start from row 3
' filter Data and Staff
If InStr("SYSTEM|VOID", UCase(arr(i, 4))) = 0 And _
CStr(arr(i, 2)) = DatePart Then
arr(i, 3) = CDate(arr(i, 3))
If MaxValue < arr(i, 3) Then MaxValue = arr(i, 3)
End If
Next
End If
' store MaxValue in Dictionary
dic(DatePart) = MaxValue
wb.Close SaveChanges:=False
FileName = Dir
Loop
With ActiveSheet
LastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
Set rngRes = .Range("C10:D" & LastRow)
rngRes.Columns(2).NumberFormat = "h:mm:ss AM/PM"
arr = rngRes.Value
For i = 2 To UBound(arr)
If VBA.IsDate(arr(i, 1)) Then
DatePart = Format(arr(i, 1), "yyyymmdd")
If dic.exists(DatePart) Then
arr(i, 2) = dic(DatePart)
Else
arr(i, 2) = ""
End If
End If
Next
rngRes.Value = arr
End With
Set dic = Nothing
Application.ScreenUpdating = True
End Sub
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论