Excel VBA: диапазон до строкового массива за 1 шаг - PullRequest
20 голосов
/ 21 июля 2011

Я знаю, что вы можете легко взять диапазон ячеек и поместить их в массив Variant, но я хочу работать со строковым массивом (потому что он одномерный и занимает меньше памяти, чем массив 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 

ОБНОВЛЕНИЕ: похоже, что нет способа пропустить шаг выброса данных в массив переменных перед преобразованием их в одномерный строковый массив.Обидно, если это правда (даже если это не требует больших усилий, мне нравится ультраоптимизация, поэтому я надеялся, что есть способ пропустить этот шаг).Я закрою вопрос через несколько дней, если решение не появится.Спасибо за полезные комментарии, ребята!

ОБНОВЛЕНИЕ 2: Ответ идет Саймону, который приложил большие усилия (как и все остальные) и совершенно точно указал, что действительно невозможно перейти от диапазона к строковому массиву за один выстрел.Спасибо всем.

Ответы [ 5 ]

10 голосов
/ 21 июля 2011

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

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
5 голосов
/ 17 мая 2017

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

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

Dim Array() As String: Array = Split(Join(Application.Transpose(SrcRange), "#"), "#")
2 голосов
/ 29 октября 2013
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
        strArray(idx) = c.Text
        idx = idx + 1
    Next c

    RangeToStringArray = strArray
End Function
1 голос
/ 08 декабря 2015

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

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

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

  3. РАЗДЕЛИТЕ строку вВариант массива:

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

    Redim Preserve MyStringArray(Ubound(MyStringArray) - 1)
    

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

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

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

0 голосов
/ 24 августа 2017

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

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