根据文本更改计算天数

问题描述 投票:0回答:1

我有“发布/请求日期”和“工作开始日期”列。工作从第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行)。

提前致谢

excel vba excel-formula excel-2010
1个回答
0
投票

这需要是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

© www.soinside.com 2019 - 2024. All rights reserved.