web-dev-qa-db-ja.com

Excel VBA:1ステップで文字列配列に範囲

ある範囲のセルを簡単に取得してVariant配列に入れることができることは知っていますが、文字列配列を操作したいです(1次元であり、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 

更新:データを1次元の文字列配列に変換する前に、最初に変数配列にデータをスローするステップをスキップする方法がないようです。もしそれが本当なら恥ずかしい(たとえそれがそれほど努力しなくても、私はその最適化を好むので、そのステップをスキップする方法があることを望んでいた)。解決策が提示されない場合は、数日で質問を終了します。有益なコメントをありがとう、みんな!

UPDATE2:回答は多大な努力を払ったSimonに行き(他の皆もそうでした)、最終的に範囲内から文字列配列に一発で移動することは実際に不可能であると指摘しました。みんな、ありがとう。

21
aevanko

どうですか...

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
10
Simon Cowen

実際には、関数Split、Join、およびテキストにない区切り文字を使用して、範囲から配列に直接移動できます。

既に1Dの値の範囲をSrcRangeとして割り当てていると仮定します

Dim Array() As String: Array = Split(Join(Application.Transpose(SrcRange), "#"), "#")
6
Tragamor
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
2
J.A. Daling

クリップボードの内容を変更してもかまわない場合:

  1. Copyメソッドを使用して範囲をクリップボードにコピーします。

    MyTargetRange.Copy
    
  2. クリップボードからコンテンツを文字列変数にコピーします(このサイトまたは他の場所で、クリップボードとの間で文字列を転送する関数を検索します)。

  3. 文字列をバリアント配列に分割します。

    MyStringArray = Split(MyClipboardText, vbCrLf)
    
  4. オプション:クリップボードにコピーしたばかりのテキストの最後に常に追加のReturn(vbCrLf)があるため、配列には1つの追加の空白要素があります。削除するには、単に配列のサイズを変更します。

    Redim Preserve MyStringArray(Ubound(MyStringArray) - 1)
    

非常にシンプルで速い!!!

欠点は、(再計算中に)予想以上にクリップボードが変更される可能性があり、文字列の配列のみを生成する(Doubleやその他の数値型ではない)ことです。

同じデータ(数千のデータポイント)を使用する多数の反復関数(数千)を使用している場合、これは非常に役立ちます。関数が初めて呼び出されたときに、必要なデータの範囲ですべての中間計算を行いますが、結果は静的変数に保存します。また、クリップボードを介して入力範囲の文字列コピーを保存します。関数への後続の呼び出しごとに、入力範囲をクリップボードに再度テキストに変換し、保存されたコピーと比較します。それらが同じ場合、予備計算の多くをバイパスできる可能性があります。

1
Shawn Pauliszyn

VBAで使用される名前付き範囲は既に配列です。そのため、まず範囲を名前付き範囲にしてから、それを参照して名前付き範囲を削除します。例えば:

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