【问题标题】:VBA (Excel) Initialize Entire Array without LoopingVBA(Excel)初始化整个数组而不循环
【发布时间】:2013-10-20 15:30:42
【问题描述】:

我对 VBA 还很陌生,所以这可能是一个简单的问题,但在这里。

我想在 VBA 中初始化整个数组myArray,比如整数。我知道我可以通过这样的简单初始化来做到这一点:

Dim myArray
myArray = Array(1, 2, 4, 8)

但是如果数组很大,这很麻烦,我想将所有元素初始化为相同的值。理想情况下应该是这样的:

myArray(:) = 0

我试过了,但编译器抱怨。然后我尝试了myArray() = 0,它也抱怨了这一点。

谁能解释一下如何做到这一点,不循环?如果可能的话,我想在一份声明中做到这一点。

澄清

我想将数组的每个元素初始化为某个初始值。 因此,如果我有一个包含 300 个整数的数组 Dim myArray(300) As Integer,例如,所有 300 个元素都将保持相同的初始值(例如,数字 13)。

更多说明

我发现 this answer 表明您可以使用如下变量执行此操作:

Dim x As Double: x = 0

也许有办法稍微更新语法以使其适用于数组?

【问题讨论】:

标签: arrays vba excel initialization


【解决方案1】:

这很容易,至少如果您想要一个基于 1 的 1D 或 2D 变体数组:

Sub StuffVArr()
    Dim v() As Variant
    Dim q() As Variant
    v = Evaluate("=IF(ISERROR(A1:K1), 13, 13)")
    q = Evaluate("=IF(ISERROR(A1:G48), 13, 13)")
End Sub

字节数组也不错:

Private Declare Sub FillMemory Lib "kernel32" Alias "RtlFillMemory" _
        (dest As Any, ByVal size As Long, ByVal fill As Byte)

Sub StuffBArr()
    Dim i(0 To 39) As Byte
    Dim j(1 To 2, 5 To 29, 2 To 6) As Byte
    FillMemory i(0), 40, 13
    FillMemory j(1, 5, 2), 2 * 25 * 5, 13
End Sub

您可以使用相同的方法填充其他数值数据类型的数组,但仅限于可以用单个重复字节表示的值:

Sub StuffNArrs()
    Dim i(0 To 4) As Long
    Dim j(0 To 4) As Integer
    Dim u(0 To 4) As Currency
    Dim f(0 To 4) As Single
    Dim g(0 To 4) As Double

    FillMemory i(0), 5 * LenB(i(0)), &HFF 'gives -1
    FillMemory i(0), 5 * LenB(i(0)), &H80 'gives -2139062144
    FillMemory i(0), 5 * LenB(i(0)), &H7F 'gives 2139062143

    FillMemory j(0), 5 * LenB(j(0)), &HFF 'gives -1

    FillMemory u(0), 5 * LenB(u(0)), &HFF 'gives -0.0001

    FillMemory f(0), 5 * LenB(f(0)), &HFF 'gives -1.#QNAN
    FillMemory f(0), 5 * LenB(f(0)), &H80 'gives -1.18e-38
    FillMemory f(0), 5 * LenB(f(0)), &H7F 'gives 3.40e+38

    FillMemory g(0), 5 * LenB(g(0)), &HFF 'gives -1.#QNAN
End Sub

如果你想在其他情况下避免循环,它会变得更加棘手。除非您的数组是 50K 或更大的条目,否则这并不值得。正如我在earlier answer 中所说的那样,只需将每个值设置在一个循环中,您就会足够快

【讨论】:

  • 如果使用空白范围,Evaluate 方式可以缩短为 v = [Column(A:KN)*0+13] 甚至 v = [A1:KN1+13]
【解决方案2】:

您可以通过指定维度来初始化数组。例如

Dim myArray(10) As Integer
Dim myArray(1 to 10) As Integer

如果您正在使用数组并且这是您第一次使用,那么我建议您访问 Chip Pearson 的 WEBSITE

这个初始化成什么?例如,如果我想将整个数组初始化为 13 怎么办?

当您想要初始化 13 个元素的数组时,您可以通过两种方式进行

Dim myArray(12) As Integer
Dim myArray(1 to 13) As Integer

首先,数组的下限以0 开头,因此您可以在数组中存储 13 个元素。例如

myArray(0) = 1
myArray(1) = 2
'
'
'
myArray(12) = 13

在第二个示例中,您将下限指定为 1,因此您的数组以 1 开头,并且可以再次存储 13 个值

myArray(1) = 1
myArray(2) = 2
'
'
'
myArray(13) = 13

如果您使用上述任何一种方法初始化数组,则数组中每个元素的值都等于0。要检查,请尝试此代码。

Sub Sample()
    Dim myArray(12) As Integer
    Dim i As Integer

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(i)
    Next i
End Sub

Sub Sample()
    Dim myArray(1 to 13) As Integer
    Dim i As Integer

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(i)
    Next i
End Sub

评论跟进

所以,在这个例子中,每个值都是 13。所以如果我有一个数组 Dim myArray(300) As Integer,那么所有 300 个元素的值都是 13

就像我提到的,AFAIK,没有直接的方法可以实现你想要的。话虽如此,这是一种使用工作表函数Rept 创建重复的 13 字符串的方法。一旦我们有了那个字符串,我们就可以使用SPLIT 使用"," 作为分隔符。但请注意,这会创建一个变量数组,但可以用于计算。

还请注意,在以下示例中,myArray 实际上将保存 301 个值,其中最后一个为空 - 您必须通过额外初始化此值或从 sNum 中删除最后一个“,”来解决这一问题在Split 操作之前。

Sub Sample()
    Dim sNum As String
    Dim i As Integer
    Dim myArray

    '~~> Create a string with 13 three hundred times separated by comma
    '~~> 13,13,13,13...13,13 (300 times)
    sNum = WorksheetFunction.Rept("13,", 300)
    sNum = Left(sNum, Len(sNum) - 1)

    myArray = Split(sNum, ",")

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print myArray(i)
    Next i
End Sub

在计算中使用变量数组

Sub Sample()
    Dim sNum As String
    Dim i As Integer
    Dim myArray

    '~~> Create a string with 13 three hundred times separated by comma
    sNum = WorksheetFunction.Rept("13,", 300)
    sNum = Left(sNum, Len(sNum) - 1)

    myArray = Split(sNum, ",")

    For i = LBound(myArray) To UBound(myArray)
        Debug.Print Val(myArray(i)) + Val(myArray(i))
    Next i
End Sub

【讨论】:

  • 这个初始化成什么?比如我想把整个数组初始化为13怎么办?
  • 根据您的上述评论更新我的答案。
  • 感谢您的澄清,但也许我不清楚这个问题。 what does this initialize to 指的是初始化值。所以,在这个例子中,每个 value 都是 13。所以如果我有一个数组 Dim myArray(300) As Integer,那么所有 300 个元素的值都是 13。
  • "sNum = WorksheetFunction.Rept("13,", 300)" :这是唯一不需要访问工作表中的单元格或行的解决方案,因此可能是最快的。因此,从我的角度来看,这是最好的解决方案。
  • @MarkWalsh:是的。如果您未指定下限,则将其视为0。所以x(0)x(12) 是 13 项。 Dim X(1 to 12) 将只有 12 个项目。您始终可以使用LBound(x)UBound(x) 来检查数组的边界
【解决方案3】:

我想将数组的每个元素初始化为某个初始值。因此,如果我有一个数组 Dim myArray(300) As Integer of 300 integers,例如,所有 300 个元素将保持相同的初始值(例如,数字 13)。

谁能解释一下如何做到这一点,不循环?我想这样做 如果可能的话,在一个声明中。

我赢了什么?

Sub SuperTest()
   Dim myArray
   myArray = Application.Transpose([index(Row(1:300),)-index(Row(1:300),)+13])
End Sub

【讨论】:

  • 不错的答案。我认为这个更好一点虽然myArray = [A1:KN1+13]
【解决方案4】:

对于 VBA,您需要分两行进行初始化。

Sub TestArray()

Dim myArray
myArray = Array(1, 2, 4, 8)

End Sub

【讨论】:

  • 感谢您的评论,但这就是我在问题中提到的 - 我希望一次性将 entire 数组初始化为单个值。
  • @user1205577 Dim myArray = New Integer() {1, 2, 4, 8} 是 vb.net 的有效语法,但不适用于 vba。对于 vba,如果您不想循环,则必须按照我建议的方式进行操作。
  • +1 用于区分 VBA 和 VB.NET,但这仍然意味着您必须为每个元素编写初始化值。问题的核心是如何做到这一点,而不必写出一个值,比如 100 次。
  • @user1205577 当一个变量被定义为整数时,它的默认值为 0。类似地,如果我们定义数组 ...根据@sid 答案Dim myArray(1 to 10) As Integer 数组内的所有元素都将具有值为 0。但我将其称为数组声明,我相信您正在寻找没有循环的声明和初始化。
  • @user1205577 我相信它在 vba 中是不可能的(数组声明并在没有循环的情况下立即为其分配一些其他值)。
【解决方案5】:

此函数适用于大小和初始值的变量,它结合了 tbur 和 Filipe 响应。

Function ArrayIniValue(iSize As Integer, iValue As Integer)
Dim sIndex As String
sIndex = "INDEX(Row(1:" & iSize & "),)"
ArrayIniValue = Evaluate("=Transpose(" & sIndex & "-" & sIndex & "+" & iValue & ")")
End Function

这样称呼:

myArray = ArrayIniValue(350, 13)

【讨论】:

    【解决方案6】:

    将@rdhs 答案放入函数中的好方法:

    Function arrayZero(size As Integer)
      arrayZero = Evaluate("=IF(ISERROR(Transpose(A1:A" & size & ")), 0, 0)")
    End Function
    

    并像这样使用:

    myArray = arrayZero(15)
    

    【讨论】:

      【解决方案7】:

      感谢您的回答。我从 Matlab 重建了一些默认函数来初始化数组。

      • 冒号运算符作为函数
      • 林空间
      • 一个

      希望对任何应用都有帮助

      Function colon( _
          ByVal LB As Integer, _
          ByVal UB As Integer, _
          Optional ByVal Step As Integer = 1, _
          Optional ByRef ColonStr As String = "")
      'generates array from LB to UB with stepwidth Step
      'equal to Matlab operator "a:b" or "a:n:b"
      
      Dim sIndex As String
      Cnt = WorksheetFunction.RoundUp((UB - LB + 1) / Step, 0)
      sIndex = "INDEX(Row(1:" & Cnt & "),)"
      
      ColonStr = "((Transpose(" & sIndex & ")-1)*" & Step & "+" & LB & ")"
      colon = Evaluate("=" & ColonStr)
      End Function
      
      
      Function linspace( _
          ByVal LB As Integer, _
          ByVal UB As Integer, _
          Optional ByVal Count As Integer = 100)
      'requirements: colon()
      'generates linearly spaced array
      'equal to Matlab function linspace()
      
      Dim str As String
      Count0 = Count - 1
      temp = colon(0, Count0, 1, str)
      y = Evaluate("=" & LB & "+" & str & "*" & ((UB - LB) / Count0))
      linspace = "=" & LB & "+" & str & "*" & ((UB - LB) / Count0)
      End Function
      
      
      Function ones( _
          ByVal vert As Integer, _
          Optional ByVal horz As Integer = 1)
      'generate array of all ones
      'horz (multidimension) not implemented yet
      
      Dim sIndex As String
      sIndex = "INDEX(Row(1:" & vert & "),)"
      ones = Evaluate("=Transpose(" & sIndex & ")*0+1")
      End Function
      
      
      Function zeros( _
          ByVal vert As Integer, _
          Optional ByVal horz As Integer = 1)
      'generate array of all zeros
      'horz (multidimension) not implemented yet
      
      Dim sIndex As String
      sIndex = "INDEX(Row(1:" & vert & "),)"
      zeros = Evaluate("=Transpose(" & sIndex & ")*0")
      End Function
      

      【讨论】:

        【解决方案8】:

        通过较新的动态函数Sequence()的一个班轮@

        如果您处置新的动态SEQUENCE() function(与 Excel/MS 365 相比) 您可以创建一个基于 1 且具有指定维度索引的二维数组(例如 5 行、4 列) 其中填充了一个序列号列表。

        由于 OP 需要通过 固定 数值(例如 13 的第三个参数)初始化整个数组, 您只需将增量步骤(最后一个参数)设置为 0:

        Excel 函数 输入到任何想要的工作表单元格中的以下公式将在 spill 范围内显示数组结果:

        =SEQUENCE(5,4,13,0)
         
        

        在 VBA 程序中使用

        也可以任意分配

        • a) 评估结果或
        • b) 工作表函数本身

        到一个预先声明的数组:

            Dim myArray()           ' declare variant array
        

        a) 评估

            myArray = [Sequence(5,4,13,0)]
        
            myArray = Evaluate("Sequence(5,4,13,0)")
        

        b) 函数式方法

            myArray = Worksheetfunction.Sequence(5,4,13,0)  ' or even: Application.Sequence
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-23
          • 2012-11-08
          • 1970-01-01
          • 1970-01-01
          • 2018-01-11
          • 1970-01-01
          • 2016-06-30
          • 1970-01-01
          相关资源
          最近更新 更多