根据文本变化计算天数
Count days based on text changes
我有 "issue/request date" 和 "work start date" 列。工作从 stage1 开始,到 stage5 结束。
我有一个状态列和 5 个名为列的阶段。每个阶段命名列应显示该阶段在状态 column.for 示例的文本更改后所用的天数,
如果状态单元格包含 "stage1" 文本 2 天,则 stage1 单元格将显示 2,如果状态单元格包含 "stage2" 文本,则在第 3 天,stage2 应显示 1。
DEMO IN EXCEL
在这里,我尝试使用函数
1. =IF(A5214="PLATING",(TODAY()-F5214)-AQ5214,((TODAY()-F5214)-AQ5214-AS5214-AT5214-AU5214))
2. =IF(A5213="PRESS",(TODAY()-F5213),AP5213)
第一个导致循环引用问题,第二个在 condition/text 与 false/not 匹配时更改值(条件失败时单元格值应保留在那里)
我想知道 VBA 是否是唯一的解决方案?请指导我一个轻量级的解决方案,因为这个文件包含大量数据(大约 5k 行)。
提前致谢
这需要 VBA。
仅当对状态列进行更改时才可以使用 "Worksheet_Change" 到 运行,因此行数不应影响性能。
解决此特定问题的一种方法是在每个阶段的开始日期和结束日期列中(AV:AZ 表示每个阶段的开始日期,BA:BE 表示每个阶段的结束日期示例)。
因此,当您更改 A 列中的值时,代码将检查状态的新旧值,然后更新该阶段的开始和结束日期。
这种方法的一个缺点是,如果您错误地 select 一个阶段,您将不得不手动修改每个阶段列的时间,因为每一行只有一次机会更新开始和结束日期。
另一个是当您更改 A 列中的单元格时要获取旧值,我不得不使用 SelectionChange,这意味着您必须在状态更改之间更改 selected 的单元格(这在常规使用中不会成为问题,除非您将同一个单元格从 CNC 更改为 PRESS、PLATING 等,而没有 select 在更改之间使用单独的单元格)。
我在其中多放了一行来保存今天的日期,因此您可以修改 VBA 中的范围以适应。
将sheet修改为如下所示:
Sheet layout
公式来自单元格 AQ3,可以拖到 AU3 - 你可以很容易地修改它来计算正确的天数 "today - start date + 1" 对于阶段仍然有效 - 你可能需要调整这个。
您可以隐藏额外的列,BF1 只是今天的日期 (=TODAY()),BG 列只是 A 列的下拉列表。
Dim oldValue
Public Sub Worksheet_SelectionChange(ByVal Target As Range)
oldValue = Target.Value
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Dim startCol As Variant
Dim endCol As Variant
Dim oVal As Variant
Dim nVal As Variant
oVal = oldValue
nVal = Cells(Target.Row, 1).Value
'make no changes if anything other than column A is changed
If Not Target.Column = 1 Then
GoTo continue
End If
'add end date if status is changed to finished
If nVal = "FINISHED" Then
Cells(Target.Row, 57) = Date
GoTo continue
End If
'update end of last stage only if new value is blank
If IsEmpty(nVal) Then
GoTo endDate
End If
'find the column of the stage being changed
startCol = Range("AV2:AZ2").Find(nVal).Column
If Not IsEmpty(oVal) Then
endCol = Range("BA2:BE2").Find(oVal).Column
End If
Set KeyCells = Range("A:A")
'run if something in column A is changed
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
'update the start date of new stage
If IsEmpty(Cells(Target.Row, startCol)) Then
Cells(Target.Row, startCol) = Date
End If
'update the date of the stage just ended
If IsEmpty(endCol) Then
GoTo continue
End If
If IsEmpty(Cells(Target.Row, endCol)) Then
If IsEmpty(oVal) Then
GoTo continue
End If
Cells(Target.Row, endCol) = Date
End If
End If
GoTo continue
endDate:
If oVal = "FINISHED" Then
GoTo continue
End If
Cells(Target.Row, Range("BA2:BE2").Find(oVal).Column) = Date
continue:
End Sub
我有 "issue/request date" 和 "work start date" 列。工作从 stage1 开始,到 stage5 结束。
我有一个状态列和 5 个名为列的阶段。每个阶段命名列应显示该阶段在状态 column.for 示例的文本更改后所用的天数,
如果状态单元格包含 "stage1" 文本 2 天,则 stage1 单元格将显示 2,如果状态单元格包含 "stage2" 文本,则在第 3 天,stage2 应显示 1。
DEMO IN EXCEL
在这里,我尝试使用函数
1. =IF(A5214="PLATING",(TODAY()-F5214)-AQ5214,((TODAY()-F5214)-AQ5214-AS5214-AT5214-AU5214))
2. =IF(A5213="PRESS",(TODAY()-F5213),AP5213)
第一个导致循环引用问题,第二个在 condition/text 与 false/not 匹配时更改值(条件失败时单元格值应保留在那里)
我想知道 VBA 是否是唯一的解决方案?请指导我一个轻量级的解决方案,因为这个文件包含大量数据(大约 5k 行)。
提前致谢
这需要 VBA。 仅当对状态列进行更改时才可以使用 "Worksheet_Change" 到 运行,因此行数不应影响性能。
解决此特定问题的一种方法是在每个阶段的开始日期和结束日期列中(AV:AZ 表示每个阶段的开始日期,BA:BE 表示每个阶段的结束日期示例)。
因此,当您更改 A 列中的值时,代码将检查状态的新旧值,然后更新该阶段的开始和结束日期。
这种方法的一个缺点是,如果您错误地 select 一个阶段,您将不得不手动修改每个阶段列的时间,因为每一行只有一次机会更新开始和结束日期。
另一个是当您更改 A 列中的单元格时要获取旧值,我不得不使用 SelectionChange,这意味着您必须在状态更改之间更改 selected 的单元格(这在常规使用中不会成为问题,除非您将同一个单元格从 CNC 更改为 PRESS、PLATING 等,而没有 select 在更改之间使用单独的单元格)。
我在其中多放了一行来保存今天的日期,因此您可以修改 VBA 中的范围以适应。
将sheet修改为如下所示: Sheet layout
公式来自单元格 AQ3,可以拖到 AU3 - 你可以很容易地修改它来计算正确的天数 "today - start date + 1" 对于阶段仍然有效 - 你可能需要调整这个。
您可以隐藏额外的列,BF1 只是今天的日期 (=TODAY()),BG 列只是 A 列的下拉列表。
Dim oldValue
Public Sub Worksheet_SelectionChange(ByVal Target As Range)
oldValue = Target.Value
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Dim startCol As Variant
Dim endCol As Variant
Dim oVal As Variant
Dim nVal As Variant
oVal = oldValue
nVal = Cells(Target.Row, 1).Value
'make no changes if anything other than column A is changed
If Not Target.Column = 1 Then
GoTo continue
End If
'add end date if status is changed to finished
If nVal = "FINISHED" Then
Cells(Target.Row, 57) = Date
GoTo continue
End If
'update end of last stage only if new value is blank
If IsEmpty(nVal) Then
GoTo endDate
End If
'find the column of the stage being changed
startCol = Range("AV2:AZ2").Find(nVal).Column
If Not IsEmpty(oVal) Then
endCol = Range("BA2:BE2").Find(oVal).Column
End If
Set KeyCells = Range("A:A")
'run if something in column A is changed
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
'update the start date of new stage
If IsEmpty(Cells(Target.Row, startCol)) Then
Cells(Target.Row, startCol) = Date
End If
'update the date of the stage just ended
If IsEmpty(endCol) Then
GoTo continue
End If
If IsEmpty(Cells(Target.Row, endCol)) Then
If IsEmpty(oVal) Then
GoTo continue
End If
Cells(Target.Row, endCol) = Date
End If
End If
GoTo continue
endDate:
If oVal = "FINISHED" Then
GoTo continue
End If
Cells(Target.Row, Range("BA2:BE2").Find(oVal).Column) = Date
continue:
End Sub