我有“发布/请求日期”和“工作开始日期”列。工作从第1阶段开始,到第5阶段结束。 我有一个状态列和5个名为列的阶段。名为column的每个阶段应显示状态列上文本更改时该阶段所用的天数。例如,如果状态单元格包含“stage1”文本2天,则stage1单元格将显示2,如果状态单元格显示第3天包含“stage2”文本,然后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)
第一个导致循环引用问题,第二个在条件/文本为假/不匹配时更改值(单元格值应该在条件失败时保持在那里) 我想知道VBA是否是唯一的解决方案?请指导我一个轻量级的解决方案,因为这个文件包含大量数据(约5k行)。
提前致谢
这需要是VBA。只有在对状态列进行更改时才能使用“Worksheet_Change”运行,因此行数不应影响性能。
可以完成这个特定问题的一种方法是为每个阶段列出开始日期和结束日期的列(AV:AZ表示每个阶段的开始日期,BA:BE表示每个阶段的结束日期)。
因此,当您更改A列中的值时,代码将检查状态的新旧值,然后更新该阶段的开始和结束日期。
这种方法的一个缺点是,如果您错误地选择了一个阶段,则必须手动修改每个阶段列的时间,因为每行只有一次机会更新开始和结束日期。
另一个是当你在A列中更改单元格时获取旧值,我必须使用SelectionChange,这意味着你必须更改状态更改之间选择的单元格(这在常规使用中不会有问题) ,除非您将相同的单元格从CNC更改为PRESS,更改为PLATING等,而不在更改之间选择单独的单元格)。
我已经添加了一行来保持今天的日期,所以你可以修改VBA中的范围以适应。
表格修改如下:Sheet layout
该公式来自单元格AQ3,可以拖动到AU3 - 您可以轻松修改此计数,以计算当前仍为活动阶段的“今天 - 开始日期+ 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