Вложенные циклы For блокируют Excel - PullRequest
0 голосов
/ 18 июня 2020

Я построил модель COVID, используя данные UVA. Эти данные в настоящее время недоступны, поэтому я нашел другой источник данных. Конечно, новые данные имеют другой формат. Поэтому вместо того, чтобы начинать с нуля, я импортирую новые данные в формате, для которого была создана модель. Новые данные выглядят так ...

enter image description here

Новые файлы данных разбиты на Подтвержденный файл, Файл Смертей и Восстановленный файл. Каждый файл состоит из 267 строк и выходит в столбец EH с ежедневным добавлением нового столбца. У меня есть макрос для каждого файла. Подтвержденный файл запускается от одной до полутора минут. А когда все будет готово, это будет выглядеть так ...

enter image description here

Я не импортирую ни одну из подтвержденных = 0 точек данных. Я добавил столбцы населения / плотности населения, чтобы удалить все страны, которые мне не важны (с населением = 0). В этом файле около 6800 строк, и, конечно же, они будут расти ежедневно. Когда файл с подтверждением импортируется, конечно, следующее - «Смерти». Когда я пытаюсь импортировать файл Deaths, excel переходит в состояние «Не отвечает» и не заканчивает sh. Я ждал макроса Deaths около часа, прежде чем убил его, но он все еще не готов. Я вижу, что правильные числа помещаются в правильный столбец в моем консолидированном файле, но на самом деле это не должно занять так много времени или заблокировать Excel, как это. Я понимаю, что три цикла For Loops много раз проходят через множество ячеек. Есть ли лучший способ сделать это?

Вот код импорта смертей:

Sub ImportCSSEDeaths()

Dim i As Variant
Dim j As Variant
Dim k As Variant
Dim lastrow As Long
Dim clastrow As Long
Dim lastcol As Long
Dim dte As Date
Dim filePath As String
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Dim cws As Excel.Worksheet

Set cws = ThisWorkbook.Sheets("Raw_Data")

lastrow = cws.Cells(Rows.count, "a").End(xlUp).Row

filePath = "C:\Users\chris.h\Desktop\COVID\Other_Data\CSSE\CSSE_Deaths.xlsx"

Set wb = Excel.Workbooks.Open(filePath)
Set ws = wb.Worksheets(1)

clastrow = cws.Cells(Rows.count, "b").End(xlUp).Row

lastrow = ws.Cells(Rows.count, "b").End(xlUp).Row
lastcol = ws.Cells(1, Columns.count).End(xlToLeft).Column

For i = 2 To clastrow
    For j = 2 To lastrow
        For k = 3 To lastcol

            If cws.Cells(i, "a").Value = ws.Cells(j, "a").Value And _
            cws.Cells(i, "b").Value = ws.Cells(j, "b").Value And _
            cws.Cells(i, "c").Value = ws.Cells(1, k).Value Then

                cws.Cells(i, "e").Value = ws.Cells(j, k).Value
                cws.Cells(i, "e").NumberFormat = "#,##0"
            End If
        Next k
    Next j
Next i
wb.Close False

End Sub

Если потребуется больше кода, я предоставлю.

1 Ответ

0 голосов
/ 18 июня 2020

Благодаря @Tom и @Nacorid следующий код на основе массива работает намного быстрее! Это займет всего пару минут.

k = 0
For i = 2 To lastrow
    For j = 3 To lastcol

        'puts country row deaths into array
        If ws.Cells(i, j).Value <> 0 Then
            ReDim Preserve deaths(k)
            deaths(k) = ws.Cells(i, j).Value
            k = k + 1
        End If
    Next j

    'finds startdate in new data
    For j = 3 To lastcol

        If deaths(0) = ws.Cells(i, j).Value Then
            startDate = ws.Cells(1, j).Value
            Exit For
        End If
    Next j

    Debug.Print startDate

    clastrow = cws.Cells(Rows.count, "b").End(xlUp).Row

    'finds startdate in compiled data and enters array values down column e
    For j = 2 To clastrow
        If cws.Cells(j, "a").Value = ws.Cells(i, "a").Value And _
        cws.Cells(j, "b").Value = ws.Cells(i, "b") And _
        cws.Cells(j, "c").Value = startDate Then

            count = j
            For k = 0 To UBound(deaths)
                cws.Cells(count, "e").Value = deaths(k)
                count = count + 1
            Next k
        End If
    Next j
Next i
...