VBA在动态构建的工作表数组中将静态范围复制/粘贴到静态范围

问题描述 投票:0回答:2

我试图从一个工作表中复制4个静态范围的单元格值,并将这些值粘贴到我的动态构建列表中包含的每个工作表的4个静态范围内的单元格中。

这是我的代码:

Sub retpsh()
Dim Home As Worksheet: Set Home = Worksheets("Home")
Dim s3 As Worksheet: Set s3 = Worksheets("Sheet3")
Dim s9 As Worksheet: Set s9 = Worksheets("Sheet9")
Dim s5 As Worksheet: Set s5 = Worksheets("Sheet5")
Dim s7 As Worksheet: Set s7 = Worksheets("Sheet7")
Dim Back As Worksheet: Set Back = Worksheets("Home Backstage")
Dim wsarray As Variant
Dim message As String: message = Back.Cells(18, 13)
Dim ws As Variant

If Back.Cells(18, 19) = 0 Then
    If MsgBox("Nothing selected!", vbOKOnly) = vbOK Then Exit Sub
Else
    If MsgBox(message + " Do you wish to continue?", vbYesNo) = vbNo Then Exit Sub
    wsarray = Array(Back.Cells(18, 19)) 'Doesn't work properly
End If

For Each ws In wsarray
    ws.Range("C2:C5", "C8:C11", "C13", "B18:C22") = Worksheets("Home Backstage").Range("B1:B4", "B6:B9", "B11", "B18:C22").Value '''''450 error with or without "Set" before line
Next ws

End Sub

首先,wsarray = Array(Back.Cells(18, 19))不起作用,因为它不解析那个单元格值,它将整个事物作为单个值(即"s3","s5","s7","s9"或任何单元格值)。 Back.Cells(18, 19)有一个公式,根据“主页”页面上选择的4个选项构建列表。该公式将列表构建为以下16种组合中的任何一种:s3,s5,s7或s9。最终的单元格值如下:"s3"或类似"s3","s7","s9"。仅使用Dim wsarray()wsarray() =不会改变行为。任何时候我使用没有wsarray()Array(...)我得到一个'13' Type mismatch错误。

  1. 这是首先动态定义数组的尺寸吗?
  2. 如果没有,有没有办法将单元格值解析为数组?
  3. 如果没有,我将如何在VBA中动态构建数组列表?

其次,即使通过手动指定数组绕过上述问题,我仍然会得到'450' Wrong number of arguments or invalid property assignment错误。我知道设置一个范围与多个非连续单元格=另一个范围设置相同的方式工作正常(例如Range("K15:C18","C29") = Range("C1:C4","C15")),所以:

  1. 为什么语法在For循环中不起作用?

第三,For循环中的语句需要完全限定名称Worksheets("Home Backstage"),并且不接受别名Back

  1. 为什么For不接受工作表别名Back
  2. For循环是否在它之前设置的Dim之外行动因此需要循环内的Dim

我知道我可以通过一堆If语句解决所有这些问题并引用“Home”页面上每个选项的状态来确定要复制到哪些工作表,但我不喜欢这个想法。这似乎不是解决这个问题的正确方法,有一堆重复的代码,对谓词有轻微的改变,因此我希望使用数组。然而,我的问题更多是“为什么”而不是“如何”,但我感谢所有相同的指导或解释!

arrays excel excel-vba vba
2个回答
1
投票

这是另一个选项,非常类似于Scott的,但是使用了更多的数组来处理你的范围:

Sub retpsh()
    Dim Back As Worksheet: Set Back = Worksheets("Home Backstage")
    Dim wsarray As Variant
    Dim fromRangeArray As Variant
    Dim toRangeArray As Variant
    Dim message As String: message = Back.Cells(18, 13)
    Dim ws As Variant

    If Back.Cells(18, 19) = 0 Then
        If MsgBox("Nothing selected!", vbOKOnly) = vbOK Then Exit Sub
    Else
        If MsgBox(message + " Do you wish to continue?", vbYesNo) = vbNo Then Exit Sub
        wsarray = Split(Back.Cells(18, 19).Value, ",")
    End If

    'Could do this into a single multidimensional array if you are a sadist
    fromRangeArray = Array("B1:B4", "B6:B9", "B11", "B18:C22")
    toRangeArray = Array("C2:C5", "C8:C11", "C13", "B18:C22")

    'loop through sheet names
    For Each ws In wsarray
        For rngIndex = 0 To UBound(fromRangeArray)
            Sheets(ws).Range(toRangeArray(rngIndex)).Value = Back.Range(fromRangeArray(rngIndex)).Value
        Next rngIndex
    Next ws

End Sub

1
投票

您需要在单元格中输入实际的工作表名称:

sheet9,sheet7

将字符串或变量等同于变量名称不起作用,因此您需要遍历由Split创建的数组并确保该表存在,然后使用它。

您不能使用具有两个以上单元格引用的范围。范围预计开始和结束。

Sub retpsh()
Dim Home As Worksheet: Set Home = Worksheets("Home")
Dim Back As Worksheet: Set Back = Worksheets("Home Backstage")
Dim wsarray() As String
Dim message As String: message = Back.Cells(18, 13)
Dim i As Long
    If Back.Cells(18, 19) = 0 Then
        If MsgBox("Nothing selected!", vbOKOnly) = vbOK Then Exit Sub
    Else
        If MsgBox(message + " Do you wish to continue?", vbYesNo) = vbNo Then Exit Sub
        wsarray = Split(Back.Cells(18, 19).Value, ",")
    End If

    For i = LBound(wsarray) To UBound(wsarray)
        If Not IsError(Application.Evaluate("'" & wsarray(i) & "'!A1")) Then
            With Worksheets(wsarray(i))
                .Range("C2:C5").Value = Back.Range("B1:B4").Value
                .Range("C8:C11").Value = Back.Range("B6:B9").Value
                .Range("C13").Value = Back.Range("B11").Value
                .Range("B18:C22").Value = Back.Range("B18:C22").Value
            End With
        End If
    Next i

End Sub
© www.soinside.com 2019 - 2024. All rights reserved.