根据文字变化计算天数

时间:2019-04-27 09:13:32

标签: excel vba excel-formula excel-2010

我有“签发/要求日期”和“工作开始日期”列。工作从阶段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行)。

预先感谢

1 个答案:

答案 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