• ベストアンサー

VBAの配列の格納について

エクセルのVBAで、セルのデータを配列に格納するスピードを向上したいと思います。 例えば、A1~A10000のセルにデータを書き出す場合、 For 行番号 = 1 To 10000 Cells(行番号, 1).Value = 1 Next よりも、一旦、配列に書き込んだ後、一気にセルに書き込んだ方法が早いのですが、 For 行番号 = 1 To 10000 HAIRETU(行番号, 1) = 1 Next Range("A1:A10000").Value = HAIRETU() 今度は、A1~A10000に書き込んだデータを、再度、配列に格納する場合、 For 行番号 = 1 To 10000 HAIRETU(行番号, 1) = Cells(行番号, 1).Value Next とすると時間がかかるので、 HAIRETU() = Range("A1:A10000").Value というような処理をしたいのですが、うまくいきません。 よい方法がありましたら、ご教授ください。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんばんは。 ワークシートからデータが渡される場合は、明示的な配列変数に格納するなら、最初にVariant 型の配列変数の宣言をしないといけません。 例: Sub Test1 Dim HAIRETU() As Variant HAIRETU() = Range("A1:A10000").Value End Sub 通常は、以下のようになるのでしょうね。 Sub Test2 Dim HAIRETU As Variant HAIRETU = Range("A1", Range("A65536").End(xlUp)).Value '格納した大きさ MsgBox UBound(HAIRETU(), 1) & " X " & UBound(HAIRETU(), 2) End Sub でも、これは、一種の2次元配列ですから、当然、コードがややこしくなります。それは、ご承知の上で使われているものだと思います。 >Dim myData(10) >Set myData = Range("a1") 申し訳ないけれど、配列の宣言をして、オブジェクト変数は格納できないように思います。 オブジェクト変数を配列のようにするには、Collection にしないといけません。ただ、かなり重くなってしまいます。 添え字に関しては、以下のようになります。 Sub Test3 Dim HAIRETU() As Variant '配列変数の宣言 '一次限の添え字の上限確保 i = Range("A1", Range("A65536").End(xlUp)).Rows.Count ReDim HAIRETU(i, 1) '動的配列の再割り当て HAIRETU(i, 1) = Range("A1", Range("A65536").End(xlUp)).Value End Sub なお、二次元配列の場合は、Variant 型しか受け付けないはずです。したがって、メモリの消費量は多くなります。

QAZ123
質問者

お礼

詳しく説明してくださってありがとうございます。 オブジェクト変数など、知らない単語を理解するのに時間がかかり、お礼が遅くなりました。 どうもありがとうございました。

その他の回答 (4)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.5

#3>LONGでは無理なのでしょうか? ムリだと思います。 その他については、Wendy02 さんが解説して下さっているので略

QAZ123
質問者

お礼

回答、どうもありがとうございました。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

Dim HAIRETU As Variant Dim 行番号 HAIRETU = Range("A1:A10000") For 行番号 = 1 To 10000 Debug.Print HAIRETU(行番号, 1) Next

QAZ123
質問者

お礼

回答、どうもありがとうございました。

QAZ123
質問者

補足

ありがとうございます。動作できました。 Variant型を使うのは初めてなのですが、ReDim HAIRETU(1 To 10000, 1 To 2)のように、配列の次元を指定する必要はないのでしょうか? また、VariantをLONGに変えるとエラーになりますが、LONGでは無理なのでしょうか?

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.2

#01です。スペルミスです。 Dim myData(10) Set myData = Range("a1") ですね。なお後者の方を少し補足すると、mydata(2, 2)は Cells(2, 2)と同じ値を持ちます。

QAZ123
質問者

お礼

回答、どうもありがとうございました。

QAZ123
質問者

補足

Set myData = Range("a1")により、シート全体を配列に格納できることが理解できました。 Dim myData(10)の10の値は、どのような意味を持っているのでしょうか? 試しに、Sub macro4()のDim myDate(10)をDim myDate(1)に置き換えても、同じ実行結果になりました。

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.1

以下で試してみてください Sub macro4() Dim myDate(10) Set mydata = Range("a1") MsgBox ("1 " & mydata(1)) MsgBox ("2 " & mydata(2)) MsgBox ("3 " & mydata(3)) MsgBox ("4 " & mydata(4)) MsgBox ("5 " & mydata(5)) End Sub または Sub macro5() Dim myDate Set mydata = Range("a1") MsgBox ("1 " & mydata(1, 1)) MsgBox ("2 " & mydata(2, 1)) MsgBox ("3 " & mydata(3, 1)) MsgBox ("4 " & mydata(4, 1)) MsgBox ("5 " & mydata(5, 1)) End Sub

関連するQ&A

  • VBAで、配列のデータをセルに書き戻す方法について

    1000行200列の配列があり、配列の5列目と6列目のデータを、セルの10列目と11列目にすばやく書き戻す方法を教えてください。 (方法1) Dim DATA() As Long ReDim DATA(1 To 1000, 1 To 200) FOR 行番号= 1 TO 1000 CELLS(行番号,10).VALUE = DATA(行番号,5) CELLS(行番号,11).VALUE = DATA(行番号,6) NEXT (方法2) Dim DATA() As Long ReDim DATA(1 To 1000, 1 To 200) Dim WORK1() As Long ReDim WORK1(1 To 1000, 1 To 1) Dim WORK2() As Long ReDim WORK2(1 To 1000, 1 To 1) FOR 行番号= 1 TO 1000 WORK1(行番号,1) = DATA(行番号,5) WORK2(行番号,1) = DATA(行番号,6) NEXT RANGE("J1:J1000").VALUE = WORK1() RANGE("K1:K1000").VALUE = WORK2() (方法1)より(方法2)の方が早いのですが、WORKに貯めるのもめんどうなので、 RANGE("J1:K1000").VALUE = DATA(1,5), DATA(2,5), DATA(3,5),~,DATA(999,6),DATA(1000,6)のようなことができればと思います。 よろしくお願いします。

  • EXCEL VBAの配列でわかりません。

    こんなコードがあるのですが、最後の他のシート(作業中シート)に書き込もうとするとエラーになってしまいます。”Sheets("作業中").”を抜くと同じシートに結果は返ってくるのですが…。コードの内容は、ある範囲のある列から空白ではないセルを探し出してその行のデータを配列で汲み取り、他のシートに一括で洗い出すというものです。 Sub 作業中() Dim myRow As Long Dim Data As Variant Dim WC() As Variant Dim WCE() As Variant myRow = Range("H1").CurrentRegion.Rows.Count Data = Range("H1:M" & myRow).Value For i = 1 To myRow If Data(i, 5) <> "" Then a = a + 1 Else b = b + 1 End If Next ReDim WC(a) ReDim WCE(b) c = 0 d = 0 For i = 1 To myRow If Data(i, 5) <> "" Then WC(c) = Range("H" & i & ":K" & i).Value c = c + 1 Else WCE(d) = Range(Cells(i, 8), Cells(i, 11)).Value d = d + 1 End If Next For i = 0 To a Range(Cells(i + 1, 15), Cells(i + 1, 18)).Value = WC(i) Next For i = 0 To b Range(Cells(i + 1, 19), Cells(i + 1, 22)).Value = WCE(i) Next e = Range(Cells(1, 15), Cells(a, 18)).Value Sheets("作業中").Range(Cells(1, 1), Cells(a, 4)).Value = e End Sub ちなみに同じシートから↓のコードを実行するとうまくいきます。 なぜ~??わからな~い??おしえてくださーい!! Sub test() Dim a As Variant a = Range("H1:K4") Sheets("作業中").Range("N1:Q4") = a End Sub

  • セルに多次元配列の値を入力する方法

     Dim A as Variant A = Range(Cells(1,1),Cells(10,2)) としてセルのデータを配列変数に格納した場合  Range(Cells(1,2),Cells(10,2)) を  Range(Cells(1,3),Cells(10,3)) に入力するとき  Aを用いて一発で入力する方法はないですか?  今は For i = 1 to 10 cells(i,3) = A(i,2) Next  という方法しか思いつかないのですが時間がかかります。 良い方法があれば教えてください!

  • エクセルVBAで配列の追加

    エクセル2000です。 1行4列のセル範囲のデータを配列に取り込んで、後から別の1行4列のセル範囲のデータを配列に追加し、2次元配列として吐き出そうと思います。 最初の範囲がA1:D1、追加範囲がA4:D4とした場合、こんな不細工なコードになってしまいました。 これでも動きますが、どう修正すべきでしょうか? Sub test() Dim myAr() myAr = Application.Transpose(Range("A1:D1").Value) ReDim Preserve myAr(1 To 4, 1 To 2) For i = 1 To 4 myAr(i, 2) = Cells(4, i) Next i Range("F1").Resize(UBound(myAr, 2), UBound(myAr, 1)).Value = Application.Transpose(myAr) End Sub

  • 配列データのソートについて

    配列データのソートについて 配列データAAA(1000,10)があるとします。 このデータを5番目のデータにて降順にソートしたいと考えています。 現在、次の方法にて実施していますが、効率が悪いようなので、効率の良い方法を教えて下さい。 Sheets("荷捌場").Select Range(Cells(1, 1), Cells(1000, 10))="" For A=1 To 1000 For B=1 To 10 Cells(A,B)=AAA(A,B) Next B Next A Range(Cells(1, 1), Cells(1000, 10)).Select Selection.Sort Key1:=Range("E1"), Order1:=xlDescending For A=1 To 1000 For B=1 To 10 BBB(A,B)=Cells(A,B).Value Next B Next A Sheets("ソート後のデータ貼付場").Select For A=1 To 1000 For B=1 To 10 Cells(A,B)=BBB(A,B) Next B Next A

  • Excel.Rangeで取得した値を配列に格納するには?

    プログラミング初心者です。 VB.NET でExcelからデータを取得したのですが、配列等に格納したいのですが、うまくできなくて困っています。どなたか教えてください。 例)以下のデータを取得する場合 セルA(列)1(行)からA5まで セルB1からB5まで セルC1からC5まで Dim xl_APP As Excel.Application Dim xl_Book AS Excel.Workbook Dim xl_Sheet As Excel.Seets = xl_Book.Worksheets Dim xl_W_Sheet As Excel.Worksheet = CType(xl_W_Sheet.Item(1),Excel.Worksheet) 中略 Dim range_data As Excel.Range Dim i Integer Dim j Integer Dim strCel As String For i = 1 To 5 For j = 1 To 3 range_data = CType(xl_W_Sheet.Cells(i,j),Excel.Range) strCel = CStr(range_data.Value)  ↑String型変数に格納していますが、多次元配列?に格納して取り出せるようにしたいのですが、どうしたらよいのでしょうか? Next Nest <range_dataに格納されるデータ> A1:氏名 B1:学年 C:1 年齢 以下同上 ・・・・のように取り出したいと考えています。 よろしくお願いします。

  • VBA処理速度の向上(配列?)

    いつもお世話になっております。 エクセルVBA勉強中の初心者です。 書籍などを参考に、下記コードを作成し、セル内データを計算しています。 セル数が少ない場合には良かったのですが、将来的には、 約30,000行×100列程度になる予定で、処理に時間がかかってしまっています。 (現状で10,000行×50列程度、データは増えていきます。) 過去ログ、HPなどを調べると、配列に入れれば、処理速度が格段に上がると あったのですが、如何せん私には難しく、理解できませんでした・・・ 配列に限らず、処理速度が上がる方法をご教授、添削頂ければ助かります。 よろしくお願いいたします。 Sub test() Dim Gyo As Long, Retu As Long For Gyo = 3 To Range("A65536").End(xlUp).Row For Retu = 1 To Range("D3").End(xlToRight).Column Cells(Gyo, Retu).Value = Cells(Gyo, Retu).Value / 1000000 Next Retu Next Gyo End Sub

  • VBA 配列について

    配列の使い方について教えてください 1つの配列をどんどん追加したりしたいので1つの mybox で追加していきたいと思っています。 (下記コードが実現できればと思います。) (1)配列を広げ追加したい (2)繰返しを使わず一気に書き込みたい (3)一部をクリアしたりしたい のですがよろしくお願いします。 Sub Macro1() Range("A1").Value = "A" Range("A2").Value = "B" Range("A3").Value = "A" o = Range("A1").End(xlDown).Row mybox = Range(Cells(1, 1), Cells(o, 1)).Value 'myBox(1,1)=A 'myBox(2,1)=B 'myBox(3,1)=A ←このような表示になります。 '------------------------------------------------- '(1)配列を広げ追加したい ReDim Preserve mybox(o, 2) For i = 1 To UBound(mybox) If mybox(i, 1) = A Then mybox(i, 2) = 0 Else mybox(i, 2) = 1 End If Next i '------------------------------------------------- '(2)(1)をC列に「myBox(?,2)を「繰返しを使わず一気に」書き込みたい 'Transposeは限界(65536個)を超えるので使えません。 Range(Cells(1, 3), Cells(UBound(mybox), 3)) = mybox '(3)配列myBox(?,1)は残したままmyBox(?,2)はクリアにしたい End Sub

  • VBA 配列に格納した値の平均のやり方についてお教え願います

    いつもお世話になります。 配列に格納した値の平均のやり方についてお教え願います。 現在、実験測定データの移動平均(下記avg(x,1))を計算をしたいのですが、 配列に格納した値の平均が思うように計算できず困っております。 a =Range("A1:A20000")‘測定データを配列に格納 avg(x, 1) = Application.WorksheetFunction.average(a(x, 1), a(x + 5, 1)) という記述方法ではa(x, 1)とa(x + 5, 1)の2点の平均になってしまいます。 これをa(x, 1), a(x+1, 1),a(x+2, 1),a(x+3, 1) ,a(x+4, 1) ,a(x+5, 1)の5点の平均が計算できる記述方法はないでしょうか? ○実際の式は下のようなもので移動平均の平均区間yも変化します。 Dim avg(1 To 20000, 1 To 1) -前式省略- For y = 1 To 20000 -途中式省略- a =Range("A1:A20000")‘測定データを配列に格納 For x = 1 To 20000 avg(x, 1) = Application.WorksheetFunction.average(a(x, 1), a(x + y, 1)) ‘↑これでは2点の平均値になってしまいます。 Next -途中式省略- Next -後式省略- ○Range(“B1”)=AVERAGE(A1:OFFSET(A1,y-1,0)) Range(“B2”)=AVERAGE(A2:OFFSET(A2,y-1,0))  ・・・ というふうにセルに一つずつaverage関数を入力すれば移動平均も計算できるのですが、繰り返し回数が多いため、計算に非常に時間がかかります。そのため上記配列を利用したもので計算したいと思います。 ○ ネットでヒントを見つけたのですが↓ Set ran = Range(Range("A1"), Range("A1").End(xlDown)) Range("C4").Value = WorksheetFunction.average(ran) こう記述すればある範囲内の平均を求められるようですが、 Set ran= 以降の部分をRange(***)ではなく、 Set ran = (a(x, 1), a(x + y, 1)) ←a(x, 1)~a(x + y, 1)まで、というイメージですが・・・ というふうに範囲を配列で表すやり方を教えて頂けるだけでも結構です。 excel2003です。 以上、よろしくお教え願います。

  • エクセルVBAの配列について

    エクセルVBAの配列について VBAをはじめたばかりの初心者です。 現在、下記のようにデータを配列の中に入れ、 別シートに書き出そうとしております。 (配列へ読み込むところのみ) Dim 配列(1 To 件数, 1 To 9) As Variant For j =1 To 件数 For i = 2 To L If Cells(i, 2).Value = Tx_month Then For k = 3 To 11 配列(j, k - 2) = Cells(i, k).Value Next k End If Next j,i 現状では、データの最終行のみを「件数」分書き出してしまいます。 jとiのForが重なっているからだと思うのですが、どう書き直したら良いか分かりません。 質問をさせていただくのも初めてなので、分かりづらく恐縮ですが お力添え頂けますと幸いです。 どうぞ宜しくお願い致します。

専門家に質問してみよう