使用 vba 中其他数组的内容过滤二维数组的最快方法

fastest way to filter an 2D array with the content of other array in vba

嗯,我的工作簿中有超过 200.000 行,所以我需要最快的方法来处理这些数据。

我将数据过滤到临时 sheet 的更简单方法,进行一些计算并删除 sheet 需要大量时间,所以我认为如果我使用数组,我可以提高效率.

我创建了一个具有动态范围的数组来保存所有数据,并且我在不同的数组(日期)中也有唯一的记录,但是我需要循环主数组并过滤日期,例如我可以对当天的结果做一个简单的总结。 日期在第 3 列,value_to_sum 在第 6 列。 我有一个适用于一维数组的代码,但我怎样才能让它适用于多字段数组?

f_array = Filter(main_array, "smith")

我只是想获取每天的价值总和

请测试下一个代码。根据独特的日期数组,它会花费更少的时间。只是好奇处理现有数据范围需要多少时间。现在,它 return 在同一个 sheet 中,从“M2”单元格开始。它可以很容易地适应 return 任何地方:

Sub SummarizePerDate()
 Dim sh As Worksheet, lastR As Long
 Dim arr, arrD, arrFin, i As Long, j As Long
 
 Set sh = ActiveSheet 'use here the sheet with the data to be processed
 lastR = sh.Range("A" & sh.Rows.count).End(xlUp).row
 
 arr = sh.Range("A2:G" & lastR).value 'put the data to be processed in an array
 arrD = sh.Range("K2:K9").value       'use here your array of unique date values
                                      'I used this range when tried testing
 ReDim arrFin(1 To UBound(arrD), 1 To 4)

 For i = 1 To UBound(arrD)
    For j = 1 To UBound(arr)
        If arrD(i, 1) = arr(j, 3) Then
            arrFin(i, 1) = arrD(i, 1)
            arrFin(i, 2) = arrFin(i, 2) + arr(j, 5)
            arrFin(i, 3) = arrFin(i, 3) + arr(j, 6)
            arrFin(i, 4) = arrFin(i, 4) + arr(j, 7)
        End If
    Next j
 Next
 sh.Range("M2").Resize(UBound(arrFin), UBound(arrFin, 2)).value = arrFin
 MsgBox "Ready..."
End Sub

一种比使用数组更快的方法是对工作表执行 SQL 语句。

添加对最新版本 Microsoft ActiveX 数据对象的引用 (Tools -> References...) (通常为 6.0)。

那么你可以编写如下代码:

Const filepath As String = "C:\path\to\excel\file.xlsx"

Dim connectionString As String
connectionString = _
    "Provider=Microsoft.ACE.OLEDB.12.0;" & _
    "Data Source=""" & filepath & """;" & _
    "Extended Properties=""Excel 12.0;HDR=Yes"""

Dim sql As String
sql = _
    "SELECT device, Data, Sum(val3) AS SumOfVal3 " & _
    "FROM [Sheet1$] " & _
    "GROUP BY device, Data"

Dim rs As New ADODB.Recordset
rs.Open sql, connectionString

结果 Recordset object 将包含三列:deviceData 以及 deviceData 的每组总和。

获得记录集后,您可以执行以下操作之一:

  • 使用EOF property, the MoveNext method, and the Fields collection遍历记录集并读取值:

    Do While Not rs.EOF
        Debug.Print rs("device")
        Debug.Print rs("Data")
        Debug.Print rs("SumOfVal3")
        rs.MoveNext
    Loop
    
  • 将其转换为二维数组,使用 GetRows method:

    Dim arr As Variant
    arr = rs.GetRows
    
    ' Indexes are zero-based, so the following line:
    Debug.Print arr(1, 0)
    ' will print the value at the second column -- Data -- in the first row
    
  • 使用GetString method将其转换为单个长字符串;您可以指定您选择的列和行分隔符。

  • 将其粘贴到新的 Excel 工作表中,使用 Excel Range.CopyFromRecordset method

请注意,默认情况下,记录集将以只进模式打开,因此您无法在记录集中来回移动;并且处于只读模式,因此您无法对记录集中的数据进行任何更改。