• 締切済み

EXCEL VBA 配列のIndex番号書きかわり

ap_2の回答

  • ap_2
  • ベストアンサー率64% (70/109)
回答No.5

>この (1 to 5) を再び (0 to 4) へ復活 残念ながら、VBAは配列操作がしょぼいのでForループするしか。 なるべく、セルと直結した配列は(1 to n)で統一したいです。 ◆処理速度@Forループに向けて 配列はアクセスが早いから誤差!…らしいよ。試した↓  '処理1: 10000×100のセル範囲取得@セルには英字100字  a1 = Range("A1:CV10000")  '-> 約1500ms  '処理2: Forループで配列複製  a2(r, c) = a1(r + 1, c + 1)   '-> 約450ms 450ms!30%増?思ったよりかかったΣ(゜□゜;) …けど、ちょっと処理を変えるだけで大きく変わるんです。  処理1' 1×100のセル取得、を10000回 -> 250ms  処理2' 1×100の配列複製、を10000回 -> 100ms …なんででしょうね(苦笑) これなら、高速化は、他の処理を見直した方が大きいかも。 特に、後者(2')の使い方なら、100msは許容範囲では? お試しあれ ◆補足説明 ◇配列について A = Rangeでは、以下と同じことが起きてます。  ReDim a1(0 to 10): ReDim a2(1 to 20)  a1 = a2 'a1はa2の複製、つまり(1 to 20)になる ちなみに、Array関数などは必ず(0 to n)の配列を返します。 "Option Base 1"なんて設定しても、ソレは変わりません。 セル絡みは1から、他は0からで慣れてクダサイ。 ◇Rangeについて Rangeはオブジェクトなので、仕様ですね。 ・Range.Valueの返却値は、範囲の場合、(1 to n)の配列です。 ・Range.Valueへの代入は、範囲の場合…こんな感じ↓   ReDim A(101 to 103)   Range("A1:C1") = A 'A1セルにはA(101)が入る

SURAGOTAPI
質問者

お礼

みなさま、ご回答ありがとうございました。 プログラム制作の最初の段階で、配列範囲を0から始める構造にしてしまったため、なんとかIndexの設定を維持したかったのですが、 仕様ならしょうがありませんでした…。 打開策として、大きな範囲を配列に一変に格納したあと、別の配列にFor文で、データを一個一個、再配置してみました。 シートとのやり取りではなく、配列同士のやり取りなので、そんなに時間がかからないことがわかりました。 ありがとうございました。

関連するQ&A

  • 配列変数 インデックス番号の最小値

     特に指定しない場合、配列変数のインデックス番号の最小値は0から始まるはずですが、下記のプロシージャでは、abの最小インデックス番号は1,2次元とも「0」でなく「1」から始まります(ウォッチ式で見ても「1」から始まっています)。 「0」から始まらない理由が分かりません。 ご教授を よろしくお願いいたします。 Public Sub セル参照() ' "A1:B10"のセル範囲のデータを順番にメッセージボックスに表示する。 Dim ab As Variant Dim i As Integer, j As Integer ab = Worksheets("Sheet1").Range("A1:B10").Value For i = 1 To UBound(ab, 1) For j = 1 To UBound(ab, 2) MsgBox ab(i, j) Next j Next i End Sub

  • 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

  • 【VBA】配列の部分コピー

    VBAにて、配列の範囲を指定して別の配列にコピーしたいと思っています。 現在は以下のようにFor文を使用して1つ1つ代入しているのですが、 もっと効率の良い方法はありますか? 処理速度を重視しています。 Dim srcArray As Variant: srcArray = Range("A1:A100") ' コピー元の配列 Dim dstArray As Variant ' コピー先の配列 Dim startIndex As Integer ' コピーする範囲の開始インデックス Dim endIndex As Integer ' コピーする範囲の終了インデックス startIndex = 6 endIndex = 16 ReDim dstArray(endIndex - startIndex) For si = startIndex To endIndex   dstArray(si - startIndex) = srcArray(si, 1) Next si

  • エクセル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

  • エクセルVBAで配列?

    以下は、文字列"t", "e", "s", "t"を配列に取り込み、セルに表示する例ですが、 ar = Array("t", "e", "s", "t") なら作動しますが、セル範囲から取り込もうと、 ar = Range("A1:D1").Value とするとエラーになります。 どうしてでしょうか? Sub test() Dim ar As Variant Dim n As Integer ar = Array("t", "e", "s", "t") 'ar = Range("A1:D1").Value For n = LBound(ar) To UBound(ar) Cells(n + 1, 5) = ar(n) Next n End Sub

  • Excel 2010 VBAで教えてください。

    Excel 2010 VBAで教えてください。 Doubleの配列 Dim A(100) as double に ワークシート "Sheet1" セル A1:A100 の値を一発(For loop等を利用しない) で読み込むにはどうすればよいのでしょうか。 同じく、 Doubleの配列 A(100)を ワークシート "Sheet2" セル B1:B100 に一発で書き出すのはどうすればよいのでしょうか。  Variantにて Dim A as Variant では  A = Sheets("Sheet1").Range("A1:A100") で 読み込めました。 また Sheets("Sheet2").Range("B1:B100")で書き込みできましたが、double等でどうすれば良いのか知りたいです。

  • VBA なぜ配列にドカンと一発で入れることが出来る

    下に2つのコードを示していますが、パターン1は、配列cに一発で一気に速く入れることが出来る雰囲気が表れています。実際に速いそうです。 しかしながら、どちらのコードも、最終的には配列cに一つずつデータが入るわけですよね。 なぜ、パターン1だと速いのでしょうか? 専門的でむずかしいようでしたら、イメージだけでも教えていただけたらと思います。 パターン1 Dim r as Range Dim c() As Variant Set r=Selection c = r.Value パターン2 redim c(r.rows.count,r.columns.count) for i=1 to r.rows.count for j=1 to r.columns.count c(i,j)=r(i,j).value next j next i

  • linest関数に配列を渡す

    こんばんは。 回帰分析をやってくれるワークシート関数にLinestとうのがありますが、 それの引数に、配列を渡したいのですが、うまくいきません。 データ自体はRangeではなく、Variant型の配列となっているのですが、Linestを 使うときは、一旦、シートに貼り付けて、配列→Range型に変換するなどするしか 対応できませんでしょうか。 もしくは、Linestと同等な自作関数を作っても良いのですが、もともと機能として あるなら、Linestを使用したいと思ってます。 うまくいかない例^^; Sub test() Dim a(1 To 3) as Variant Dim b(1 To 3, 1 To 2) as Variant a(1) = 1 a(2) = 3 a(3) = 2 b(1, 1) = 4 b(2, 1) = 5 b(3, 1) = 6 b(1, 2) = 12 b(2, 2) = 15 b(3, 2) = 19 MsgBox WorksheetFunction.LinEst(a, b, True, True) End Sub -- エクセル2003

  • VBA:日付を配列に入れ別セルに転記するとデータ型が変わる

    データを別シートに転記するVBAコードを書いていて気付きました。 日付データをバリアント型の配列に入れて、再度書き出すと 21/2/2005 のように表示され、さらに日付ではなく、文字列になってしまいました。 具体的には下記のような内容です。Sheet1 の A1:A10 に 2005/2/21 のような日付が入力されています。 1. セル範囲のデータをバリアント型の配列に格納 2. 1.を別のセルへ一括転記を行う Sub TestMacro()   Dim Buf As Variant   With Sheets("Sheet1").Range("A1:A10")     Buf = .Value     '・・・(1)     .Offset(0, 3) = Buf  '・・・(2)   End With End Sub ウォッチ式で変数を確認すると(1)および(2)の時点では #05/02/21# Variant/Date型 と正しく日付として扱われているようです。しかし、転記されたセルを見てみると、「文字列で 21/2/2005 」となっているのです。 2005/2/21 が返されるものと思うのですが、なぜ、このような現象が起こるのでしょうか?何かとんでもない勘違いをしているのでしょうか? テスト環境は Win98SE + EXCEL2002 です。よろしくお願いします。

  • 【VBA】配列を使ったマクロで高速化

    いつもお世話になっております。 現在大量にセルの内容を参照し、照らし合わせるマクロを作っていますが、内容が膨大でマクロでも 時間がかかるので、何とか高速化できないか、考えております。 そこで、セルを直接参照するより、配列を使った方が速くなるという話を聞いたのですが、 配列を使うときに普通はVariantで宣言をして、セルの値のみ格納すると思います。 例えば、次のように、A列とB列を10000個のセルを1個ずつ比較し、一致した時にある作業をさせて C列に出力するとします。 A = Range("A1:A10000") B = Range("B1:B10000") For i = 1 To 10000 For j = 1 To 10000 If A(i, 1) = B(j, 1) Then A(i, 1) = A(i, 1) + 1 End If Next Next Range("C1:C10000") = A このようなマクロならいいのですが、値が一致した時にそのセルの色を変えるだとか削除するだとか行うと、次のようになり、配列のみでの構成ができなくなってしまいます A = Range("A1:A10000") B = Range("B1:B10000") For i = 1 To 10000 For j = 1 To 10000 If A(i, 1) = B(j, 1) Then Cells(i, 1).Interior.ColorIndex = 3 End If Next Next 前者は15秒、後者は19秒かかりました。上のプログラムは例であり、 実際に実務の方でマクロを実行すると数十分かかってしまいます。 何とか、条件によってセルの色変えたり削除するときに、速度を低下させずに配列のみで構成することは不可能でしょうか?