Выберите только (объединенные) ячейки, которые содержат указанные столбцы - PullRequest
0 голосов
/ 19 сентября 2018

Итак, сейчас я разрабатываю макрос VBA, который сможет выбирать только те ячейки, которые соответствуют указанным условиям.Проблема в том, что у меня есть вложенный список с несколькими ячейками уровня.Каждый уровень определяется количеством объединенных столбцов .То есть уровень 0 равен ABCDE, уровень 1 содержит ячейку, которая объединяет столбцы BCDE, уровень 2 объединяет только CDE, уровень 3 DE и уровень 4 составляет всего E.Пожалуйста, смотрите прикрепленное изображение для лучшей визуализации enter image description here.Проблема в том, что я не могу просто выбрать столбцы, так как он выберет все уровни сразу.

Итак, скажем, я хочу выбрать только level 1 клеток (поэтому ячейка, которая объединена из столбцов BCDE *) - как я могу это сделать в VBA?

Спасибо

*) ABCD в исходном сообщении (см. Комментарий)

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Эта процедура позволяет вам выбрать любой заданный диапазон и уровень, который вы хотите выбрать.Он определяет уровень строки, принимая количество столбцов в заданном диапазоне как количество столбцов, необходимое для «Уровня 0», и вычитает из него количество столбцов в диапазоне слияния последнего столбца.

enter image description here

Чтобы проиллюстрировать, как это работает, я добавил необязательную переменную для записи уровня каждой строки (два столбца после выбранного диапазона).По умолчанию опция не отображает уровни.

Предложение TM для проверки, что 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
0 голосов
/ 19 сентября 2018

Выберите определенные уровни

"... То есть уровень 0 равен ABCDE, уровень 1 содержит ячейку, которая объединяет столбцы BCDE, уровень 2 объединяет только CDE, уровень 3 DE и уровень 4 только E."

Этот подход выбирает все элементы данного Level (, как определено выше ), используя свойства MergeCells и MergeArea для проверки объединенных ячеекв определенном Level через вспомогательную функцию bIsLevel().

Прикладной метод

В основном это

  1. проверяет каждую ячейку cв определенном диапазоне *) принадлежит ли он к диапазону объединенных ячеек (If c.MergeCells Then ...),
  2. получает результирующие c.MergeArea.Address,
  3. проверки найденных адресов по требуемому адресу уровня x через помощникафункция bIsLevel()

Примечание к последнему редактированию в 1-м цикле

*) Поскольку MergeArea.Addresses показывает только первый включенный диапазон (верхняя / левая ячейка)в диапазоне слияния), можно тo сузить диапазон поиска, например, .UsedRange до столбца в нем, соответствующего Level + 1;поэтому вместо этого я отредактировал For Each c In Intersect(.UsedRange, .Columns(Level + 1)) как новое условие цикла.

Вызов основной процедуры SelectLevel

Процедура SelectLevel имеет два необязательных параметра: (1)Разыскиваемый уровень, определенный OP, (2) квалифицированное имя рабочего листа.Он может быть вызван следующим примером оператора ( Примечание: , если вы не назначите 1-й аргумент , level 0 предполагается по умолчанию, 2-й аргумент по умолчанию имя листа по вашему выбору и должно быть заменено на ваше текущее имя листа).

     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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...