Excel: вычисление разницы между ячейкой и ячейкой выше в автоматически отфильтрованной таблице

У меня есть таблица со столбцом A, содержащим увеличивающиеся числовые значения, а столбец B - это набор имен. Мне нужно отфильтровать таблицу по именам и обновить столбец C с разницей между значением в столбце A в текущей строке и ячейке выше ..

Например, я хотел бы иметь что-то подобное, которое, при фильтрации по столбцу "Имя" должно обновлять разницу, вот так

Я пробовал использовать функцию ПРОМЕЖУТОЧНЫЙ ИТОГ несколькими способами, но безрезультатно. В идеале он будет обновляться после изменения фильтра в таблице. Я пытался сделать это в VBA, но до сих пор у меня есть макрос, который фильтрует только жестко заданные критерии фильтрации.

Решения в формулах excel / python / vba приветствуются и очень ценятся!

Заранее прошу прощения, если этот вопрос не соответствует стандартам, так как я здесь новенький :) Заранее спасибо!

@JvdV: Это результат моей попытки реализовать вашу формулу, Это после фильтрации.


person bigbumbly    schedule 15.08.2018    source источник
comment
Глядя на ваш скриншот, я считаю, что вы ошиблись с диапазонами :). Пожалуйста, смотрите внимательно! Если вы не можете найти ошибку, дайте мне знать, какая формула сейчас находится в вашей ячейке C2.   -  person JvdV    schedule 17.08.2018


Ответы (2)


ПЕРЕСМОТРЕННЫЙ ОТВЕТ

Итак, после вашего объяснения я изучил формулу, которая даст вам разницу между текущим значением B строки за вычетом B-значения появления значения A до этого.

=IFERROR(B2-LOOKUP(2,1/($A$1:A1=A2),$B$1:B2),0)

Взяв ваши образцы данных, это будет выглядеть так:

введите здесь описание изображения

Затем, когда вы примените фильтр, он будет выглядеть так:

введите здесь описание изображения

Таким образом, с помощью этого обходного пути у вас нет правильного значения, когда фильтр не применяется, но в этом случае я предположил, что вас интересует разница, когда он IS отфильтрован!

Формула вводится в ячейку C2 и перемещается вниз.

ИЗМЕНИТЬ

Если это не тот ответ, который вам нужен, и вам НЕОБХОДИМО значения, когда он не отфильтрован, используйте UDF, как показано ниже:

Public Function LastVisibleCell(CL As Range) As Long

Dim RW As Long, X As Long
RW = CL.Row - 1
On Error GoTo 1

If RW > 1 Then
    For X = RW To 1 Step -1
        If ActiveSheet.Rows(X).EntireRow.Hidden Then
        Else
            LastVisibleCell = Cells(CL.Row, 2).Value - Cells(X, 2).Value
            Exit For
        End If
    Next X
Else
1:    LastVisibleCell = 0
End If

End Function

Вызовите его из ячейки C2, например: =LastVisibleCell(A2), и потяните вниз. Когда вы примените фильтр, ячейки обновятся.

Осторожно, обновление больших наборов данных займет много времени!

person JvdV    schedule 15.08.2018
comment
Привет, JvdV, спасибо за ответ! к сожалению, это не то, что я искал. Опять же, извиняюсь за расплывчатость, я обновил вопрос для ясности! - person bigbumbly; 16.08.2018
comment
Привет, @JvdV, спасибо! это прекрасно работает! Я изменил тип данных на удвоение, чтобы можно было использовать десятичные точки. Еще раз спасибо! - person bigbumbly; 20.08.2018

После 3 дней интенсивного (хотя и неэффективного) поиска в Google я наконец наткнулся на answer также при переполнении стека.

Однако, поскольку я работаю с большим набором данных (> 150 000 строк), рассматриваемый метод использует слишком много памяти. Использование VBA для вставки формул только в видимые ячейки, похоже, не решает проблемы.

Sub CopyPasteFormula()
    Dim Ws As Worksheet
    Dim LRow As Long
    Dim PasteRng As Range

    Set Ws = Worksheets("Translated Data")
    Ws.Range("$D$2:$D$200000").AutoFilter Field:=4, Criteria1:="<>-", Operator:=xlFilterValues
    LRow = Ws.Range("D" & Rows.Count).End(xlUp).Row
    Set PasteRng = Ws.Range("A3:A" & LRow).SpecialCells(xlCellTypeVisible)
    Ws.Range("A3").Copy
    PasteRng.PasteSpecial xlPasteFormulas
    Application.CutCopyMode = False
End Sub

Выше мой код макроса, чтобы попытаться уменьшить использование памяти ... Примите во внимание любую обратную связь!

person bigbumbly    schedule 16.08.2018
comment
Если все, что вас интересует, это получить разницу между двумя строками при фильтрации, вы можете применить такую ​​формулу: =IFERROR(B3-LOOKUP(2,1/($A$2:A2=A3),$B$2:B2),""). Если первая строка - заголовки, тогда она переходит в ячейку B3. Просто потяните вниз. Это не имеет особого смысла, если фильтр не применяется. - person JvdV; 16.08.2018
comment
Если вы хотите оставаться в кодах VBA, возможно, изучите использование значения фильтра в цикле .FindNext, вставляющем вашу формулу. Кроме того, вместо вставки формулы вы можете просто получить необходимое значение с помощью vba, извлекая значение с последней видимой ячейкой. Код не должен быть сложным. - person JvdV; 16.08.2018
comment
Привет @JvdV, похоже, твоя формула мне не подходит ... в идеале я бы держался подальше от VBA и других формул. Спасибо, в любом случае! продолжу поиск - person bigbumbly; 17.08.2018
comment
формула работает при следующих допущениях: 1) Имена указаны в столбце A. 2) Числа находятся в столбце B. 3). Заголовки в строке 1. 4) Формула вставлена ​​в C3 (не B3, мой плохой), и ее нужно перетащить вниз. Если это не сработает, покажите мне скриншот того, что вы сделали. - person JvdV; 17.08.2018
comment
@JvdV, скриншот я приложил в вопросе. Также прямо сейчас я работаю над обходным путем на основе некоторого кода, который я нашел в Интернете (больше не могу найти ссылку): Public Function NextVisibleCell(Range As Range) As Range Application.Volatile Dim i As Long Set Range = Range.Cells(Range.Rows.Count, Range.Columns.Count) For i = 1 To Rows.Count - Range.Row If Not Range.Offset(i).EntireRow.Hidden Then Set NextVisibleCell = Range.Offset(i) Exit Function End If Next i End Function , но я не могу заставить его ссылаться на предыдущую строку, только текущую ... - person bigbumbly; 17.08.2018
comment
Я изменил свой ответ, чтобы прояснить, что я собирался делать. - person JvdV; 17.08.2018
comment
@JvdV, извините, забыл обновить отфильтрованную таблицу, кажется, что остались пробелы, и значения не совпадают. Кроме того, я хотел бы увидеть различия, когда это тоже не фильтруется, если это возможно. Не могли бы вы взглянуть на приведенный выше код и посоветовать мне изменить его так, чтобы он ссылался на предыдущую строку? Я думал, что изменение части If Not Range.Offset(i).EntireRow.Hidden на If Not Range.Offset(i-2).EntireRow.Hidden поможет, но это дало мне беспорядочные результаты. ссылка на исходный вопрос находится здесь - person bigbumbly; 17.08.2018
comment
Обновленный ответ. - person JvdV; 17.08.2018