仅选择包含指定列的(合并)单元格

时间:2018-09-19 08:32:53

标签: excel vba range

因此,现在我正在开发VBA宏,它将只能选择满足指定条件的单元格。问题是我有多个级别单元格的嵌套列表。每个级别由合并的列的数量确定。因此,级别 0 ABCDE,级别 1 包含合并列BCDE,级别 2的单元格仅合并CDE,级别 3 DE和级别 4 E。请查看随附的图片,以获得更好的可视化效果enter image description here。问题是我不能只选择列,因为它会一次选择所有级别。

因此,假设我只选择 1级单元格(因此是从BCDE列合并的单元格)-如何在VBA中做到这一点?

谢谢

*) ABCD在原始帖子中(见评论)

2 个答案:

答案 0 :(得分:2)

此过程使您可以选择任何给定范围以及要选择的级别。它通过将给定范围内的列数作为“级别0”所需的列数来确定行的级别,并从中减去最后一列的合并范围内的列数。

enter image description here

为帮助说明其工作原理,我添加了一个可选变量以写出每一行的级别(在选定范围之后的两列)。默认情况下,该选项不显示级别。

还添加了T.M.检查oSelectRange的建议,以防止选择时崩溃。谢谢:)

Sub Test()
   Call GetRowLevel(Sheet1.Range("A1:E8"), 4, True)
End Sub

Private Sub GetRowLevel(ByVal SearchRange As Range, ByVal Level As Integer, Optional ShowLevel As Boolean = False)

    Dim oLevel0 As Integer      ' Number of columns in Level 0
    oLevel0 = SearchRange.Columns.Count

    Dim oRowCounter As Long
    Dim oSelectRange As Range
    Set oSelectRange = Nothing

    For oRowCounter = 1 To SearchRange.Rows.Count
        If oLevel0 - SearchRange.Cells(oRowCounter, SearchRange.Columns.Count).MergeArea.Columns.Count = Level Then

            If oSelectRange Is Nothing Then
                Set oSelectRange = SearchRange.Cells(oRowCounter, SearchRange.Columns.Count).MergeArea
            Else
                Set oSelectRange = Application.Union(oSelectRange, SearchRange.Cells(oRowCounter, SearchRange.Columns.Count).MergeArea)
            End If
        End If

        'Testing: Show Levels
        If ShowLevel Then
            Sheet1.Cells(oRowCounter, SearchRange.Columns.Count + 2).Value = oLevel0 - SearchRange.Cells(oRowCounter, SearchRange.Columns.Count).MergeArea.Columns.Count
        End If
    Next

    If Not oSelectRange Is Nothing Then oSelectRange.Select
End Sub

答案 1 :(得分:1)

选择定义的级别

  

” ...因此,级别0 ABCDE级别1 包含合并列BCDE级别2 仅合并CDE,级别 3 DE级别4 仅合并E。”

此方法使用LevelMergeCells属性选择给定MergeArea(如上定义的 )的所有项,以检查定义的合并单元格Level通过辅助功能bIsLevel()

应用的方法

基本上是

  1. 检查已定义范围内的每个单元格c *)是否属于合并的单元格范围(If c.MergeCells Then ...),
  2. 获取结果c.MergeArea.Address
  3. 通过辅助函数bIsLevel()根据所需的级别x地址检查找到的地址

在第一个循环条件下最近编辑的注释

*)由于MergeArea.Addresses仅显示第一个包含的范围(合并范围的顶部/左侧单元格),因此可以将搜索范围从例如.UsedRange到其中对应于Level + 1的列;因此,我将For Each c In Intersect(.UsedRange, .Columns(Level + 1))编辑为新的循环条件。

调用主过程SelectLevel

过程SelectLevel有两个可选参数:(1)OP定义的所需级别,(2)合格的工作表名称。可以通过以下示例语句来调用它(注意:,如果您未分配第一个参数,则 level 0是假设默认情况下,第二个参数默认为您选择的工作表名称,并且应更改为当前工作表名称)。

     SelectLevel 1     ' e.g. level 1 selects all merged cells of columns B:E

主要过程SelectLevel

Sub SelectLevel(Optional Level& = 0, Optional ByVal SheetName$ = "MySheet")
Dim c As Range, rng As Range, i&
With ThisWorkbook.Worksheets(SheetName)
    For Each c In Intersect(.UsedRange, .Columns(Level + 1))
        If c.MergeCells Then
           If c.Address = Left(c.MergeArea.Address, Len(c.Address)) Then
              If bIsLevel(c, Level) Then
                 If rng Is Nothing Then
                    Set rng = c
                 Else
                    Set rng = Application.Union(rng, c)
                 End If
              End If
           End If
        End If
    Next
End With
' Execute selection of wanted level
If Not rng Is Nothing Then
       rng.Select
Else
       MsgBox "Found no LEVEL" & Level & " items.", vbExclamation, "No Selection"
End If
End Sub

辅助功能bIsLevel()

Function bIsLevel(currCell As Range, ByVal lvl&) As Boolean
Dim LevelAddress$, CellAddress$
Dim arr(): arr = Array("A", "B", "C", "D", "E")
LevelAddress = arr(lvl) & ":" & arr(UBound(arr))    ' define Level columns due to OP
CellAddress = Split(currCell.MergeArea.Address, "$")(1) & ":" & _
              Split(currCell.MergeArea.Address, "$")(3)
bIsLevel = (LevelAddress = CellAddress)

'If bIsLevel Then Debug.Print "cell " & currCell.Address & " in currcell.MergeArea " & currCell.MergeArea.Address & _
                         " (" & CellAddress & " equ./LEVEL" & lvl & " " & LevelAddress & ")"

End Function