簡體   English   中英

使用 Excel VBA 計算列中連續值的 COUNT

[英]Calculate COUNT of consecutive values in a column with Excel VBA

我在 excel 電子表格中有以下數據

初始數據

我想循環瀏覽 B 列並為每個員工捕獲連續的帶薪休假並生成另一個聚合表,如下所示:

結束狀態數據

因此,對於每個員工,計算額外行中連續帶薪休假的天數以及開始和結束日期(開始第一天和結束連續休假的最后一天)。

我還沒有想出解決這個問題的方法。 我在 VBA 方面的經驗最少,到目前為止,據我所知,這個邏輯似乎非常復雜。 如果有人能提供幫助,我將不勝感激。

評論時間太長了,所以這里可以幫助你:我們盡量不在沒有 OP 的情況下為別人做東西,甚至嘗試編寫任何代碼。 要進入 VBA,請嘗試使用宏閱讀器,然后閱讀 Excel VBA 中的如何避免使用 Select ,也許從https 開始://www.simplilearn.com/tutorials/excel-tutorial so/excel-tutorial你有點明白一切是做什么/是為了什么。 至於從頭到尾的邏輯state:

  • 聲明並設置您的工作簿和工作表
  • Currentrow = 1(或者你想從哪里開始)
  • go 通過帶有 for 循環的 B 列從 1 到 Lastrow(對於 i = Currentrow 到 Lastrow)
  • if Range("B" & i).Value2 = "帶薪休假"
  • 將 i 填充到不同的變量中以存儲您的 startRow(如果下班多日)
  • 相同,但在您的 endrow 變量中(稍后會派上用場)
  • 然后使用 while 循環檢查下一行是否也有帶薪休假,並相應地調整你的 endrow
  • 在同一個 while 循環中,將 Currentrow 調整為 Currentrow + 1(對於每一行,下一個是帶薪休假,您需要增加 for 循環中的步長)
  • amtDays = amtDays+1(while 循環結束)
  • 仍然在那個 If 語句中順便說一句:
  • 獲取不同工作表的最后一行 (lastrow2),然后在變量的幫助下填寫值,即 Start Date 列將獲取 wbOther.wsOther.Range("D" & lastrow2 + 1).Value2 = wbStart.wsStart.Range ("A" & startRow).Value2
  • amtDays = 1(如果結束)
  • 按日期排序(您可以在最后的另一張表中執行此操作)

然后,如果您在嘗試所有這些之后仍然遇到困難,請回來,我們很樂意提供幫助:)

編輯在看到你實際嘗試了一些東西之后,這是我的修訂版本(希望)可以理解的評論,我以前使用過類似的代碼,我不知道為什么我選擇了 for-loop 而不是 while但在這種情況下都可以。

Sub paid_leave()
    Dim wb As Workbook 'declare all your variables upfront and go through your code with F8 from the VBE (VB environment)
    Dim ws As Worksheet, ws2 As Worksheet
    Dim CurrentRow As Long, Lastrow As Long, Lastrow2 As Long, amtDays As Long, i As Long
    
    Set wb = ActiveWorkbook
    Set ws = wb.Sheets("Blad1") 'a lot easier to write the rest of the code with
    Set ws2 = wb.Sheets("Blad2") 'and it helps when you need the change the name of the sheet/workbook
    CurrentRow = 2
    
    Lastrow = ws.Range("B" & Rows.Count).End(xlUp).Row
    amtDays = 1
    For i = CurrentRow To Lastrow 'could technically work with a while loop since we're not using the i and increment our CurrentRow as well
        If ws.Range("B" & CurrentRow).Value2 = "Paid Leave" Then
            Lastrow2 = ws2.Range("A" & Rows.Count).End(xlUp).Row
            ws2.Range("A" & Lastrow2 + 1).Value2 = ws.Range("C" & CurrentRow).Value2 'start and endrow not necessary this way
            ws2.Range("B" & Lastrow2 + 1).Value2 = ws.Range("B" & CurrentRow).Value2
            ws2.Range("D" & Lastrow2 + 1).Value2 = ws.Range("A" & CurrentRow).Value2
            'Do While CurrentRow <> Lastrow 'this is a bad condition, we're already going through all the rows with the for loop, base it on the criteria we want to keep finding aka "Paid Leave"
            Do While ws.Range("B" & CurrentRow + 1).Value2 = "Paid Leave" 'if it's only one day, CurrentRow and amtDays remain on values where it started
                CurrentRow = CurrentRow + 1
                amtDays = amtDays + 1
            Loop
            ws2.Range("C" & Lastrow2 + 1).Value2 = amtDays
            ws2.Range("E" & Lastrow2 + 1).Value2 = ws.Range("A" & CurrentRow).Value2
            amtDays = 1
        End If
        CurrentRow = CurrentRow + 1
        If CurrentRow > Lastrow Then Exit For 'no need to go further (with a while loop this isn't necessary anymore)
    Next i
End Sub

如果您有任何其他問題,請隨時問他們(適當地;))

這也可以使用 Power Query 完成,在 Windows Excel 2010+ 和 Excel 365(Windows 或 Mac)中可用

使用 Power Query

  • Select 數據表中的某個單元格
  • Data => Get&Transform => from Table/Rangefrom within sheet
  • 當 PQ 編輯器打開時: Home => Advanced Editor
  • 記下第 2 行中的表名稱
  • 粘貼下面的 M 代碼代替您看到的內容
  • 將第 2 行中的表名稱更改回最初生成的名稱。
  • 閱讀評論並探索Applied Steps以了解算法
let

//Change Name in next line to reflect actual data source
    Source = Excel.CurrentWorkbook(){[Name="Table5"]}[Content],

//Set the data types
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Status", type text}, {"Name", type text}}),

//Group by status and Name with "GroupKind.Local" argument
    #"Grouped Rows" = Table.Group(#"Changed Type", {"Status", "Name"}, {
        {"Days", each Table.RowCount(_), Int64.Type}, 
        {"Start Date", each List.Min([Date]), type nullable date}, 
        {"End Date", each List.Max([Date]), type nullable date}},
        GroupKind.Local),

//Select only "Paid Leave" in the Status column
    #"Filtered Rows" = Table.SelectRows(#"Grouped Rows", each ([Status] = "Paid Leave"))
in
    #"Filtered Rows"

在此處輸入圖像描述

注意:其中大部分可以在用戶界面中完成。 但是,需要將Date列的默認typedatetime更改為date ,並且需要手動添加GroupKind.Local參數

編輯代碼並添加另一種方法,因為在 Notus_Panda 的最終答案之前我已經解決了更多問題。! 再次感謝。

Sub paid_leave()
Dim wb As Workbook
Dim sh, sh2 As Worksheet

Set wb = ActiveWorkbook
Set sh = wb.Sheets("Sheet1")
Set sh2 = wb.Sheets("Sheet2")

Currentrow = 2
i = 2
lastrow = wb.Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
amtDays = 1

Do While i <= lastrow
    If wb.Sheets("Sheet1").Range("B" & i).Value2 = "Paid Leave" Then
        startRow = i
        endrow = i
        Do While wb.Sheets("Sheet1").Range("B" & i + 1).Value2 = "Paid Leave"
                endrow = endrow + 1
                amtDays = amtDays + 1
                i = i + 1
        Loop
        lastrow2 = wb.Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row
        wb.Sheets("Sheet2").Range("A" & lastrow2 + 1).Value2 = wb.Sheets("Sheet1").Range("C" & startRow).Value2
        wb.Sheets("Sheet2").Range("B" & lastrow2 + 1).Value2 = wb.Sheets("Sheet1").Range("B" & startRow).Value2
        wb.Sheets("Sheet2").Range("C" & lastrow2 + 1).Value2 = amtDays
        wb.Sheets("Sheet2").Range("D" & lastrow2 + 1).Value2 = wb.Sheets("Sheet1").Range("A" & startRow).Value2
        wb.Sheets("Sheet2").Range("E" & lastrow2 + 1).Value2 = wb.Sheets("Sheet1").Range("A" & endrow).Value2
        amtDays = 1
        i = i + 1
    End If
    i = i + 1
Loop
End Sub

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM