【问题标题】:Can I nest a With inside a With when both are designating a different sheet in the same workbook? VBA当两者都在同一个工作簿中指定不同的工作表时,我可以将 With 嵌套在 With 中吗? VBA
【发布时间】:2020-01-26 03:02:57
【问题描述】:

基本上,我有一个工作簿,它可以从一个工作表中导入值,然后允许您选择一些、添加额外数据、然后传输所选项目、您添加的值以及包含在其值被拉出的工作表中的其他信息从最初到另一个工作簿。我需要能够将初始工作表中的值与另一张工作表中的相应信息(在同一个工作簿中)相匹配,以便我可以从两者中获取数据并将它们循环输入。我担心我不能嵌套当他们都在同一个工作簿中指定工作表时,我的 Withs 因为我不断收到错误 91(对象变量或未设置块变量)。这是真的吗?

Dim RMs As Worksheet
Dim FLF As Worksheet
Set RMs = Workbooks("FLF Coding Trials.xlsm").Worksheets("Program")
Set FLF = Workbooks("FLF Template.xlsx").Worksheets("FLF Sheet")

Dim lng As Long
Dim cnt As Long
Dim check As Long
Dim length As Long

Dim namecheck As Range
Dim vencheck As Range

With ThisWorkbook.Sheets("Program")
lng = Me.Cells(.Rows.Count, "N").End(xlUp).Row
For cnt = 1 To lng - 1 Step 1
    'The two below lines work reliably
    FLF.Range("B" & cnt + 23).Value = Me.Range("N" & cnt + 1).Value
    FLF.Range("N" & cnt + 23).Value = Me.Range("P" & cnt + 1).Value

    'Adding the following variable designations and the With gives me the error. If I change the below two variables to strings I get a compile error
    namecheck.Value = Range("N" & cnt + 1).Value
    vencheck.Value = Range("P" & cnt + 1).Value

        With ThisWorkbook.Sheets("Names and Vendors")
        length = Me.Cells(.Rows.Count, "B").End(xlUp).Row
        check = ThisWorkbook.Sheets("Names and Vendors").Evaluate("MATCH(1,(B1:B" & length & "=""" & namecheck.Value & """)*(C1:C" & length & "=""" & vencheck.Value & """),0)")
        'more commands will go here
        End With
    Next cnt
End With

【问题讨论】:

  • 既然您实际上并没有使用第二个With(用于“名称和供应商”的那个),为什么不直接删除它呢?
  • 我会的。我将在那里放置一个循环来循环其中包含的所有额外数据,如“更多命令将转到此处”注释所指定的那样。
  • 是的,您可以嵌套 With 块,但只能有一个作用域 - 这将是最接近的 With 的作用域
  • 抱歉,您能详细说明一下吗?我假设 With 中包含的任何内容都只能通过 End With 命令或通过在其中嵌套另一个 With 来完成(正如我在这里尝试的那样)。
  • 我正在尝试复制错误 91。上面的代码是在 Trials、Template 还是其他地方?它是在工作表模块还是类模块中?上面的代码是如何执行的?上面的代码是在 Sub 还是 Function 中?为了确定哪一行代码失败了。

标签: excel vba nested with-statement


【解决方案1】:

如果您在 With 块中,并且您的代码进入第二个 With(没有先点击 End With),那么第二个 With 定义的范围将成为活动范围,直到您点击End With(或另一个With

With A
   'scope here is A
   With B
       'scope here is B
   End with
   'scope here is A
End With

【讨论】:

    【解决方案2】:

    您的代码中有很多问题,但都与With 块无关。

    基于评论我假设我在作用域中指定了对象 Me. 的使用应仅替换为 .

    请参阅下面标有'~~~的代码中的注释

    Dim RMs As Worksheet
    Dim FLF As Worksheet
    Set RMs = Workbooks("FLF Coding Trials.xlsm").Worksheets("Program")
    Set FLF = Workbooks("FLF Template.xlsx").Worksheets("FLF Sheet")
    
    Dim lng As Long
    Dim cnt As Long
    Dim check As Long
    Dim length As Long
    
    Dim namecheck As Range
    Dim vencheck As Range
    
    With ThisWorkbook.Sheets("Program")
        '~~~ .Rows refers to ThisWorkbook.Sheets("Program").Rows
        lng = .Cells(.Rows.Count, "N").End(xlUp).Row '~~~ drop the Me
        For cnt = 1 To lng - 1 Step 1
            'The two below lines work reliably
            '~~~ Me implies this code is in a Worksheet code behind module, and refers to that sheet.  Is this what you intend?
            FLF.Range("B" & cnt + 23).Value = .Range("N" & cnt + 1).Value '~~~ drop the Me
            FLF.Range("N" & cnt + 23).Value = .Range("P" & cnt + 1).Value '~~~ drop the Me
    
            'Adding the following variable designations and the With gives me the error. If I change the below two variables to strings I get a compile error
            '~~~ there is no reference to the With block in these 2 lines of code
            '~~~ And you havn't Set namecheck or vencheck. Add
            Set namecheck = FLF.Range("B" & cnt + 23) '~~~ or whatever range you actually meant
            Set vencheck = FLF.Range("N" & cnt + 23)
            namecheck.Value = Range("N" & cnt + 1).Value '~~~ the unqualified Range(...) refers to the ActiveSheet.  Maybe should be .Range? 
            vencheck.Value = Range("P" & cnt + 1).Value
    
            With ThisWorkbook.Sheets("Names and Vendors")
                '~~~ .Rows now refers to ThisWorkbook.Sheets("Names and Vendors").Rows
                length = .Cells(.Rows.Count, "B").End(xlUp).Row '~~~ drop the Me
                '~~~ you can leave out ThisWorkbook.Sheets("Names and Vendors") as this is in the With block for that sheet
                check = .Evaluate("MATCH(1,(B1:B" & length & "=""" & namecheck.Value & """)*(C1:C" & length & "=""" & vencheck.Value & """),0)")
                'more commands will go here
            End With
            '~~~ .Anything now refers to ThisWorkbook.Sheets("Program").Anything again
        Next cnt
    End With
    

    【讨论】:

    • 非常感谢。如您所知,我正拿着一本我的朋友借给我的 VBA 教科书坐在这里,并使用 Google 尝试将这种语言转变为我的目的。不过,我不明白您在谈论“我”时的意思。我基本上一直用它来指代 ActiveSheet。我假设 Me 在作用域 With 中指定了对象。
    • 我假设 Me 在范围内指定了对象 With 不,它没有。在对 Q 的评论中,您说 Code is in Trials under a Private Sub 如果此代码在 Trials 模块中(在 VBA 编辑器中的“Microsoft Excel 对象”下列出),那么 @987654327 @ 指的是Trials 表。 with 块对象用前导 . 引用(就像您在 Me.Cells(.Rows.Count, "B").End(xlUp).Row 中使用 .Rows 所做的那样)
    • 我可以让你帮我解决最后一件事吗?我得到与 check = .Evaluate..... 行的类型不匹配,经过测试,它以 namecheck.Value 和 vencheck.Value 为中心。我在其他地方使用过类似的代码,它可以工作,但由于某种原因在这里不行。尝试重写它,以便我的代码使用变体,但这不起作用。这是已经有效的行: rw = ThisWorkbook.Sheets("Names and Vendors").Evaluate("MATCH(1,(B1:B" & lr & "=""" & arr(0) & """) *(C1:C" & lr & "=""" & arr(1) & """),0)")
    • 此时变量的值是多少?它们是否生成有效的公式字符串?
    【解决方案3】:

    这个问题更正确的答案是 With 构造应该被限制为一个简单的对象的 getter 和 setter 序列。

    一个很好的例子是 Word Find 对象,下面的代码很常见

    With ActiveDocument.Content.Find
         .Text = "FindText"
         .Replacement.Text = "ReplaceText"
         .Forward = True
         .Wrap = wdFindStop
         Do While .Execute() = True
             .TypeParagraph
             .MoveLeft Unit:=wdWord, Count:=2, Extend:=wdExtend
             .Find.Replacement.Font.Italic = True
             .Font.Bold = True
             .Collapse Direction:=wdCollapseEnd
         Loop
     End With
    

    解决您提出的问题的更正确方法是使用具有本地范围的适当对象来提供您需要的快捷方式,例如

    而不是

    With ThisWorkbook.Sheets("Program")
    
        'Do xyz
    
    End With
    

    使用

    Dim mySourceWb  as excel.Worksheet
    Set mySOurceWb = ThisWorkbook.Sheets("Program")
    Dim myDestWb as Excel.Worksheet
    Set myDestWB = ADifferentWb.Sheets("YetAnotherSpreadsheet")
    
    'Do xyz
    
    set mySourceWb=nothing
    set myDestWb=nothing
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      相关资源
      最近更新 更多