Подтвердить что ты не робот

Excel VBA: диапазон до строкового массива в 1 шаг

Я знаю, что вы можете легко взять ряд ячеек и пощекотать их в Variant Array, но я хочу работать со строковым массивом (потому что он одномерный и занимает меньше памяти, чем массив Variant).

Есть ли способ автоматического преобразования диапазона в массив строк?

В настоящее время я использую функцию, которая будет принимать диапазон и сохранять значения в альтернативном массиве, а затем преобразовать массив вариантов в массив строк. Он работает хорошо, но я ищу способ перейти непосредственно из диапазона в строковый массив. Любая помощь будет принята с благодарностью.

Function RangeToArray(ByVal my_range As Range) As String()

Dim vArray As Variant
Dim sArray() As String
Dim i As Long

vArray = my_range.Value
ReDim sArray(1 To UBound(vArray))

For i = 1 To UBound(vArray)
    sArray(i) = vArray(i, 1)
Next

RangeToArray = sArray()

End Function 

UPDATE: Похоже, что нет способа пропустить шаг метаданных в переменный массив, прежде чем преобразовать его в одномерный массив строк. Позор, если это правда (даже если это не требует больших усилий, мне нравится ультра-оптимизировать, поэтому я надеялся, что есть способ пропустить этот шаг). Я закрою вопрос через несколько дней, если решение не представится. Спасибо за полезные комментарии, ребята!

UPDATE2: Ответ идет к Симону, который прилагал большие усилия (так же сделал и все остальные), и предельно указал на то, что действительно невозможно перейти от диапазона к массиву строк за один выстрел. Спасибо, всем.

4b9b3361

Ответ 1

Как насчет...

Public Function RangeToStringArray(theRange As Excel.Range) As String()

    ' Get values into a variant array
    Dim variantValues As Variant
    variantValues = theRange.Value

    ' Set up a string array for them
    Dim stringValues() As String
    ReDim stringValues(1 To UBound(variantValues, 1), 1 To UBound(variantValues, 2))

    ' Put them in there!
    Dim columnCounter As Long, rowCounter As Long
    For rowCounter = UBound(variantValues, 1) To 1 Step -1
       For columnCounter = UBound(variantValues, 2) To 1 Step -1
           stringValues(rowCounter, columnCounter) = CStr(variantValues(rowCounter, columnCounter))
       Next columnCounter
    Next rowCounter

    ' Return the string array
    RangeToStringArray = stringValues

End Function

Ответ 2

Фактически вы можете перейти непосредственно из диапазона в массив, используя функции Split, Join и разделитель, не содержащийся в тексте.

Предполагая, что вы уже присвоили 1D диапазон значений как SrcRange

Dim Array() As String: Array = Split(Join(Application.Transpose(SrcRange), "#"), "#")

Ответ 3

Function RangeToStringArray(myRange as range) as String()

    ReDim strArray(myRange.Cells.Count - 1) As String
    Dim idx As Long
    Dim c As Range
    For Each c In myRange
        Set strArray(idx) = c.Text
        idx = idx + 1
    Next c

    RangeToStringArray = strArray
End sub

Ответ 4

Если вы не возражаете изменить содержимое буфера обмена, выполните следующие действия:

  • КОПИРОВАТЬ диапазон в буфер обмена с помощью метода Копировать:

    MyTargetRange.Copy
    
  • Скопируйте содержимое из буфера обмена в строковую переменную (выполните поиск на этом сайте или в другом месте для функций для передачи строк в/из буфера обмена).

  • SPLIT строку в массив вариантов:

    MyStringArray = Split(MyClipboardText, vbCrLf)
    
  • ДОПОЛНИТЕЛЬНО: массив будет иметь один дополнительный пустой элемент, потому что в конце текста, который вы только что скопировали в буфер обмена, всегда есть дополнительный Return (vbCrLf). Для удаления просто измените размер массива:

    Redim Preserve MyStringArray(Ubound(MyStringArray) - 1)
    

Очень просто и быстро!!!

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

Это было бы ЧРЕЗВЫЧАЙНО ПОМОЩЬ, если вы работаете с множеством повторяющихся функций (тысяч), которые используют одни и те же данные (тысячи точек данных). При первом вызове функции выполняйте все промежуточные вычисления в диапазонах данных, которые вам нужны, но сохраните результаты в статических переменных. Также сохраните строчную копию ваших диапазонов ввода через буфер обмена. С каждым последующим вызовом вашей функции преобразуйте диапазоны ввода в текст, снова через буфер обмена и сравните с сохраненной копией. Если они одинаковы, вы можете обойти все предварительные расчеты.

Ответ 5

Именованные диапазоны, используемые в VBA, уже являются массивами. Поэтому сначала сделайте диапазон в именованный диапазон, затем обратитесь к нему и удалите именованный диапазон. Например:

ThisWorkbook.Names.Add Name:="test_array", RefersTo:=Sheet1.Range("A4:B10")
a = Sheet1.Range("test_array")
ThisWorkbook.Names("test_array").Delete