【问题标题】:Nested For Loops locking up Excel嵌套的 For 循环锁定 Excel
【发布时间】:2020-06-18 23:38:05
【问题描述】:

我使用 UVA 数据构建了一个 COVID 模型。该数据目前不可用,因此我找到了另一个数据源。当然,新数据的格式不一样。因此,我不是从头开始,而是以模型编码的格式导入新数据。新数据看起来是这样的……

新数据文件分为确认文件、死亡文件和恢复文件。每个文件有 267 行,并且每天添加一个新列到 EH 列。我对每个文件都有一个宏。 Confirmed 文件运行大约需要一分半钟。完成后它看起来像这样......

我不导入任何已确认 = 0 的数据点。我添加了人口/人口密度列以删除所有我不关心的国家(人口 = 0)。这个文件有大约 6800 行,当然,这也会每天增长。导入Confirmed文件后,当然接下来就是Deaths了。当我尝试导入死亡文件时,excel 进入“无响应”状态并且没有完成。在我杀死它之前,我已经在死亡宏上等待了大约一个小时,但它仍然没有完成。我可以看到正确的数字被放入我合并文件的正确列中,但它真的不应该花这么长时间或像这样锁定 excel。我意识到三个 For 循环多次通过很多单元格。有没有更好的方法来做到这一点?

这是死亡导入代码:

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

如果需要更多代码,我会提供。

【问题讨论】:

  • 你的代码很慢。由于循环的数量,但 b 由于每个循环都在读取和写入单元格。与其一一进行,不如将所有源数据读入一个数组。处理数组并将所有数据一次性写回工作表。
  • 您通过访问工作表比较了Variants 大约 5850 万次。即使是整数比较也会从数组中花费一两秒

标签: excel vba for-loop


【解决方案1】:

感谢@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    相关资源
    最近更新 更多