Как найти повторяющиеся значения в столбце и скопировать и вставить найденные дублированные строки [VBA] - PullRequest
0 голосов
/ 06 июня 2019

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

Я хотел найти номера ISIN, которые уже существуют в моем первом столбце (как минимум два раза), а затем взять определенные элементы из другогостолбцы (той же строки, в которой было найдено дублированное значение), например имя эмитента, измененная длительность и т. д., и вставьте их в элементы ISIN других, чтобы сообщать о тех же элементах (данные в других столбцах) в случае, когда номера ISIN являютсятак же.Я также хотел сравнить модифицированную продолжительность этих дублированных продуктов и взять большую (по консервативным причинам, поскольку эти данные используются в дальнейших вычислениях).

Sub dup_cp()

Dim i As Integer
Dim j As Integer
Dim k As Integer

Sheets("Investment Assets").Activate
j = Application.CountA(Range("A:A")) 
'counts the number of filled in rows

For i = 5 To j
'it starts from line 5 on purpose, the ISIN numbers start from that line
    For k = i + 1 To j
        If Sheets("Investment Assets").Range(Cells(k, 55), Cells(k, 55)).Value = "Duplicate Value" Then GoTo skip_dup 
        'it skips the line that has already been detected as duplicated

        If Sheets("Investment Assets").Range(Cells(k, 1), Cells(k, 1)).Value = Sheets("Investment Assets").Range(Cells(i, 1), Cells(i, 1)).Value Then 
        'it finds the duplicate value (ISIN number) in the first column
            If Sheets("Investment Assets").Range(Cells(k, 29), Cells(k, 29)).Value >= Sheets("Investment Assets").Range(Cells(i, 29), Cells(i, 29)).Value Then 
            'it compares the 29th column values (the modified duration of the components) and keeps the bigger value for prudency reasons
                Sheets("Investment Assets").Range(Cells(k, 15), Cells(k, 32)).Copy
                Sheets("Investment Assets").Range(Cells(i, 15), Cells(i, 32)).PasteSpecial Paste:=xlPasteValues
            Else
                Sheets("Investment Assets").Range(Cells(i, 15), Cells(i, 32)).Copy
                Sheets("Investment Assets").Range(Cells(k, 15), Cells(k, 32)).PasteSpecial Paste:=xlPasteValues
            End If
            Sheets("Investment Assets").Range(Cells(k, 55), Cells(k, 55)).Value = "Duplicate Value"
            'it shows in the 55th column if the ISIN number is duplicated or not
            Sheets("Investment Assets").Range(Cells(i, 55), Cells(i, 55)).Value = "Duplicate Value"
        Else
            Sheets("Investment Assets").Range(Cells(k, 55), Cells(k, 55)).Value = "-"
        End If
skip_dup:
    Next
Next

End Sub

Этот код работает, но немного запутани я прошу прощения за это.Заранее спасибо всем, кому потребуется время, чтобы сделать это проще и быстрее.Я думаю, что это поможет любому актуарию или риск-менеджеру, который работает в среде Solvecy II.

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

Изменено несколько вещей.Как уже говорилось, Copy и Activate - самые большие потери производительности.Я ввел оператор With вместо Activate и изменил Copy, Paste на более быстрый ....Value = ....Value

Sub dup_cp()

Dim i As Integer
Dim j As Integer
Dim k As Integer

With Sheets("Investment Assets")
    j = Application.CountA(.Range("A:A"))
    'counts the number of filled in rows

    For i = 5 To j
    'it starts from line 5 on purpose, the ISIN numbers start from that line
        For k = i + 1 To j
            If .Cells(k, 55).Value = "Duplicate Value" Then GoTo skip_dup
            'it skips the line that has already been detected as duplicated

            If .Cells(k, 1).Value = .Cells(i, 1).Value Then
            'it finds the duplicate value (ISIN number) in the first column
                If .Cells(k, 29).Value >= .Cells(i, 29).Value Then
                'it compares the 29th column values (the modified duration of the components) and keeps the bigger value for prudency reasons
                    .Range(.Cells(i, 15), .Cells(i, 32)).Value = .Range(.Cells(k, 15), .Cells(k, 32)).Value
                Else
                    .Range(.Cells(k, 15), .Cells(k, 32)).Value = .Range(.Cells(i, 15), .Cells(i, 32)).Value
                End If
                .Cells(k, 55).Value = "Duplicate Value"
                'it shows in the 55th column if the ISIN number is duplicated or not
                .Cells(i, 55).Value = "Duplicate Value"
            Else
                .Cells(k, 55).Value = "-"
            End If
skip_dup:
        Next
    Next
End With

End Sub

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

Sub xxx

    On Error GoTo ErrorHandler

    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    'Your code

ErrorHandler:
    If Err.Number <> 0 Then MsgBox Err.Number & " " & Err.Description
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True

End Sub

Потому что, если вы отключите эти вещи в начале, а затем вдруг что-то пойдет не так в коде, вы, возможно, не получите эти вещи повторно включенными.

0 голосов
/ 06 июня 2019

Не изменяя ничего, что вы сделали (как после всего, что вы говорите, что это работает), вы можете попытаться отключить некоторые из автоматических функций Excel, прежде чем вызывать вашу подпрограмму:

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False

И затем повторночтобы включить их, когда вы вернетесь со своего подпрограммы:

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True 

Надеемся, вы увидите улучшение скорости выполнения, выполнив это

...