web-dev-qa-db-ja.com

配列を範囲に書き込む。配列の最初の値のみを取得する

範囲に配列を書き込もうとしていますが、いくつかの方法を試しましたが、何があっても、常に配列の最初の値のみを何度も取得しています。

コードは次のとおりです。

Option Explicit

Sub test()

    ActiveWorkbook.Worksheets("Sheet1").Cells.Clear

    Dim arrayData() As Variant
    arrayData = Array("A", "B", "C", "D", "E")

    Dim rngTarget As Range
    Set rngTarget = ActiveWorkbook.Worksheets("Sheet1").Range("A1")

    'this doesn't work
    rngTarget.Resize(UBound(arrayData, 1), 1).Value = arrayData

    Dim rngTarget2 As Range
    Set rngTarget2 = ActiveWorkbook.Worksheets("Sheet1").Range(Cells(1, 5), Cells(UBound(arrayData, 1), 5))
    'this doesn't work either
    rngTarget2.Value = arrayData

End Sub

私が見ることを期待しているのは:

(Col A)     (Col E)
A           A
B           B
C           C
D           D
E           E

私が実際に見ているのは:

(Col A)     (Col E)
A           A
A           A
A           A
A           A
A           A

ここで何が間違っていますか?

[〜#〜] here [〜#〜] 見つかったように、Chip Pearsonの提案に従おうとしました。

しかし、運はありません...

さて、この問題の2番目の部分を追加します。

8,061個の要素を持つ1D配列があり、それを次の関数に渡します。

Call writeArrayData7(strTabName, arrayBucketData, 7)

Sub writeArrayData7(strSheetName As String, arrayData As Variant, intColToStart As Integer)

    Dim lngNextRow As Long
    lngNextRow = 1 ' hard-coded b/c in this instance we are just using row 1

    ' Select range for data
    Dim rngData As Range
    Set rngData = Sheets(strSheetName).Range(Cells(lngNextRow, intColToStart), Cells(lngNextRow - 1 + UBound(arrayData, 1), intColToStart))

    ' Save data to range
    Dim arrayDataTransposed As Variant
    arrayDataTransposed = Application.Transpose(arrayData)
    rngData = arrayDataTransposed

End Sub

したがって、これを実行すると、転置関数は適切に以下に変換されます。

Array(1 to 8061, 1 to 1)

範囲は、列Gに8,061個のセルがある単一の列のように見えます。

しかし、次のエラーが表示されます。

Run-time error '1004':
Application-defined or object-defined error

エラーは次の行にスローされます。

rngData = arrayDataTransposed

--- UPDATE ---

したがって、サンプルコードから除外したことの1つは(b/c正直に言って、それが重要だとは思わなかった)、配列の内容は実際には数式であるということです。実際のライブコードで使用している行は次のとおりです。

arrayData(i) = "=IFERROR(VLOOKUP($D" + CStr(i) + "," + strSheetName + "!$D:$F,3,FALSE),"")"

さて、(Excel Heroの助けを借りて)私が見つけたのは、上記のステートメントには文字列に必要な二重引用符が含まれていないため、代わりにこれに変更する必要があるということです。

arrayBucketData(i) = "=IFERROR(VLOOKUP($D" + CStr(i) + "," + strSheetName + "!$D:$F,3,FALSE),"""")"

それを深夜のボーンヘッドコーディングまでチョークできます。

しかし、私が学んだもう1つのことは、完全なコードを実行するために戻ったときに、配列を範囲に貼り付けるのにFOREVERがかかったことです。これは通常非常に単純なタスクであり、すぐに実行されるため、非常に混乱していました。

多くのデバッグを行った後、すべてのアラート/計算などをオフにしていて、これらの式に貼り付けたときにstrSheetNameシートがまだなかったという事実に問題があることがわかりましたb/cこのコードをメインファイルとは別に開発しています。どうやら、コードを貼り付けるとダイアログボックスが表示されますが、すべてのものをシャットオフすると、表示されませんが、本当にすべてが遅くなります。これらのタブが存在しない場合、範囲の貼り付けには約6分かかり、存在する場合は数秒かかります(おそらくそれよりも短い)。とにかく、コードをさらに改良するために、必要なシートをチェックする関数を追加し、それが存在しない場合は、タブをプレースホルダーとして追加して、プロセス全体がクロールに遅くならないようにします。

皆さん、助けてくれてありがとう!これが他の誰かに役立つことを願っています。

8
gotmike

これを行う:

arrayData = Array("A", "B", "C", "D", "E")

[a1].Resize(UBound(arrayData)) = Application.Transpose(arrayData)

重要なビットはTranspose()関数です。

ただし、2D配列をワークシートに書き込む予定がある場合は、最初から2D配列を使用することをお勧めします。最初のランクの行と2番目の列の列として定義する限り、転置は必要ありません。

23
Excel Hero

この:

Sub test()

    ActiveWorkbook.Worksheets("Sheet1").Cells.Clear

    Dim arrayData(1 To 5, 1 To 1) As Variant
    arrayData(1, 1) = "A"
    arrayData(2, 1) = "B"
    arrayData(3, 1) = "C"
    arrayData(4, 1) = "D"
    arrayData(5, 1) = "E"

    Dim rngTarget As Range
    Set rngTarget = ActiveWorkbook.Worksheets("Sheet1").Range("A1:A5")
    rngTarget = arrayData

End Sub

生成されます:

enter image description here

4
Gary's Student

受け入れられた答えを拡大することができるなら、私は提案します:

[a1].Resize(UBound(arrayData) - LBound(arrayData) + 1) = Application.Transpose(arrayData)

それが安全な方法です。これは、配列変数を次のように宣言しても機能します。

Dim arrayData(0 to 2) 

または

Dim arrayData(1 to 3) 

受け入れられた答えは、2番目の場合にのみ機能します。

提案された方法は、配列のサイズが不明で、arrayDataを次のように宣言する場合に便利です。

Dim arrayData()
0