【问题标题】:UBound inside Redim Preserve throws "Subscript out of range"Redim Preserve 内的 UBound 引发“下标超出范围”
【发布时间】:2020-03-05 03:14:26
【问题描述】:

我想使用一个包含任意数量字符串的动态数组。该数组由if ... then 逻辑而不是循环填充。我不断收到Subscript out of range 错误:

Dim Files() As String

If True Then
    ReDim Preserve Files(UBound(Files) + 1) ' Throws "Subscript out of range" error
    Files(UBound(Files)) = "foo.pdf"
End If

If True Then
    ReDim Preserve Files(UBound(Files) + 1)
    Files(UBound(Files)) = "bar.txt"
End If

If True Then
    ReDim Preserve Files(UBound(Files) + 1)
    Files(UBound(Files)) = "baz.jpg"
End If

我有一个这样声明的函数:

Function SendFiles(Files() As String)

我想摆脱这个错误尽可能不使用变体。我可以重写代码,但我不能使用循环。

【问题讨论】:

  • 一个未调整大小的数组没有UBound
  • @bigben 处理这个问题的最干净的方法是什么?我事先不知道需要添加多少条目,没有循环,并且要求我尽可能使用类型。
  • 您可以在第一个 If 之前使用 ReDim Files(0)。如果您一开始就知道可能的最大尺寸,您可以在一开始调整到该尺寸,然后在最后使用 Preserve 删除任何不必要的元素。
  • 你知道ReDim Preserve分配了一个全新的数组,一个一个地复制元素,然后更新原来的引用,对吧?这是一头表现力的猪。如果您有一个希望经常追加的数组,您应该查看Collection 类型。
  • If True Then 这些行需要吗? TRUE 什么时候不是 TRUE?

标签: arrays vba ms-access


【解决方案1】:

你的数组一开始没有初始化,你不能Redim Preserve一个未初始化的数组。

如果您希望字符串数组包含可变数量的项目,可能为零,您可以使用 Split 将其初始化为长度为零的数组:

Files = Split(vbNullString)

【讨论】:

  • 这似乎可以完成这项工作。是否有语言构造来初始化声明为 Dim Files() As String 的数组,该数组的 UBound = -1?
  • @SalmanA 不,不幸的是,没有。您可以使用Split(vbNullString) 来获取长度为0 的字符串数组,或者使用复杂的WinAPI 调用来减少开销。有关更多背景信息,请参阅This Q&A,获取零长度数组对于字符串以外的任何内容都很困难。
【解决方案2】:

您还可以分配一个足够大的数组,然后将其大小调整为使用的大小。这样你只有 1 个调整大小。像这样的:

Dim Files(1000) As String, i as long

If True Then
    Files(i) = "foo.pdf": i = i+1
End If

If True Then
    Files(i) = "bar.txt": i = i+1
End If

If True Then
    Files(i) = "baz.jpg": i = i+1
End If

redim preserve Files(i-1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 2015-05-27
    相关资源
    最近更新 更多