Сравнение значений на разных листах (VBA / Формулы)

#excel #vba #for-loop

#excel #vba #цикл for

Вопрос:

У меня есть два листа Excel, один накопительный (с начала года) и один периодический (ежеквартальный). Я пытаюсь проверить наличие потенциальных ошибок ввода.

Упрощенная таблица с начала года:

 ID      Q1/18       Q2/18        Q3/18      Q4/18      Q1/19     Q2/19     ...
1        6           12            20        28        10        20       
2        5           11            18        26        10        20       
3        5           11            18        26        10        20
  

Упрощенная квартальная таблица:

 ID     Q1/18       Q2/18        Q3/18      Q4/18      Q1/19     Q2/19     ...
1        6           6            8          8         10        10       
2        5           6            7          8         10        10       
3        5           6            7          8         10        10       
  

В приведенном выше примере ошибок ввода нет.

Я пытаюсь создать третий лист, который выглядел бы примерно так

 ID     Q1/18       Q2/18        Q3/18      Q4/18      Q1/19     Q2/19     ...
1                    T            T          T         T        T       
2                    T            T          T         T        T       
3                    T            T          T         T        T  
  

Изначально я пытался использовать формулу, подобную этой:

  =IF('YTD'!C2-'YTD LC'!B2-'QTR'!B2=0,T,F)
  

Мне это не особенно нравится, потому что формула не будет применяться в первом квартале. Это также предполагает, что мои данные на обоих листах упорядочены одинаково. Хотя я считаю, что это верно во всех случаях, я бы предпочел иметь что-то вроде сопоставления индексов для подтверждения.

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

 Sub Compare()

lrow = Cells (Rows.Count, 1).End(xlUp).Row
lcol = Cells(1, Columns.Count).End(xltoLeft).Column

Sheets.Add
ActiveSheet.Name = "Temp Sheet"

For i = 2 To lrow
    For j = 3 To lcol

    valytd = Worksheets("YTD").Cells(i,j).Value
    valytd = Worksheets("YTD").Cells(i,j).Value

    If valytd = valytd Then
        Worksheets("Temp").Cells(i,j).Value = "T"
    Else:                           
        Worksheets("Temp").Cells(i,j).Value = "F"
        Worksheets("Temp").Cells(i,j).Interior.Color Index = 40

    End If
    Next j
 Next i
 End Sub
  

Комментарии:

1. Ваша выборка данных большая или примерно в несколько строк?

2. Он довольно большой.

Ответ №1:

На мой взгляд, самый простой способ — это:

  1. Создайте лист и скопируйте строку 1 столбец 1, как показано на рисунке ниже (заголовок и идентификаторы)
  2. Используйте Sum Product для получения ответов

Формула:

 =IF(SUMPRODUCT((Sheet1!$B$1:$G$1=Sheet3!$B$1)*(Sheet1!$A$2:$A$4=Sheet3!A2)*(Sheet1!$B$2:$G$4))=SUMPRODUCT((Sheet2!$B$1:$G$1=Sheet3!$B$1)*(Sheet2!$A$2:$A$4=Sheet3!A2)*(Sheet2!$B$2:$G$4)),"T","F")
  

Примечания к формулам:

  • Продолжайте исправлять диапазон с помощью четвертей, используя double $$ -> Sheet1!$B $ 1:$ G $ 1
  • продолжайте исправлять диапазон идентификаторами, используя double $$ -> Sheet1!$A$2:$ A$ 4
  • Продолжайте фиксировать диапазон значениями -> Лист1!$B $2: $ G $
  • Продолжайте исправлять заголовок столбца -> = Лист3!$ B $ 1
  • Оставьте число строк переменной -> = Лист3!A2

Изображения:

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

Комментарии:

1. Привет, можете ли вы объяснить, как двойной $ $ предотвратит проблему с квартальными результатами?

2. Используя $$, вы исправляете целевой диапазон. Итак, если вы хотите перетащить свою формулу и определенный диапазон, чтобы они оставались неизменными, вы должны использовать $$.

Ответ №2:

Это должно сработать, весь код прокомментирован:

 Option Explicit
Sub Compare()

    Dim arrYTD As Variant, arrQuarterly As Variant, arrResult As Variant
    Dim Compare As Scripting.Dictionary 'You need Microsoft Scripting Runtime for this to work
    Dim i As Long, j As Integer, x As Integer

    With Application
        .EnableEvents = False
        .Calculation = xlCalculationManual
        .DisplayAlerts = False
        .ScreenUpdating = False
    End With

    With ThisWorkbook
        arrYTD = .Sheets("Name of YTD sheet").UsedRange.Value 'this will get everything on that sheet
        arrQuarterly = .Sheets("Name of Quarterly sheet").UsedRange.Value 'this will get everything on that sheet
    End With
    ReDim arrResult(1 To UBound(arrYTD), 1 To UBound(arrYTD, 2)) 'resize the final array with the same size of YTD

    Set Compare = New Scripting.Dictionary

    'Here we fill the dictionary with the ID's position on the arrQuarterly array
    For i = 2 To UBound(arrQuarterly) '2 because 1 is headers
        If Not Compare.Exists(arrQuarterly(i, 1)) Then 'this is an error handle if you have duplicated ID's
            Compare.Add arrQuarterly(i, 1), i 'now we know the position of that ID on the table
        Else
            'Your handle if there was a duplicated ID
        End If
    Next i

    'Let's fill the headers on the result array
    For i = 1 To UBound(arrYTD, 2)
        arrResult(1, i) = arrYTD(1, i)
    Next i

    'Now let's compare both tables assuming the columns are the same on both tables (same position)
    For i = 1 To UBound(arrYTD)
        arrResult(i, 1) = arrYTD(i, 1) 'This is the ID
        For j = 2 To UBound(arrYTD, 2)
            x = Compare(arrYTD(i, 1)) 'this way we get the position on the quarterly array for that ID
            If arrYTD(i, j) = arrQuarterly(x, j) Then 'compare if they have the same value on both sides
                arrResult(i, j) = "T"
            Else
                arrResult(i, j) = "F"
            End If
        Next j
    Next i

    With ThisWorkbook.Sheets("Name of the result sheet") 'paste the array to it's sheet
        .Range("A1", .Cells(UBound(arrResult), UBound(arrResult, 2))).Value = arrResult
    End With

End Sub
  

Комментарии:

1. Спасибо за это. Однако я получаю ошибку в строке: Если не Compare.Exists(arrQuarterly(i, 1)), то я не слишком знаком с тем, что здесь делает «Compare», и поэтому изо всех сил пытаюсь отредактировать код. Был бы признателен, если бы вы могли поделиться! Редактировать: Флажок для среды выполнения Microsoft Scripting установлен.

2. @Cheryl извините, я всегда забываю инициализировать словарь, я отредактировал свой ответ, теперь он должен работать. Compare здесь находится словарь, если вы хотите узнать о словарях, вы можете прочитать это