Извлечь / разделить несколько диапазонов из метода Range.Area, когда он возвращает оригинальный объект Range вместо коллекции? - PullRequest
0 голосов
/ 31 января 2020

Я упустил очевидный сценарий случая, когда писал следующее, и надеюсь, что эксперты здесь смогут пролить свет на то, какой путь мне следует go пройти дальше, чтобы восстановить этот код ...

If Application.counta(wurgtbl.DataBodyRange.Columns(7)) > 0 Then 'checks if Note column contains any

    wurgtbl.DataBodyRange.AutoFilter Field:=7, Criteria1:="=*"  'uses autofilter to show only rows with a note

    Dim noterange As Range 'store note row addresses in range, each row (was supposed to) be treated as separate area
    Set noterange = wurgtbl.DataBodyRange.SpecialCells(xlCellTypeVisible)

    'oops, this only works if 100% discontinuous (multiple selection) ranges.  when any contiguous rows have a note,
    'their ranges are treated as a single selection which breaks my assumption of each row being a separate area!  
    'I had initially spaced my test notes out on different rows and it only broke when testing two contiguous notes

    'add range to array: since discontinuous range is certain, cant mainnotes = noterange.Value, must loop instead
    Dim mainnotes() As String
    ReDim mainnotes(0 To 6, 0 To noterange.Areas.Count - 1)
    Dim area As Range 'each group (area) will get its own row in array
    Dim acell As Range 'this will be each actual cell in the sub-groups
    Dim areaNum As Long

    areaNum = 0
    For Each area In noterange.Areas
        i = 0
        For Each acell In area
            mainnotes(i, areaNum) = acell.Value
            i = i + 1
        Next acell
        areaNum = areaNum + 1
    Next
End If

Из Документация Microsoft:

Для одного выбора свойство Areas возвращает коллекцию, которая содержит один объект - сам исходный объект Range. Для выбора нескольких областей свойство Areas возвращает коллекцию, содержащую один объект для каждой выбранной области.

В этом заключается проблема: я предположил, что свойство Areas всегда будет возвращать каждую строку в качестве Area object , но в ретроспективе имеет смысл присоединиться к областям по умолчанию, если они являются смежными диапазонами.

Общая цель - сохранить любые заметки, которые пользователь поместил в столбец, до обновления данных рабочей книги. После обновления он проходит по массиву и помещает заметки обратно в соответствующие записи. Ранее я использовал скрытые вспомогательные рабочие листы (для хранения), но вместо этого хотел использовать массивы для всех очевидных преимуществ. Мое первоначальное предположение только о несмежных рядах заметок было предположительно ужасным задним числом. В то время как рабочая книга будет иметь несмежные заметки, может также иметь их смежные, и , скорее всего, будет содержать оба, заставляя noterange возвращать комбинацию областей, где некоторые области отдельные строки, как я хочу, но другие области - это смежные строки, которые нужно как-то разделить, чтобы работать с моим дизайном.

Так можно ли взять непрерывный диапазон и затем разбить его на строки компонентов? Например, объект диапазона noterange.Address возвращает непрерывные данные:

$A$4:$G$6

Но я предполагал, что он вернется в виде коллекции (до прочтения документации для Range.Areas)

$A$4:$G$4,$A$5:$G$5,$A$6:$G$6

, содержащей N = 3 области. (просто в качестве примера, на практике N - это ~ 140K строк, которые могут содержать значение в столбце примечания.)

Для ясности, фактическая ошибка VBA возникает здесь mainnotes(i, areaNum) = acell.Value, потому что если Area содержит больше чем одна строка, то количество ячеек (или i) превышает границы определения массива. Все прекрасно работает, если нет смежных рядов, где он затем обрабатывает каждый ряд как отдельную область.

Надеясь на это, надеюсь, мое подсознание начнет решать это. Но я чувствую, что достиг предела своих знаний по этому вопросу, и был бы рад, если бы меня направили в правильном направлении!

1 Ответ

0 голосов
/ 31 января 2020

Огромный кредит BigBen за предоставление необходимых подсказок в его комментариях и представление меня .CountLarge в ответе, который он впоследствии удалил.

Я реализовал большинство его предложений (хотя столбец # все еще жестко запрограммирован):

  1. Измерение массива с использованием стандартной практики строк / столбцов вместо обратного.
  2. Измерение массива с использованием noterange.Cells.CountLarge / (# of columns) для получения фактического числа существующих строк, а не с использованием количества областей (поскольку некоторые области в этом сценарии будут содержать более одной строки).
  3. Повторяется через каждый Range.Area, затем через каждый Row в этом Range.Area, затем через каждый Cell в этом Row, присваивая Range.Value его позиции в массиве.

Вот окончательный код, который работает независимо от конфигурации примечаний в столбце примечаний:

'check if notes exist in note column
If Application.counta(wurgtbl.DataBodyRange.Columns(7)) > 0 Then 

    'use autofilter to show only rows with a note
    wurgtbl.DataBodyRange.AutoFilter Field:=7, Criteria1:="=*"  

    'store visible addresses in range
    Dim noterange As Range 
    Set noterange = wurgtbl.DataBodyRange.SpecialCells(xlCellTypeVisible)

    'add range to array: since discontinuous range is certain, cant mainnotes = noterange.Value, must loop instead
    Dim mainnotes() As String
    ReDim mainnotes(0 To noterange.Cells.CountLarge / 7 - 1, 0 To 6) 'Credit to BigBen on SO for this (rows/columns)

    Dim areaiterate As Long
    Dim rowNumb As Long
    Dim colNumb as Long
    Dim arow As Range
    Dim rcell As Range

    rowNumb = 0
    For areaiterate = 1 To noterange.Areas.Count
        For Each arow In noterange.Areas(areaiterate).Rows
            colNumb = 0
            For Each rcell In arow.Cells
                mainnotes(rowNumb, colNumb) = rcell.Value
                colNumb = colNumb + 1
            Next
            rowNumb = rowNumb + 1
        Next arow
    Next areaiterate
End If

Спасибо BigBen за предложения и фрагмент!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...