[英]Calculate COUNT of consecutive values in a column with Excel VBA
I have the below data in an excel spreadsheet我在 excel 电子表格中有以下数据
I want to cycle through column B and capture consecutive Paid Leaves for each employee and generate a another aggregated table like the below one:我想循环浏览 B 列并为每个员工捕获连续的带薪休假并生成另一个聚合表,如下所示:
So for each employee to calculate the days of consecutive Paid Leaves in an extra row together with a Start and an End date (Start the first day and End the last day of the consecutive Leave).因此,对于每个员工,计算额外行中连续带薪休假的天数以及开始和结束日期(开始第一天和结束连续休假的最后一天)。
I haven't managed to think of a way to tackle that.我还没有想出解决这个问题的方法。 I have minimum experience in VBA and this logic seems very complex to my knowledge so far.
我在 VBA 方面的经验最少,到目前为止,据我所知,这个逻辑似乎非常复杂。 I would appreciate if anyone could help.
如果有人能提供帮助,我将不胜感激。
This was getting too long for a comment so here's to help you on your way: We try not to just make things for others without OP even trying to code anything.评论时间太长了,所以这里可以帮助你:我们尽量不在没有 OP 的情况下为别人做东西,甚至尝试编写任何代码。 To get into VBA, try out things with the macro reader, then read up on How to avoid using Select in Excel VBA and perhaps start off with https://www.simplilearn.com/tutorials/excel-tutorial/excel-vba so you understand a bit what everything does/is for.
要进入 VBA,请尝试使用宏阅读器,然后阅读 Excel VBA 中的如何避免使用 Select ,也许从https 开始://www.simplilearn.com/tutorials/excel-tutorial so/excel-tutorial你有点明白一切是做什么/是为了什么。 As for logic getting from initial to end state:
至于从头到尾的逻辑state:
Then if you're still stuck after trying all this, come back and we'll be happy to help:)然后,如果您在尝试所有这些之后仍然遇到困难,请回来,我们很乐意提供帮助:)
EDIT After seeing you actually tried out something, here's my revised version of it with (hopefully) understandable commentary, I've used similar code like this before and I don't know anymore why I opted for a for-loop instead of a while but either could work in this case.编辑在看到你实际尝试了一些东西之后,这是我的修订版本(希望)可以理解的评论,我以前使用过类似的代码,我不知道为什么我选择了 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
If you have any further questions, feel free to ask them (properly;))如果您有任何其他问题,请随时问他们(适当地;))
This can also be accomplished using Power Query, available in Windows Excel 2010+ and Excel 365 (Windows or Mac)这也可以使用 Power Query 完成,在 Windows Excel 2010+ 和 Excel 365(Windows 或 Mac)中可用
To use Power Query使用 Power Query
Data => Get&Transform => from Table/Range
or from within sheet
Data => Get&Transform => from Table/Range
或from within sheet
Home => Advanced Editor
Home => Advanced Editor
Applied Steps
to understand the algorithmApplied 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"
Note: Most of this can be done in the User Interface.注意:其中大部分可以在用户界面中完成。 However, the default
type
for the Date
column needs to be changed from datetime
to date
, and the GroupKind.Local
argument needs to be added manually但是,需要将
Date
列的默认type
从datetime
更改为date
,并且需要手动添加GroupKind.Local
参数
Editing the code and adding another approach since I have worked it out a little more before Notus_Panda's final answer.!编辑代码并添加另一种方法,因为在 Notus_Panda 的最终答案之前我已经解决了更多问题。! Thanks a lot again.
再次感谢。
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.