VBA在动态构建的工作表数组

时间:2017-12-19 19:16:15

标签: arrays excel excel-vba vba

我正在尝试从一个工作表中复制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)有一个公式,可根据" Home"上选择的4个选项构建列表。页。该公式将列表构建为以下16种组合中的任何一种:s3,s5,s7或s9。最终的单元格值如下:"s3"或类似"s3","s7","s9"。仅使用Dim wsarray()wsarray() =不会改变行为。每当我使用wsarray()而没有Array(...)时,我都会收到'13' Type mismatch错误。

  1. 这是动态定义数组维度的问题 第一λ
  2. 如果没有,有没有办法将单元格值解析为数组?
  3. 如果没有,我将如何在VBA中动态构建数组列表?
  4. 其次,即使通过手动指定数组来绕过上述问题,我仍然会收到'450' Wrong number of arguments or invalid property assignment错误。我知道设置一个范围与多个非连续的单元格=另一个范围设置相同的方式工作正常(例如Range("K15:C18","C29") = Range("C1:C4","C15")),所以:

    1. 为什么该语法在For循环中不起作用?
    2. 第三,For循环中的语句需要完全限定的名称Worksheets("Home Backstage"),并且不接受别名Back

      1. 为什么For不接受工作表别名Back
      2. For循环是否在Dim之前设置,因此在循环中需要Dim
      3. 我知道我可以通过一堆If语句解决所有这些问题,并参考" Home"上的4个选项中的每个选项的状态。页面,以确定要复制到哪些工作表,但我不喜欢这个想法。这似乎不是解决这个问题的正确方法,有一堆重复的代码,对谓词有轻微的改变,因此我希望使用数组。不过,我的问题更多是为什么"而且"怎么",但我感谢任何指导或解释都一样!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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

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