【问题标题】:VBA Subroutine can't pass variableVBA子程序不能传递变量
【发布时间】:2012-10-21 05:03:34
【问题描述】:

我在将变量从一个子程序传递到另一个子程序时遇到问题。我已将它们宣布为公开,但它似乎不起作用。它说子程序超出范围。我所需要的只是在我的第二个子例程中使用 varUnique(一个数组)和 firstIndex。我需要做什么才能做到这一点?

Public fistIndex As Integer
Public varUnique As Variant
Sub FindUnique()

    Dim varIn As Variant
    Dim iInCol As Long
    Dim iInRow As Long
    Dim iUnique As Long
    Dim nUnique As Long
    Dim isUnique As Boolean
    Dim lastIndex As Integer

    varIn = Range("List")
    ReDim varUnique(1 To UBound(varIn, 1) * UBound(varIn, 2))

    nUnique = 0
    For iInRow = LBound(varIn, 1) To UBound(varIn, 1)
        For iInCol = LBound(varIn, 2) To UBound(varIn, 2)

            isUnique = True
            For iUnique = 1 To nUnique
                If varIn(iInRow, iInCol) = varUnique(iUnique) Then
                    isUnique = False
                    Exit For
                End If
            Next iUnique

            If isUnique = True Then
                nUnique = nUnique + 1
                varUnique(nUnique) = varIn(iInRow, iInCol)
            End If

        Next iInCol
    Next iInRow
    '// varUnique now contains only the unique values.
    '// Trim off the empty elements:
    ReDim Preserve varUnique(1 To nUnique)
    firstIndex = LBound(varUnique)
    lastIndex = UBound(varUnique)


create:
    If Not varUnique(firstIndex) = "Sub-Total" Then
    Worksheets.Add.Name = varUnique(firstIndex)
    Call Ledge(varUnique, firstIndex)
    Else
    End
    End If
    If Not firstIndex = lastIndex Then
    firstIndex = firstIndex + 1
    ActiveCell.Offset(1, 0).Select
    GoTo create
    Else
    End If
End Sub
Sub Ledge(varUnique, firstIndex)
'

'

'Define Variables
Dim Account_type As String
Dim Debit As Long
Dim Credit As Long


'Select Journal and Cell B4
    Sheets("Journal").Select
    Range("B4").Select

Account_Search:
'Make that cell= account_type
    Account_type = ActiveCell.Value
'If that cell= cash then save the values adjecent
    If Account_type = varUnique(firstIndex) Then
        ActiveCell.Offset(0, 1).Select
        Debit = ActiveCell.Value
        ActiveCell.Offset(0, 1).Select
        Credit = ActiveCell.Value
'Then go back to where you began
        ActiveCell.Offset(0, -2).Select
'Select Cash and Cell A2
        Sheets(varUnique(firstIndex)).Select
        Range("A2").Select
Search:
'If both cells are empy
            If ActiveCell.Value = "" And ActiveCell.Offset(0, 1).Value = "" Then
'Then write values and indicate you have done so
               ActiveCell.Value = Debit
               ActiveCell.Offset(0, 1).Select
               ActiveCell.Value = Credit
               Else
'If they are not empty go down one cell and search again
               ActiveCell.Offset(1, 0).Select
               GoTo Search
            End If
'Once it is recorded go to Journal again and go down one more cell
                Sheets("Journal").Select
                ActiveCell.Offset(1, 0).Select
'If it wasn't cash then go down one
    Else
        ActiveCell.Offset(1, 0).Select
    End If
'Record that cell value and check to see if it is not sub-total
    Account_type = ActiveCell.Value
    If Not Account_type = "Sub-Total" Then
'Now see if it is cash
        GoTo Account_Search
    Else
    End If
End Sub

【问题讨论】:

  • a) 使用函数返回值,而不是在 Sub 中设置全局变量。好的代码没有全局变量。 b) 也许你应该在任何地方都称你为变量firstIndex,而不是有时称它为fistIndex。使用Option Explicit 看看会发生什么。事实上,你真的应该在你编写的所有 VBA 代码中使用它。
  • @Tomalak 告诉人们好的代码没有全局变量是没有帮助的。或者是真的。取出全局变量并不会使坏代码变好,而放入全局变量并不会使好代码变坏。另外,您对Option Explicit 的看法是完全正确的。
  • @Seith 是的,关于全局变量的部分有点争议。无论如何,我认为避免将状态保存在全局变量中是一个好习惯,尤其是作为初学者,尤其是在上述情况下。对所有事情都使用全局变量太简单了,太诱人了,而且没有什么好处。
  • @Tomalak 我不认为这是争论。全局变量是一种副作用,而副作用通常被认为是一件坏事。也许将信息软化为“避免使用全局变量来存储状态;更喜欢将参数显式传递给函数”?
  • >> “它说子程序超出范围。” ???你确定这不是“下标超出范围”吗?它发生在哪一行?

标签: vba excel subroutine


【解决方案1】:

我不认为错误是因为传递参数,尽管“下标超出范围”可能来自 firstIndex 指向 varUnique 数组中的缺失项。

关于您的代码的一些想法:

  • 通常,您应该避免使用变体,即使它们在涉及数组时会很方便。而是使用类型化数组(在本例中为字符串数组,请改用 Dim varUnique() as String)或集合
  • 您还应尽可能避免使用公共变量或全局变量,如您问题的 cmets 中所述。在您上面的代码中,它们绝对不是必需的。
  • 使用Option Explicit,上面也提到过。用这种方式编译会发现很多错误,否则很难找到错误(参见fistIndex vs firstIndex
  • 使用函数将值传递回调用子 - 我认为在您的示例中不需要它 - 据我所知,您不会更改 firstIndex

最后,我知道几个在 subs 和函数之间传递参数的示例,但正如我所说,我认为这不是你遇到问题的地方。

Option Explicit

Sub OuterSub()
    Dim varUnique As Variant
    Dim firstIndex As Integer
    Dim returnedInt As Integer

    '***** Create array
    varUnique = Array("String#1", "String#2", "String#3", "String#4", "String#5", "String#6")

    '***** Get first index
    firstIndex = LBound(varUnique)

    '***** Pass variables to second sub
    Call InnerSub(varUnique, firstIndex)

    '***** Pass variables to and from function
    returnedInt = InnerFunction(varUnique, firstIndex)

    Debug.Print "returnedInt=" & returnedInt & ", varUnique(returnedInt)=" & varUnique(returnedInt)
End Sub

Sub InnerSub(pvIn As Variant, piIndex As Integer)
    '***** Do something with the paramterers, like
    '***** checking to see if pvIn is an array
    If IsArray(pvIn) Then
        Debug.Print pvIn(piIndex)
    Else
        Debug.Print "pvIn not an array..."
    End If
End Sub

Function InnerFunction(pvIn As Variant, piIndex As Integer) As Integer
    '***** Return Integer
    InnerFunction = piIndex + 1
End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    相关资源
    最近更新 更多