Подсчет дней на основе изменений текста - PullRequest
0 голосов
/ 27 апреля 2019

У меня есть «дата выпуска / запроса» и столбец «дата начала работы». работа начинается с этапа 1 и заканчивается на этапе 5.
У меня есть столбец состояния и 5 этапов с именем столбцы. Каждый столбец с именем стадии должен показывать количество дней, проведенных этим этапом после изменения текста в столбце состояния. Например, если ячейка состояния содержит текст «stage1» в течение 2 дней, то ячейка stage1 будет отображать 2, а на 3-й день, если ячейка состояния содержит текст «stage2», stage2 должна показывать 1.
ДЕМО В ЭКСЕЛ

Здесь я попробовал использовать функции
1. =IF(A5214="PLATING",(TODAY()-F5214)-AQ5214,((TODAY()-F5214)-AQ5214-AS5214-AT5214-AU5214))
2. =IF(A5213="PRESS",(TODAY()-F5213),AP5213)

Первый вызывает проблему с циклической ссылкой, а второй изменяет значение, когда условие / текст ложно / не соответствует (значение ячейки должно оставаться там, пока условие не выполняется)

Интересно, является ли VBA единственным решением для этого? Помогите мне облегчить решение, так как этот файл содержит огромные данные (около 5 тыс. Строк).

Заранее спасибо

1 Ответ

0 голосов
/ 27 апреля 2019

Это должно быть VBA.Вы можете использовать «Worksheet_Change» для запуска только в том случае, если в столбец состояния внесено изменение, поэтому количество строк не должно влиять на производительность.

Одним из способов решения этой конкретной проблемы является включение столбцов для каждого из них.этап для даты начала и окончания (AV: AZ для даты начала каждого этапа, например, BA: BE для даты окончания каждого этапа).

Поэтому, когда вы изменяете значение в столбце A, код будетпроверьте новое и старое значение статуса, затем обновите даты начала и окончания этого этапа.

Недостаток этого подхода заключается в том, что при неправильном выборе этапа вам придется вручную изменять время на каждомСтолбцы стадии, поскольку каждая строка получает только один шанс обновить даты начала и окончания.

Другой способ заключается в том, чтобы получить старое значение при изменении ячейки в столбце A, мне пришлось использовать SelectionChange, что означаетчто вы должны изменить, какая ячейка выбрана между изменениями статуса (это не будет проблемой при регулярном использовании, если вы не меняете ту же ячейку дляm CNC, PRESS, PLATING и т. д. без выбора отдельной ячейки между изменениями.

Я поместил дополнительную строку, чтобы сохранить сегодняшнюю дату, чтобы вы могли изменить диапазоны в VBA, чтобы они соответствовали.

Лист изменен таким образом: Макет листа

Формула из ячейки 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

...