简体   繁体   中英

VBA Copy/paste static ranges to static ranges in dynamically built array of worksheets

I am trying to copy the cell values of 4 static ranges from one worksheet and paste those values into the cells within 4 static ranges for each worksheet that is included in my dynamically built list.

Here is my code:

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

First, wsarray = Array(Back.Cells(18, 19)) does not work as it is not parsing that cell value, it takes the whole thing as a single value (ie "s3","s5","s7","s9" or whatever the cell value is). Back.Cells(18, 19) has a formula that builds the list based on the 4 options selected on the "Home" page. The formula builds the list to be any of the 16 combinations of: s3, s5, s7, or s9. The final cell value looks like: "s3" or like "s3","s7","s9" . Using just Dim wsarray() or wsarray() = doesn't change the behavior. Any time I use wsarray() without Array(...) I get a '13' Type mismatch error.

  1. Is this a matter of dynamically defining the dimensions of the array first?
  2. If not, is there a way to parse the cell value into the array?
  3. If not, how would I build the array list dynamically in VBA?

Second, even bypassing the above issues by specifying the array manually, I still get a '450' Wrong number of arguments or invalid property assignment error. I know setting one range with multiple nonconsecutive cells = another range setup the same way works fine (eg Range("K15:C18","C29") = Range("C1:C4","C15") ), so:

  1. Why is that syntax not working within the For loop?

Third, the statement within the For loop needs the fully qualified name Worksheets("Home Backstage") and did not accept the alias Back .

  1. Why does the For not accept the worksheet alias Back ?
  2. Does the For loop act outside of the Dim 's that are setup prior to it thus needing the Dim within the loop?

I know I could get around all of this with a bunch of If statements and referencing the state of each of the 4 options on the "Home" page to determine which worksheets to copy to, but I don't like that idea. That doesn't seem to be the right way to go about this, having a bunch of duplicated code with slight changes to predicates hence my desire to use an array. Nevertheless, my questions are more "why" than "how", but I appreciate any guidance or explanations all the same!

You will need to enter the actual sheet names in the cell:

sheet9,sheet7

equating a string or variable with a variable name does not work, so you will need to loop through the array created by Split and make sure the sheet exists, then use it.

You cannot use range with more than two cell references. Range expects a start and a finish.

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

Here's another option, very similar to Scott's, but making use of a few more arrays to handle your ranges:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM