Более 35 000 строк - PullRequest
       2

Более 35 000 строк

0 голосов
/ 22 октября 2018

Я новичок в VBA, но мне помог некоторый код, который мне нужен от друга.

По сути, есть более 35 000 строк данных.Мы ищем ячейки, которые соответствуют одному из четырех различных критериев в столбце H (из памяти).Если он удовлетворяет одному из этих четырех критериев, он слегка изменяет данные в ячейке, а затем ищет соответствующую запись в листе.

Проблема заключается в том, что каждый раз, когда у него есть попадание, он ищет в 35 000+ строкданных и не всегда есть соответствующая запись для них.

Это занимает значительное количество времени (всего более 20 часов для всего листа!).

Есть ли в любом случаеускорить этот процесс?Например, возможно, имитируя функцию CTRL-F вместо циклического перебора всех строк ...?

Любая помощь будет принята с благодарностью :)

Dim VAR_AMOUNT As Double
Dim VAR_STRING As String
Dim VAR_EDITED_STRING As String
Dim VAR_SOURCE As String
Dim VAR_STA_ROW As Long
Dim VAR_MAT_ROW As Long
Dim VAR_END_ROW As Long
Dim VAR_MATCHES As Integer
Dim VAR_ROW_SAV As Long 

VAR_END_ROW = VarRunToBox
VAR_STA_ROW = VarRunFromBox
VAR_MAT_ROW = 1

Tag0:
Range(Cells(VAR_STA_ROW, 8), Cells(VAR_STA_ROW, 8)).Select
VAR_STRING = ActiveCell.Value
VAR_EDITED_STRING = VAR_STRING
Range(Cells(VAR_STA_ROW, 7), Cells(VAR_STA_ROW, 7)).Select
VAR_SOURCE = ActiveCell.Value
Range(Cells(VAR_STA_ROW, 5), Cells(VAR_STA_ROW, 5)).Select
VAR_AMOUNT = ActiveCell.Value
If VAR_AMOUNT < 0 Then VAR_AMOUNT = (VAR_AMOUNT * -1)
If VAR_SOURCE <> "SDE" Then GoTo Tag1

VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 1)
If IsNumeric(VAR_EDITED_STRING) = False Then GoTo Tag1
VAR_EDITED_STRING = VAR_STRING


VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 14)
If IsNumeric(VAR_EDITED_STRING) = True Then GoTo Tag1
VAR_EDITED_STRING = VAR_STRING


VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 13)
If IsNumeric(VAR_EDITED_STRING) = True Then
    VAR_EDITED_STRING = VAR_STRING
    VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 13)
    VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 10) & "0" &      Right(VAR_EDITED_STRING, 3)
    If VAR_AMOUNT >= 15 Then

        Do

VAR_MAT_ROW = VAR_MAT_ROW + 1
Range(Cells(VAR_MAT_ROW, 9), Cells(VAR_MAT_ROW, 9)).Select
            If IsEmpty(ActiveCell.Value) Then GoTo TAG2A
            If ActiveCell.Value = VAR_EDITED_STRING Then
                    VAR_ROW_SAV = ActiveCell.Row
                    VAR_MATCHES = VAR_MATCHES + 1
                    Range(Cells(VAR_STA_ROW, 17 + VAR_MATCHES), Cells(VAR_STA_ROW, 17 + VAR_MATCHES)).Select
                    ActiveCell.Value = VAR_ROW_SAV

            Else
            End If
TAG2A:
            If VAR_MAT_ROW = VAR_END_ROW Then GoTo Tag1


        Loop
    Else

        Do
     VAR_MAT_ROW = VAR_MAT_ROW + 1
            Range(Cells(VAR_MAT_ROW, 8), Cells(VAR_MAT_ROW, 8)).Select
            If IsEmpty(ActiveCell.Value) Then GoTo TAG2B
            If ActiveCell.Value = VAR_EDITED_STRING Then
                    VAR_ROW_SAV = ActiveCell.Row
                    VAR_MATCHES = VAR_MATCHES + 1
                    Range(Cells(VAR_STA_ROW, 17 + VAR_MATCHES), Cells(VAR_STA_ROW, 17 + VAR_MATCHES)).Select
                    ActiveCell.Value = VAR_ROW_SAV

            Else
            End If
            Range(Cells(VAR_MAT_ROW, 9), Cells(VAR_MAT_ROW, 9)).Select
            If IsEmpty(ActiveCell.Value) Then GoTo TAG2B
            If ActiveCell.Value = VAR_EDITED_STRING Then 
                    VAR_ROW_SAV = ActiveCell.Row
                    VAR_MATCHES = VAR_MATCHES + 1
                    Range(Cells(VAR_STA_ROW, 17 + VAR_MATCHES), Cells(VAR_STA_ROW, 17 + VAR_MATCHES)).Select
                    ActiveCell.Value = VAR_ROW_SAV

            Else
            End If
TAG2B:
            If VAR_MAT_ROW = VAR_END_ROW Then GoTo Tag1

        Loop

    End If
Else
    VAR_EDITED_STRING = VAR_STRING
    If VAR_AMOUNT >= 15 Then
        VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 7)
        If IsNumeric(VAR_EDITED_STRING) = True Then
            VAR_EDITED_STRING = VAR_STRING
            VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 7)
            Do

            VAR_MAT_ROW = VAR_MAT_ROW + 1
            Range(Cells(VAR_MAT_ROW, 8), Cells(VAR_MAT_ROW, 8)).Select
            If IsEmpty(ActiveCell.Value) Then GoTo TAG2C
            If ActiveCell.Value = VAR_EDITED_STRING Then
                    VAR_ROW_SAV = ActiveCell.Row
                    VAR_MATCHES = VAR_MATCHES + 1
                    Range(Cells(VAR_STA_ROW, 17 + VAR_MATCHES), Cells(VAR_STA_ROW, 17 + VAR_MATCHES)).Select
                    ActiveCell.Value = VAR_ROW_SAV

            Else
            End If
            Range(Cells(VAR_MAT_ROW, 9), Cells(VAR_MAT_ROW, 9)).Select
            If IsEmpty(ActiveCell.Value) Then GoTo TAG2C
            If ActiveCell.Value = VAR_EDITED_STRING Then
                    VAR_ROW_SAV = ActiveCell.Row
                    VAR_MATCHES = VAR_MATCHES + 1
                    Range(Cells(VAR_STA_ROW, 17 + VAR_MATCHES),  Cells(VAR_STA_ROW, 17 + VAR_MATCHES)).Select
                    ActiveCell.Value = VAR_ROW_SAV

            Else
            End If
TAG2C:
            If VAR_MAT_ROW = VAR_END_ROW Then GoTo Tag1
            Loop
        Else
            GoTo Tag1
        End If
    Else
        GoTo Tag1
    End If

End If

Tag1:
VAR_STA_ROW = VAR_STA_ROW + 1
VAR_MATCHES = 0
VAR_MAT_ROW = 1
If VAR_STA_ROW = VAR_END_ROW Then GoTo Tag3

GoTo Tag0

Tag3: 

Endsubfail:
End Sub

1 Ответ

0 голосов
/ 22 октября 2018

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

  1. Не прост в обслуживании.
  2. Медленно.

Маловероятночто использование range.find () действительно решит вашу проблему, поскольку ваша проблема не в VBA, а в том, как вы структурируете свой алгоритм.

Уже есть много ответов об оптимизации кода, но вот один из моихчто вам может пригодиться .


Основные предложения для этого поста:

Не зацикливаться на ячейках.Используйте массивы!

Не зацикливайтесь на каждой ячейке таблицы, как эта!Это то, что я видел, так много людей делают, и это то, что делает большинство кода VBA чрезвычайно медленным!Это:

dim var as Variant
for i = 1 to 10000
    var = cells(i,1).value
next

Всегда будет намного дольше, чем это:

Dim var, arr as variant
arr = range(cells(1,1),cells(1,10000)).value
for i = 1 to 10000
   var = arr(i,1)
next

Вам не нужна переменная, чтобы иметь условие!

Переменная будетне будет изменено, если оно передано функции (в большинстве ситуаций).Это:

VAR_EDITED_STRING = Left(VAR_EDITED_STRING, 1)
If IsNumeric(VAR_EDITED_STRING) = False Then GoTo Tag1
VAR_EDITED_STRING = VAR_STRING

излишне сложно!Используйте это:

If Not IsNumeric(Left(VAR_STRING, 1)) Then GoTo Tag1

Не используйте ярлыки.Используйте операторы

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

If Not IsNumeric(Left(VAR_STRING, 1)) Then GoTo Tag1

to this:

If IsNumeric(Left(VAR_STRING, 1)) Then
    '...other code...
end if

Это значительно улучшит читабельность кода (хотя это не повлияет на производительность)

Это должно быть на данный момент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...