在不同的子语句中引用变量。下标超出范围

时间:2019-07-01 16:36:40

标签: excel vba

第一次来这里的程序员是几天前开始自学VBA来编写的。目的是使代码能够引用两个不是常量的工作簿。用户选择了一个,另一个正在运行宏。我已经在前面的子语句中定义了工作簿,但是当我尝试在下一行的子语句中引用工作簿时,出现错误“ 9”“下标超出范围”。我尝试使用call,但是它也带来了未定义的错误(可能是我不理解'call'语句)。

如果您还有其他时间查看我的公式并确保其格式正确,那也会有很大帮助。我只知道到那儿将会是一个很大的问题。

P.S。我只是注意到,我一直以来都在代码中拼写错误的引用。来吧,笑。

'''
Sub Openfile()

    Dim FileToOpen As Variant, wbRefrence As Workbook
    Dim wbOracle As Workbook
    Set wbOracle = ThisWorkbook

FileToOpen = Application.GetOpenFilename(FileFilter:="Excel Workbooks (*.xls*),*.xls*", Title:="Open Database File")
    If FileToOpen = False Then
    MsgBox "No file selected, cannot continue." 'If the user does not open a file this message is displayed
    Exit Sub 'If no file is selected the program stops running
    End If

    Set wbRefrence = Workbooks.Open(FileToOpen)

    Workbooks.Open (FileToOpen) 'If a file is selected it opens that file.

Call LoopTest1

End Sub


Sub LoopTest1()

Dim BlankCell As Boolean
Dim i As Long
    'Loop until a blank cell is encountered
    Do While BlankCell = False
    i = i + 1

    If Cells(i, "C").Value = "" Then
    BlankCell = True 'When it reaches a blank cell BlankCell will now be true which ends the do while formula.
    End If

    Application.Workbooks("wbOracle").Sheets("Cancel Requisition Lines").Range("C16").Select

'Formula for "do while" condition
Selection.Formula = "=IF(INDEX(['wbRefrence']Sheet1!'A2000:M2000',MATCH(1,(['wbRefrence']Sheet1!'D:D'=['wbOracle']'Cancel Requisition Lines'!'C16')*(['wbRefrence']Sheet1!'E:E'=['wbOracle']'Cancel Requisition Lines'!'I16')*(['wbRefrence']Sheet1!'F:F'=['wbOracle']'Cancel Requisition Lines'!'J16'),0),9)>=['wbOracle']'Cancel Requisition Lines'!M:M, ""materials supplied"","""")"

Loop

End Sub

'''

1 个答案:

答案 0 :(得分:1)

您的代码已经有了一个很好的开端,因此,以下几点可以帮助您上路……

  1. Always use Option Explicit
  2. 尝试定义尽可能接近首次使用的变量(您当前的代码足够简短,没关系,这只是一种习惯)。
  3. Call用法已被弃用,不需要使用。如果要调用函数或子函数,只需使用该例程的名称即可。
    • 此外,如果您在单个语句中有一个单独的子调用,则不需要括号括住参数。如果要在复合语句或赋值语句中进行调用,则必须使用括号。
  4. 一个好习惯是始终fully qualified reference 每次清楚说明您要引用的工作簿,工作表和范围。这件事让很多VBA用户大跌眼镜。

例如,在您的LoopTest1代码中,您指的是Cells。没有任何合格的参考,VBA代码假定是指当前活动的工作表(无论位于何处)。因此,定义一些中间变量并使其清楚(请参见下面的示例)。

  1. 为帮助清除您的LoopTest1子项中的任何混乱,我添加了一些参数,以便您可以处理所选的任何两个工作簿。
  2. 我个人的偏好是在一个单独的字符串变量中构建一个复杂的公式,以便我可以在调试器中对其进行检查并确保它是正确的。这样您就可以看到我定义了一个formulaText字符串并建立了您的公式。
  3. 我“更正”了我在公式中发现的一些内容(但我不能告诉你它会起作用),包括:
    • 在公式中使用两个工作簿的FullName属性(因此您永远不会对其进行硬编码)
    • 使用工作表的Name属性(因此您永远不会对其进行硬编码)
    • 正确安排单点标记以适合正确的工作簿/工作表参考(总的来说,您在公式中使用了太多的单点标记)

只有您可以确定该公式是否确实是您想要的以及它是否有效。但这可能是一个单独的问题:)

Option Explicit

Sub Openfile()
    Dim wbOracle As Workbook
    Set wbOracle = ThisWorkbook

    Dim FileToOpen As Variant
    FileToOpen = Application.GetOpenFilename( _
                          FileFilter:="Excel Workbooks (*.xls*),*.xls*", _
                          Title:="Open Database File")
    If FileToOpen = False Then
        MsgBox "No file selected, cannot continue."
        Exit Sub
    End If

    Dim wbReference As Workbook
    Set wbReference = Workbooks.Open(FileToOpen)
    Workbooks.Open FileToOpen

    LoopTest1 wbOracle, wbReference, "Cancel Requisition Lines"
End Sub

Sub LoopTest1(ByRef wbOracle As Workbook, _
              ByRef wbReference As Workbook, _
              ByVal oracleSheetName As String)
    Dim wsOracle As Worksheet
    Set wsOracle = wbOracle.Sheets(oracleSheetName)

    Dim wsReference As Worksheet
    Dim referenceCell As Range
    Set wsReference = wbReference.Sheet1
    Set referenceCell = wsReference.Range("C1")

    Dim formulaText As String
    Do While Not IsEmpty(referenceCell)
        formulaText = "=IF(INDEX('[" & wbReference.Name & _
                      "]Sheet1'!A2000:M2000,MATCH(1,(['" & wbReference.FullName & _
                      "]Sheet1'!D:D=['" & wbOracle.FullName & _
                      "]" & wsOracle.Name & "'!C16)*('[" & wbReference.FullName & _
                      "]Sheet1!E:E=[" & wbOracle.FullName & _
                      "]" & wsOracle.Name & "'!'I16')*([" & wbReference.FullName & _
                      "]Sheet1!F:F=[" & wbOracle.FullName & _
                      "]" & wsOracle.Name & "'!'J16'),0),9)>=[" & wbOracle.FullName & _
                      "]" & wsOracle.Name & "'!M:M, ""materials supplied"","""")"
        wsOracle.Range("C16").Formula = formulaText
        Set referenceCell = ReferenceCell.Offset(1, 0)
    Loop
End Sub