
今VBAの勉強中です。
VBAの高速化で二次元配列?というものがあるということで勉強しようと思っていますが、
良く理解出来ていません。
例えば、
下記はSheet1のB列の値が0以外であれば、その行をSheet2に順次コピーしていくというもので
自分なりに作成してみました。
これを二次元配列?で一気に処理する場合、どのようにすれば良いかご教授頂けないでしょうか。
p = 2
For i = 1 To 100000
If .Cells(i, "B").Value <> 0 Then
Sheets("Sheet1").Rows(i).Copy Sheets("Sheet2").Rows(p)
p = p + 1
End If
Next i
No.4ベストアンサー
- 回答日時:
No.2です、
お礼欄のコードを拝見すると、B列だけの操作でよいのですね。
ただ、今回の質問に関しては配列で処理するのは不向きのような気がします。
どうしても!というコトであれば・・・
前回のコードのmyRはループを高速にするために元データを単に配列にしただけなので
該当データを格納する箱(入れ物)を用意する必要があります。
(直接セルに表示する場合は該当データを格納する必要がないので、不要です)
最初に記載したように無理やりになりますが、やってみました。
B列の「0」以外のデータをC列に表示するとします。
Sub Sample2()
Dim i As Long
Dim lastRow As Long
Dim cnt As Long
Dim myR1, myR2
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
myR1 = Range(Cells(1, "B"), Cells(lastRow, "B"))
myR2 = Range(Cells(1, "C"), Cells(lastRow, "C")) '//←表示先の範囲をとりあえず決めておく(多めでも大丈夫)★//
For i = 1 To UBound(myR1, 1)
If myR1(i, 1) <> 0 Then
cnt = cnt + 1
myR2(cnt, 1) = myR1(i, 1)
End If
Next i
Range(Cells(1, "C"), Cells(cnt, "C")) = myR2 '//←C列に一気に吐き出す//
End Sub
※ 通常は上記のようなことはあまりやりませんが、無理やりやってみました。
まずはこの程度で・・・m(_ _)m
ありがとうございます。
配列の事少しずつ分かってきました。
変な例を挙げてしまい申し訳ございません。
ご教授頂いた内容を基に勉強していきます。
No.3
- 回答日時:
ご質問を拝見する限り、めぐみん_さんの方法が望ましく配列処理に適していない内容と思います。
>これを二次元配列?で一気に処理する場合、どのようにすれば良いかご教授頂けないでしょうか。
一気に処理する場合、不具合なく処理する事は出来ないと思います。(空白でない列が千行、B列の0が千程度ある想定)
私も詳しい訳でないので、教えられるレベルではありませんが、配列処理に向かない(するべきでない)処理もあると思います。
向いている機能を使うのもExcelVBAの使い方かとこの場合、、めぐみん_さんの代案処理
向かない理由としては、
~.Rows(1),~.Rows(lastRow) の様に
範囲として一度に配列に代入するのは問題があります。
Set でRangeとして代入でも、、、
また、
If .Cells(i, "B").Value <> 0 Then
Sheets("Sheet1").Rows(i).Copy Sheets("Sheet2").Rows(p)
にもあります。
行を忘れて、セルの範囲としても
条件.Cells(i, "B").Value <> 0 によってSheets("Sheet2")にSheets("Sheet1")の行がコピペされますが
0の時は、コピーされません。
値だけで良いなら、(xlPasteValues)配列で良いですが、.Rows(i).Copy Sheets("Sheet2").Rows(p)なので書式が含まれています。
従って、違う書式がある場合を想定して、その度に書式を設定またはコピペしなくてはなりません。
(すべて同じ書式なら最後に書式コピペでも良いですが)
その度にコピペするなら、配列で一度に書き出す最大のメリットをあまり生かせません。
条件設定が無いのであれば、範囲のコピペなのでそもそも配列もループもいりませんしね。
No.2
- 回答日時:
こんばんは!
簡単に解決したい場合はNo.1さんがおっしゃっているような方法が手っ取り早いと思いますが、
今回は「配列」に関しての質問が主だと思いますので・・・
お示しのコードはコピー&ペーストとなっていますが、
配列は高速で処理する場合によく使用しますが、あくまで「値」のみの操作になってしまいます。
すなわちコピー&ペーストではありません。
A1~A列最終行(仮に10万行目まで)のデータがあり、B1セル以降に1から連番を入れるとします。
単純にFor~Nextで1~100000までループさせると相当の時間を要してしまいます。
それを配列を使ってやると↓のようなコードで一瞬で可能です。
Sub Sample1()
Dim i As Long
Dim lastRow As Long
Dim myR '//←配列はValiant型で宣言(何も宣言していないので、Valiant型になる)//
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
myR = Range(Cells(1, "B"), Cells(lastRow, "B")) '//B1~最終行までを配列に格納(「Set」は付けない!)★①//
For i = 1 To UBound(myR, 1)
myR(i, 1) = i
Next i
'//▼セル上に一気に吐き出す//
Range(Cells(1, "B"), Cells(lastRow, "B")) = myR '//★②//
End Sub
上記コードの「★①」でをB1~B100000の範囲を配列に格納できます。
※ 本来はセル範囲ではなく、行数(列数)で配列とします。
配列内でループさせる方がセル範囲を「Set」し、セルを順にループさせるより格段に速く処理できます。
ただ、「★②」の処理をしないと単に配列にデータがあるだけで、
Sheet上には何も表示されないので、一気にSheetに吐き出します。
上記説明は1列だけの説明でしたが、複数列も配列にするコトが可能です。(二次配列)
というわけでセルのある範囲を行数・列数を指定することでその範囲内を高速にループさせることが可能だというコトになります。
※ 注意点として、極端に広い範囲(行数・列数)を配列にして、その中でループさせてしまうと
「メモリが不足しています」となりますので、ほどほどの行・列数を配列とした方がよいと思います。m(_ _)m
ご回答ありがとうございます。
ご丁寧なご説明により少しづつ分かってきました。また、値のみの操作という事
理解出来ました。
おそらくmyR(i, 1) = iの部分でmyRに値(i)を格納していき、それを最終行で一気に
吐き出すという事だと考えて、B列で0以外のみを格納して一気に吐き出すことを
試しにやってみたいと思い、下記のようにしてみましたが、
B列全ての値が吐き出されてしまいました。
私の思慮不足部分があると思いますが、根本間違っているでしょうか?
Sub Sample1()
Dim i As Long
Dim lastRow As Long
Dim myR
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
myR = Range(Cells(1, "B"), Cells(lastRow, "B"))
For i = 1 To UBound(myR, 1)
If Cells(i, "B").Value <> 0 Then
myR(i, 1) = Cells(i, "B").Value
End If
Next i
Sheets("Sheet2").Select
Range(Cells(1, "B"), Cells(lastRow, "B")) = myR
End Sub
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルで、絶対値の平均を算...
-
【VBA】配列に数式を仕込む方法...
-
ExcelのINDEXとMATCH関数でスピ...
-
array関数で格納した配列の型を...
-
Datatableへの代入
-
【VBA】ユーザーフォーム リス...
-
配列がとびとびである場合の書き方
-
エクセル2007 VBA シート内のデ...
-
スプレットシートのGetTextにつ...
-
INDEX(D:D,L3)の意味は?
-
エクセルVBAで変数をセルに一行...
-
【C#】二次元配列へのcsvファイ...
-
ノーツのデータをVBScriptで取...
-
[エクセル]連続する指定範囲か...
-
VBA 配列に格納した値の平均の...
-
VB.NETで DataRow()を利用して...
-
特定のセルが空白だったら、そ...
-
Excelで指定した日付から過去の...
-
連続する複数のセル値がすべて0...
-
VB.NETでコンボボックスの1行目...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで、絶対値の平均を算...
-
[エクセル]連続する指定範囲か...
-
表にフィルターをかけ、絞った...
-
ExcelのINDEXとMATCH関数でスピ...
-
array関数で格納した配列の型を...
-
Excelのセルの色指定をVBAから...
-
DataSetから、DataTableを取得...
-
Excel オートフィルタのリスト...
-
Datatableへの代入
-
【VBA】ユーザーフォーム リス...
-
配列がとびとびである場合の書き方
-
VBAでの100万行以上のデータの...
-
二次元配列の中の各行の要素を...
-
スプレットシートのGetTextにつ...
-
.NET - 配列変数を省略可能の引...
-
VB6.0 ファイルの一括読込み
-
【VBA】配列に数式を仕込む方法...
-
iniファイルのキーと値を取得す...
-
配列のSession格納、及び取得方...
-
Split関数でLong配列に格納する...
おすすめ情報