我有“签发/要求日期”和“工作开始日期”列。工作从阶段1开始,到阶段5结束。
我有一个状态栏和5个名为栏的阶段。每个名为column的阶段都应在status列上显示文本更改后该阶段花费的天数。例如,
如果状态单元格包含“ stage1”文本持续2天,则stage1单元格将显示2;如果状态单元格包含“ 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行)。
预先感谢
答案 0 :(得分:0)
这必须是VBA。 您只能在对“状态列”进行更改时使用“ Worksheet_Change”来运行,这样行数才不会影响性能。
可以解决此特定问题的一种方法是在每个阶段的列中输入开始日期和结束日期(例如,AV:AZ代表每个阶段的开始日期,BA:BE代表每个阶段的结束日期)。 / p>
因此,当您更改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