代码之家  ›  专栏  ›  技术社区  ›  PL200

如何从VBA字典更新工作表而不出现性能问题?

  •  0
  • PL200  · 技术社区  · 7 年前

    我有一个相当大的电子表格(表a)(400k行),都有一个唯一的标识符。

    dict.Add 'ID_01', Array('val1', 'val2', 'val3')
    

    然后,为了更新,我遍历了工作表A,每当遇到该ID时,它都会更新单元格。大致来说:

    With sheet A
    For i = 2 to lastrow:
        If dict.exists(.Cells(i, 1).value) Then
            .Cells(i, 2).Value = dict.Item(.Cells(i,1).Value)(0)
            .Cells(i, 3).Value = dict.Item(.Cells(i,1).Value)(1)
            .Cells(i, 4).Value = dict.Item(.Cells(i,1).Value)(2)
    Next i    
    

    以上只是一个模拟示例,但您可以看到为什么这需要很长时间,通常超过10分钟。瓶颈不是将ID/值从表B添加到字典中,而是将它们更新回表A中。

    1 回复  |  直到 7 年前
        1
  •  3
  •   user11026105    7 年前

    在内存中创建并填充二维数组,然后将数组转储回工作表。

    'at this point the dictionary is already populated similar to
    'dict.Add 'ID_01', Array('val1', 'val2', 'val3')
    
    dim i as long, arr as variant
    
    with sheet a
    
        arr = .range(.cells(2, "A"), .cells(.rows.count, "A").end(xlup)).value2
        redim preserve arr(lbound(arr, 1) to ubound(arr, 1), 1 to 4)
        'if sheet A already has values that only require updating,
        'then use this instead
        'arr = .range(.cells(2, "A"), .cells(.rows.count, "A").end(xlup).offset(0, 3)).value2
    
        for i=lbound(arr, 1) to ubound(arr, 1)
            If dict.exists(arr(i, 1)) Then
                arr(i, 2) = dict.Item(arr(i, 1))(0)
                arr(i, 3) = dict.Item(arr(i, 1))(1)
                arr(i, 4) = dict.Item(arr(i, 1))(2)
            end if
        next i
    
        .cells(2, "A").resize(ubound(arr, 1), ubound(arr, 2)) = arr
    
    end with