在VBA中创建1:N的数组

在VBA中创建1:N的数组,vba,excel,Vba,Excel,这是一个超级简单的问题,我还没能从前面的答案中拼凑出一个解决方案 我有N张图片在一张纸上,只是想把它们分组。通常我会使用: Sheets(“Mail”).Shapes.Range(数组(1,2,3,4,5)).Group 但如果我想从1变为N,这显然不起作用。我目前正在尝试: For i = 0 To Y / 33 ReDim Preserve test(i) test(i) = i Next i Sheets("Mail").Shapes.Range(Array(test())).G

这是一个超级简单的问题,我还没能从前面的答案中拼凑出一个解决方案

我有N张图片在一张纸上,只是想把它们分组。通常我会使用:

Sheets(“Mail”).Shapes.Range(数组(1,2,3,4,5)).Group

但如果我想从1变为N,这显然不起作用。我目前正在尝试:

For i = 0 To Y / 33
  ReDim Preserve test(i)
  test(i) = i
Next i

Sheets("Mail").Shapes.Range(Array(test())).Group

但是我不知道如何使用我的测试对象来复制我在非一般情况下使用的格式。感谢您的帮助

这是一个函数,将数值数组从M返回到N

Public Function ReturnArrayAtoB(ByVal M As Long, ByVal N As Long) As Variant

    Dim lngCounter  As Long
    Dim arrReturn   As Variant

    ReDim arrReturn(N - M)

    For lngCounter = 0 To N - M
        arrReturn(lngCounter) = M + lngCounter
    Next lngCounter

    ReturnArrayAtoB = arrReturn

End Function
这就是你所说的:

arrA = ReturnArrayAtoB(1, 5)
arrB = ReturnArrayAtoB(10, 12)
第一个返回
数组(1,2,3,4,5)

第二个函数返回
数组(10,11,12)

为了完整起见,有一种更简洁的方法可以使用
Evaluate
函数创建连续数组:

Public Function ReturnArrayWithEvaluate(ByVal M As Long, ByVal N As Long) As Variant
    Dim vArr1 As Variant
    vArr1 = Application.Transpose(Evaluate("ROW(" & M & ":" & N & ")"))
    ReturnArrayWithEvaluate = vArr1
End Function
正如Vityata在评论中所观察到的,这种方法存在一些缺点:

  • 如果
    N>ActiveSheet.Rows.Count
  • 它的可移植性有限,因为
    在其他VBA版本中不存在,例如
    访问VBA
  • 就性能而言,这是不值得的
我在此报告一些测试,其中我将
N
的值从
10000
更改为
10000000
,并运行这两种方法(对于
M=1

基准设置

使用的功能:

Private Declare Function GetTickCount Lib "kernel32.dll" () As Long

Public Function ReturnArrayWithEvaluate(ByVal M As Long, ByVal N As Long) As Variant
    Dim vArr1 As Variant
    vArr1 = Application.Transpose(ActiveSheet.Evaluate("ROW(" & M & ":" & N & ")"))
    ReturnArrayWithEvaluate = vArr1

End Function

Public Function ReturnArrayAtoB(ByVal M As Long, ByVal N As Long) As Variant

    Dim lngCounter  As Long
    Dim arrReturn   As Variant

    ReDim arrReturn(N - M)

    For lngCounter = 0 To N - M
        arrReturn(lngCounter) = M + lngCounter
    Next lngCounter

    ReturnArrayAtoB = arrReturn

End Function

Sub test()
    Dim M As Long, N As Long
    Dim lTicks As Long
    Dim lCnt As Long, lStep As Long, lCnt2 As Long

    Dim vArrReturn As Variant
    Dim vArrResults As Variant

    M = 1
    N = 10000
    lStep = 9900 / 2
    lCnt2 = 1

    ReDim vArrResults(1 To 99 * N / lStep + 1)

    For lCnt = N To N * 100 Step lStep
        lTicks = GetTickCount
        vArrReturn = ReturnArrayAtoB(M, lCnt)
        vArrResults(lCnt2) = GetTickCount - lTicks
        lCnt2 = lCnt2 + 1
    Next lCnt
    Range("B2").Resize(lCnt2 - 1, 1).Value2 = Application.Transpose(vArrResults)
    lCnt2 = 1
    For lCnt = N To N * 100 Step lStep
        lTicks = GetTickCount
        vArrReturn = ReturnArrayWithEvaluate(M, lCnt)
        vArrResults(lCnt2) = GetTickCount - lTicks
        lCnt2 = lCnt2 + 1
    Next lCnt
    Range("C2").Resize(lCnt2 - 1, 1).Value2 = Application.Transpose(vArrResults)
End Sub
结果

横轴显示
N
,纵轴显示每个方法使用的时间

对于大型阵列,求值比循环快

断言
求值
比循环快实际上是不正确的

平均而言,这两种方法消耗的时间大致相同:

-- Average Looping is 57 ticks
-- Average Evaluate is 62 ticks
-- Median ticks are 62 for both methods

总的来说,我认为坚持循环可能是一个更好的选择。

这是否接受整数变量作为参数?我想以
ReturnArrayAtoB(1,Y)
的形式使用它,其中Y是代码前面定义的整数。目前它提供了一个类型不匹配。@alex1stef2-将我代码中的long改为integer wherewhere,它应该可以工作。我没有尝试过YowE3K的版本,但简单地将long改为integer就行了!谢谢你的帮助@alex1stef2-带有
ByVal
的版本同时接受整数和Long now您的语句不是简单的
Sheets(“Mail”).Shapes.Range(test).Group
,因为
test
已经是一个数组了吗?(您需要将
test(i)=i
更改为
test(i)=i+1
)好消息。我使用过这种方法,这种方法确实比循环提供了更好的性能。。因此+1It有两个缺点-缺点1-它只在Excel中工作(无访问权限等),缺点2-第二次使用
大N/M比率的测试是错误的,但您没有注意到-如果您使用Excel中的行,1000万应该会给出错误。看一看你收到的数组-应该是错误2015。@Zac-阅读我的评论并再次检查你的代码,使用它是危险的。最后但并非最不重要的一点是-循环2^16次的最佳使用比使用Evaluate快得多。@Vityta感谢提示-我用额外的实验和注释修改了文章。代码应该是可复制的,所以如果你能仔细检查结果,那就太好了!