Using VBA to create a single range from multiple ranges

依然范特西╮ 提交于 2021-01-28 11:41:34

问题


Hello this is my first post as I've always been able to find my answers in previous posts... until now. There must be a post, but I couldn't find one addressing the issue I'm having. My skill level is intermediate at best :-)

I have some values in a tabular format. I want to create a range from that which excludes some rows. I felt like I was getting close with a union, but alas, no go. The code example is below. The result was a new range containing only the value of Rng1. Any suggestions would be greatly appreciated. Please let me know if I should provide anything else. Thank You!

Sub TestUnion()

    Dim Rng1 As Range, Rng2 As Range, NewRng As Range, OutputRng As Range
    
    Set Rng1 = Range("A1:D1")
    Set Rng2 = Range("A3:D5")
    Set NewRng = Union(Rng1, Rng2)
    Set OutputRng = Range("F1:I4")
    
    OutputRng.Value2 = NewRng.Value2

End Sub

回答1:


This code should do the job. Please try it.

Sub TestUnion()

    ' list source ranges comma-separated
    Const Sources   As String = "A1:D1,C5,A3:D5"
    Const Target    As String = "F1"

    Dim Src()       As String               ' converted from Sources
    Dim Data        As Variant              ' value of Src(i)
    Dim i           As Long                 ' index of Src()
    Dim Ct          As Long                 ' target column
    Dim Rt          As Long                 ' target row
    
    Src = Split(Sources, ",")
    Rt = Range(Target).Row
    Ct = Range(Target).Column
    
    For i = 0 To UBound(Src)
        Data = Range(Src(i)).Value
        If InStr(Src(i), ":") Then
            Cells(Rt, Ct).Resize(UBound(Data), UBound(Data, 2)).Value = Data
            Rt = Rt + UBound(Data)
        Else
            Cells(Rt, Ct).Value = Data
            Rt = Rt + 1
        End If
    Next i
End Sub

Just set the two constants at the top of the procedure and the code will do the rest. This arrangement isn't strictly necessary but to set it up takes very little time which will be save tenfold if you ever need to make a change.




回答2:


Get Multi Range

Option Explicit

Sub TESTgetMultiRange()
    On Error GoTo clearError
    Const dFirst As String = "F1"
    ' Define ranges.
    Dim Rng1 As Range: Set Rng1 = Range("A1:D1")
    Dim Rng2 As Range: Set Rng2 = Range("A3:D5")
    ' Define Source range (the union of all ranges).
    Dim sRng As Range: Set sRng = Union(Rng1, Rng2)
    'Debug.Print sRng.Address
    ' Write values from Source range to an array.
    Dim Data As Variant: Data = getMultiRange(sRng)
    ' Define Destination range.
    Dim dRng As Range
    Set dRng = Range(dFirst).Resize(UBound(Data, 1), UBound(Data, 2))
    'Debug.Print dRng.Address
    ' Write values from the array to the Destination range.
    dRng.Value = Data
    MsgBox "Copied range '" & sRng.Address(0, 0) & "' to range '" _
        & dRng.Address(0, 0) & "'.", vbInformation, "Success"
ProcExit:
    Exit Sub
clearError:
    Resume ProcExit
End Sub

Function getMultiRange(rng As Range) As Variant
    On Error GoTo clearError
    Dim aCount As Long: aCount = rng.Areas.Count
    Dim Data As Variant: ReDim Data(1 To aCount)
    Dim DataRows As Variant: ReDim DataRows(1 To aCount)
    Dim DataCols As Variant: ReDim DataCols(1 To aCount)
    Dim aRng As Range
    Dim n As Long
    For Each aRng In rng.Areas
        n = n + 1
        Data(n) = getRange(aRng)
        DataRows(n) = UBound(Data(n), 1)
        DataCols(n) = UBound(Data(n), 2)
    Next
    Dim Result As Variant
    ReDim Result(1 To Application.Sum(DataRows), 1 To Application.Max(DataCols))
    Dim i As Long, j As Long, k As Long
    For n = 1 To aCount
        For i = 1 To DataRows(n)
            k = k + 1
            For j = 1 To DataCols(n)
                Result(k, j) = Data(n)(i, j)
            Next j
        Next i
    Next n
    getMultiRange = Result
ProcExit:
    Exit Function
clearError:
    Resume ProcExit
End Function

Function getRange(rng As Range) As Variant
    On Error GoTo clearError
    Dim Data As Variant
    If rng.Rows.Count > 1 Or rng.Columns.Count > 1 Then
        Data = rng.Value
    Else
        ReDim Data(1 To 1, 1 To 1)
        Data(1, 1) = rng.Value
    End If
    getRange = Data
ProcExit:
    Exit Function
clearError:
    Resume ProcExit
End Function


来源:https://stackoverflow.com/questions/65227228/using-vba-to-create-a-single-range-from-multiple-ranges

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!