筛选多列并将值编译到主工作簿

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

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
&#39; Update your folder name
FolderPath = &quot;D:\Temp\&quot;
&#39; Clean activesheet and set format
With ActiveSheet
.UsedRange.Clear
.[A1:B1].Value = Array(&quot;Date&quot;, &quot;LatestTime&quot;)
.Columns(1).NumberFormat = &quot;mm/dd/yyyy&quot;
.Columns(2).NumberFormat = &quot;h:mm:ss AM/PM&quot;
End With
&#39; Retrieve files with &quot;Workbook_*.xlsx&quot;
FileName = Dir(FolderPath &amp; &quot;Workbook_*.xlsx&quot;)
Do While FileName &lt;&gt; &quot;&quot;
DatePart = Split(FileName, &quot;_&quot;)(1)
Set wb = Workbooks.Open(FolderPath &amp; FileName)
Set ws = wb.Sheets(1)
&#39; Get max value of column B
arr = ws.UsedRange.Value
MaxValue = 0
If UBound(arr, 2) &gt;= 3 Then
For i = 2 To UBound(arr)
If InStr(&quot;SYSTEM|VOID&quot;, UCase(arr(i, 3))) = 0 Then
If MaxValue &lt; 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, &quot;A&quot;).End(xlUp).Row
If LastRow &gt; 1 Or .Cells(LastRow, 1) &lt;&gt; &quot;&quot; Then LastRow = LastRow + 1
.Cells(LastRow, &quot;A&quot;).Value = DateSerial(CInt(Mid(DatePart, 1, 4)), CInt(Mid(DatePart, 5, 2)), CInt(Mid(DatePart, 7, 2)))
.Cells(LastRow, &quot;B&quot;).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(&quot;scripting.dictionary&quot;)
Application.ScreenUpdating = False
&#39; Update your folder name
FolderPath = &quot;D:\Temp\&quot;
&#39; Retrieve files with &quot;Workbook_*.xlsx&quot;
FileName = Dir(FolderPath &amp; &quot;Workbook_*.xlsx&quot;)
Do While FileName &lt;&gt; &quot;&quot;
DatePart = Split(Split(FileName, &quot;_&quot;)(1), &quot;.&quot;)(0)
Set wb = Workbooks.Open(FolderPath &amp; FileName)
Set ws = wb.Sheets(1)
&#39; Get data from worksheet
arr = ws.UsedRange.Value
MaxValue = 0
If UBound(arr, 2) &gt;= 3 Then
For i = 3 To UBound(arr) &#39; Start from row 3
&#39; filter Data and Staff
If InStr(&quot;SYSTEM|VOID&quot;, UCase(arr(i, 4))) = 0 And _
CStr(arr(i, 2)) = DatePart Then
arr(i, 3) = CDate(arr(i, 3))
If MaxValue &lt; arr(i, 3) Then MaxValue = arr(i, 3)
End If
Next
End If
&#39; store MaxValue in Dictionary
dic(DatePart) = MaxValue
wb.Close SaveChanges:=False
FileName = Dir
Loop
With ActiveSheet
LastRow = .Cells(.Rows.Count, &quot;C&quot;).End(xlUp).Row
Set rngRes = .Range(&quot;C10:D&quot; &amp; LastRow)
rngRes.Columns(2).NumberFormat = &quot;h:mm:ss AM/PM&quot;
arr = rngRes.Value
For i = 2 To UBound(arr)
If VBA.IsDate(arr(i, 1)) Then
DatePart = Format(arr(i, 1), &quot;yyyymmdd&quot;)
If dic.exists(DatePart) Then
arr(i, 2) = dic(DatePart)
Else
arr(i, 2) = &quot;&quot;
End If
End If
Next
rngRes.Value = arr
End With
Set dic = Nothing
Application.ScreenUpdating = True
End Sub

huangapple
  • 本文由 发表于 2023年7月27日 21:07:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76780065.html
匿名

发表评论

匿名网友

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

确定