You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VBA二维Variant数组赋值与分组求和问题:数组Resize失败

二维数组筛选与分组求和问题

问题描述

我正在遍历一个二维Variant数组(输入格式为Variant/Variant(1 to N, 1 to 4),行数可变、列数固定为4),需要筛选出属于Inventory类的行,并将这些行的剩余元素存入新数组,但始终无法正确调整新数组的大小。最终目标是生成一张分组求和表:第一列为原数组第三列的去重值,第二列为对应分组下Inventory类第四列的求和值,第三列为对应分组下Sold类第四列的求和值。

现有代码

Function sortingArray( arr As Variant )
   Dim counter As Integer
   Dim i As Long
   Dim j As Variant
   Dim z As Variant
   Dim inventory As Variant 
   'if I declare it as: Dim inventory(0,1) As Variant it does not compile
   Dim soldItems As Variant
   cntr = 0
   For i = LBound(arr) To UBound(arr)
      If InStr(arr(i,2), "Inventory") Then
         j = arr(i,3)
         z = arr(i,4)
         If counter = 0 Then
            inventory(0,0) = j
            inventory(0,1) = z
         Else
            ReDim Preserve inventory(counter + 1,1)
            inventory(counter + 1,0) = j
            inventory(counter + 1,1) = z
         End If
         counter = counter + 1
      End If
   Next i
   sortingArray = inventory
End Function

示例输入数组

result类型标识分组代码数值
resultInventory_ProdAA15.468
resultInventory_ProdA4/z10.6704
resultInventory_ProdAb24-00.567
resultInventory_ProdAV31.2
resultSold_ProdAL28.32
resultSold_ProdAA113.450
resultSold_ProdAKP/098.32
resultSold_ProdAV313.450
resultSold_ProdAb24-046.08
resultSold_ProdA4/z2.8370
resultSold_ProdA78-ir-80.0672
resultInventory_ProdBA10.3
resultInventory_ProdB4/z0.05801
resultInventory_ProdBb24-01.0129
resultInventory_ProdBV35.779
resultInventory_ProdBKP/0918.99
resultSold_ProdBL22.355
resultSold_ProdBA10.62
resultSold_ProdB4/z32.011
resultSold_ProdBKP/0915.66

目标结果表

group codeInventory(对应分组求和)Sold(对应分组求和)
A1所有Inventory类A1的数值和所有Sold类A1的数值和
4/z所有Inventory类4/z的数值和所有Sold类4/z的数值和
b24-0所有Inventory类b24-0的数值和所有Sold类b24-0的数值和
V3所有Inventory类V3的数值和所有Sold类V3的数值和
L2所有Inventory类L2的数值和所有Sold类L2的数值和
KP/09所有Inventory类KP/09的数值和所有Sold类KP/09的数值和
78-ir-8所有Inventory类78-ir-8的数值和所有Sold类78-ir-8的数值和

解决方案

1. 数组调整失败的原因

VBA中ReDim Preserve仅允许调整数组的最后一维大小。你当前的数组是(行,列)结构,直接调整行维度会导致数据丢失,这是代码无法正确扩容的核心原因。

2. 推荐方案:用字典实现分组求和

使用Scripting.Dictionary可以自动完成分组去重与求和,无需手动处理数组扩容,代码更简洁高效:

Function GenerateSummary(arr As Variant) As Variant
    Dim dict As Object
    Dim i As Long
    Dim groupCode As String
    Dim isInventory As Boolean
    Dim sumVal As Double
    
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 遍历输入数组,统计分组求和
    For i = LBound(arr, 1) To UBound(arr, 1)
        groupCode = arr(i, 3)
        isInventory = InStr(arr(i, 2), "Inventory") > 0
        sumVal = CDbl(arr(i, 4))
        
        ' 初始化新分组的求和项
        If Not dict.Exists(groupCode) Then
            dict(groupCode) = Array(0, 0) ' 索引0=Inventory求和,1=Sold求和
        End If
        
        ' 更新对应分组的求和值
        If isInventory Then
            dict(groupCode) = Array(CDbl(dict(groupCode)(0)) + sumVal, CDbl(dict(groupCode)(1)))
        Else
            dict(groupCode) = Array(CDbl(dict(groupCode)(0)), CDbl(dict(groupCode)(1)) + sumVal)
        End If
    Next i
    
    ' 将字典数据转换为结果数组
    Dim resultArr() As Variant
    Dim key As Variant
    Dim rowIndex As Long
    
    ReDim resultArr(1 To dict.Count + 1, 1 To 3)
    ' 写入表头
    resultArr(1, 1) = "group code"
    resultArr(1, 2) = "Inventory"
    resultArr(1, 3) = "Sold"
    
    ' 写入分组数据
    rowIndex = 2
    For Each key In dict.Keys
        resultArr(rowIndex, 1) = key
        resultArr(rowIndex, 2) = dict(key)(0)
        resultArr(rowIndex, 3) = dict(key)(1)
        rowIndex = rowIndex + 1
    Next key
    
    GenerateSummary = resultArr
End Function

3. 原数组方案的修复(若坚持用数组)

如果必须使用数组处理,需先统计符合条件的行数,再初始化数组,或通过转置规避ReDim Preserve的限制:

Function sortingArray(arr As Variant) As Variant
    Dim counter As Long
    Dim i As Long
    Dim inventory() As Variant
    
    ' 先统计Inventory类的行数
    counter = 0
    For i = LBound(arr, 1) To UBound(arr, 1)
        If InStr(arr(i, 2), "Inventory") > 0 Then
            counter = counter + 1
        End If
    Next i
    
    ' 初始化并填充数组
    If counter > 0 Then
        ' 先创建(列,行)结构的数组,方便ReDim Preserve
        ReDim inventory(1 To 2, 1 To counter)
        counter = 0
        For i = LBound(arr, 1) To UBound(arr, 1)
            If InStr(arr(i, 2), "Inventory") > 0 Then
                counter = counter + 1
                inventory(1, counter) = arr(i, 3)
                inventory(2, counter) = arr(i, 4)
            End If
        Next i
        ' 转置为(行,列)结构返回
        sortingArray = Application.Transpose(inventory)
    Else
        sortingArray = Empty ' 无符合条件的行时返回空
    End If
End Function

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:57:06