在不同的私有子例程中使用公共声明的数组时下标超出范围

Posted

技术标签:

【中文标题】在不同的私有子例程中使用公共声明的数组时下标超出范围【英文标题】:Subscript out of range when using a public declared array in a different private subroutine 【发布时间】:2020-03-29 01:49:51 【问题描述】:

我已将 refedit selected range 分配给名为 dataarray0 的数组,我已将其声明为公共,然后在主子例程中使用此数组。但是,当我从 Private sub 运行到 main 子例程时,我得到了 subscript out of range 错误,我无法弄清楚。请在下面找到两个代码 1 是定义数组的 USERFORM 的代码,2 是使用该数组的代码:

Option Explicit
Public dataarray0 As Variant

Private Sub ActiWorkBook_Change()
   If ActiWorkBook <> "" Then Application.Workbooks(ActiWorkBook.Text).Activate
   Label1.Caption = "": RefEdit1 = ""
End Sub

Private Sub CommandButton1_Click()
Unload Me
End
End Sub


Private Sub CommandButton2_Click()
   Dim addr As String, partderivrng As Range, cell As Range, thisbook As String, NROWSPDIV As Integer
   Dim NCOLSPDIV As Integer
   Dim mydestination As Range
   Dim dataarray0() As Variant, DEST As Variant


   If RefEdit1.Value = "" Then
      Partderiv.Hide
      ERR1.Show
   Else
      addr = RefEdit1.Value
      Set partderivrng = Range(addr)
      NROWSPDIV = Range(addr).Rows.Count
      NCOLSPDIV = Range(addr).Columns.Count
'      ReDim dataarray0(NROWSPDIV, NCOLSPDIV)
      dataarray0() = partderivrng
      ThisWorkbook.Activate
      Sheets("PD").Select
      Set mydestination = Application.InputBox(Prompt:= _
          "What is the first cell in the destination range for data?", Type:=8)
      mydestination.Select

'      mydestination.Paste Link:=True
      Partderiv.Hide

      Set DEST = mydestination.Resize(NROWSPDIV, NCOLSPDIV)
      DEST.Value = dataarray0

   End If
   Data1.Show
   End
End Sub

Private Sub CommandButton3_Click()
Unload Me
DYNA1.Show

End Sub

Private Sub UserForm_Initialize()

   Dim wb As Workbook

   For Each wb In Application.Workbooks
      ActiWorkBook.AddItem wb.Name
   Next

   ActiWorkBook = ActiveWorkbook.Name
   Partderiv.RefEdit1.Text = ""

End Sub

Private Sub RefEdit1_Change()
   Label1.Caption = ""
   If RefEdit1.Value <> "" Then _
   Label1.Caption = "[" & ActiWorkBook & "]" & RefEdit1
End Sub

Sub CALC1_Run(ByRef dataarray1 As Variant, ByRef dataarray0 As Variant)
' This subroutine runs the calculation for the Isolated brick: Simple KWR Strength Calculation
' Created 27/11/2019 by Owen Booler
' Version 1: 27/11/2019 - Creation of subroutine  by Owen Booler
'Integer definitions
' Loop Identifiers
Dim i As Integer, j As Integer, k As Integer
' Other Variables
Dim NSIM As Integer, NSITES As Integer, NKWRS As Integer, NTIME As Integer, NHITS As Integer

' Double Precision definitions
' String definitions
Dim DIST As String

' Array definitions
Dim Prob() As Double, SAMPSTRENGTH() As Double, SDV23 As Double, IRRSAMPSTRENGTH() As Variant
Dim NEWARRAY() As Variant, HITTIME() As Double
' Range definitions
Dim DEST1 As Range, DEST2 As Range



Randomize

' Defintions for Testing
NSIM = 1000
DIST = "N"
NTIME = Val(DYNA1.NUMTINC) + 2
' Real definitions

'NSIM = Val(MCINPUT1.NUMSIM)
'DIST = Val(MCINPUT1.DSTRENGTH)
NSITES = 16 ' Number of cracking sites
NKWRS = 16
'Re define arrays to match size of number of simulations
ReDim SAMPSTRENGTH(NSIM, NKWRS), Prob(NSIM, NKWRS), IRRSAMPSTRENGTH(NSIM, NKWRS)
ReDim NEWARRAY(2, NKWRS)
ReDim HITTIME(NTIME)
'NEWARRAY = Array(Data1.dataarray1)
For i = 1 To NSIM

   ' Calculate Sample Strength
   If DIST = "N" Then

      For j = 1 To NKWRS
         HITTIME(0) = 0
         NHITS = 0
         Prob(i, j) = Rnd()
         SAMPSTRENGTH(i, j) = sabNORMINV(Prob(i, j), 27.5653, 1.1777)
'        SAMPSTRENGTH(i, j) = sabNORMINV(Prob, Val(MCINPUT1.MSTRENGTH), Val(MCINPUT1.SSTRENGTH))


         IRRSAMPSTRENGTH(i, j) = SAMPSTRENGTH(i, j) * dataarray1(2, j + 1)
         For k = 1 To NTIME
' Maybe put a check in here to see whether keyway root are the same in stress and strength
            If dataarray0(k + 2, j + 1) > IRRSAMPSTRENGTH(i, j) Then
               NHITS = NHITS + 1
               HITTIME(k) = dataarray0(k + 2, 1)
            Else
               HITTIME(k) = HITTIME(k - 1)
            End If
            If HITTIME(k) = 0 Then
               GoTo 10
            ElseIf HITTIME(k) < HITTIME(k - 1) Then
               HITTIME(j) = HITTIME(k)
            Else
            End If
10       Next
      Next
   Else
      MsgBox "ERROR - VALUE FOR DISTRIBUTION NOT RECOGNISED"
      End
   End If
Next
Set DEST1 = Sheets("Sample").Range("B2").Resize(NSIM + 1, NKWRS + 1)
Set DEST2 = Sheets("Data").Range("B10").Resize(NSIM + 1, NKWRS + 1)
DEST1.Value = IRRSAMPSTRENGTH
DEST2.Value = SAMPSTRENGTH



End Sub

【问题讨论】:

补充一下,错误发生在``` If dataarray0(k + 2, j + 1) > IRRSAMPSTRENGTH(i, j) Then``` 在您的子程序中,您正在定义一个新数组Dim dataarray0() As Variant, DEST As Variant。这个新数组是 Sub 中的一个使用,不是上面定义的 public 的,它的作用域也不一样。 去掉Sub中的附加定义。 @VincentG 谢谢,但是当我按照您的建议删除 Dim dataarray0() 作为变体时,它在流程的早期出现了另一个错误,现在在dataarray0()=partderivrng 的第一个代码中,错误也是下标范围。 【参考方案1】:

模块中声明的Public变量dataarray0在SubCommandButton2_Click中没有被修改,因为你还在sub中定义了同名的局部变量。

因此,所有对 Sub 中dataarray0 的访问都是在本地定义的变量上进行的,而不是全局公共变量。当尝试从其他地方访问变量时,您访问的是未初始化的 Variant。

如果没有用,请删除屏蔽全局变量的本地不需要的局部变量。

Private Sub CommandButton2_Click()
   Dim addr As String, partderivrng As Range, cell As Range, thisbook As String, NROWSPDIV As Integer
   Dim NCOLSPDIV As Integer
   Dim mydestination As Range
   'Dim dataarray0() As Variant, DEST As Variant
   Dim DEST As Variant
  .
  .
  .
End Sub

编辑: 在您当前的代码中,公共声明是:

Public dataarray0 As Variant

变体可以包含一个数组,因此语法dataarray0 = partdelivery 会将范围的内容分配给该变量,然后该变量将变为 Variant/Variant 数组类型 您将访问这样的数据:

您将无法像这样将 dataarray0 声明为 Variant 数组,至少不能在模块范围内:

Public dataarray0() As Variant 'WRONG -&gt; compile error

【讨论】:

谢谢,但是,当这样做时,错误subscript out of range 现在与dataarray0()=partderivrng 一起存在 dataarray0 没有被定义为一个数组,而是一个变体......所以还没有 dataarray0() 。将定义更改为 Variant 数组,或使用 dataarray0 = partdelivery 初始化值(在这种情况下,它将是包含数组的 Variant) 我不确定你的意思是什么,partdelivrng 是一个范围,我认为为了给一个数组分配一个范围,你需要在末尾加上 ()。在模块中调用它时如何知道它是带有下标 k 和 j 的二维数组? 感谢并抱歉让您感到痛苦,但现在在模块中应用它后,它会在If dataarray0(k + 2, j + 1) &gt; IRRSAMPSTRENGTH(i, j) Then 处出现超出范围的下标,所以回到开头。 数组的Lbounds和Ubounds的值是多少,失败时k、j、i的值是多少?它应该指出错误所在。【参考方案2】:

我发现因为dataarray0userform 中被声明为public,所以它不会作为全局变量,因此当我在我的模块中使用它时,我应该在使用之前放置用户表单名称dataarray0 即

Partderiv.dataarray0这似乎现在可以工作了

谢谢

【讨论】:

以上是关于在不同的私有子例程中使用公共声明的数组时下标超出范围的主要内容,如果未能解决你的问题,请参考以下文章

如何让 VBA 子例程调用将数组传递给子例程中的另一个函数的函数

在子例程中保留 VBA 函数值

模块化程序-子例程

如何在 Perl 子例程中处理已捕获和未捕获的错误?

仅在子例程中需要时才使用 Perl 模块

在子例程中退出 Select Case