
今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で質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 改行ごとに行を追加し、数量を分割 4 2023/07/11 16:39
- Excel(エクセル) マクロで最終行から上に検索を逆にしたい 1 2022/05/17 18:27
- Excel(エクセル) VBAの指示の内容 昨日こちらでご教示頂いたのですが初心者な為、一つ一つの指示が何をやっているのかわ 2 2022/10/25 18:08
- Visual Basic(VBA) VBAで実行時エラー'424' オブジェクトが必要ですと出る 2 2022/10/07 09:25
- Excel(エクセル) なぜExit Subがあるのかわかりません 4 2023/02/19 12:34
- Visual Basic(VBA) 列と行の名前(重複あり)が交差するセルに、データを入力したい 2 2022/06/25 22:42
- Visual Basic(VBA) VBA処理追加 こちらでご教示頂いたのですが回答完了させてしまいましたのでこちらからまた質問させてく 2 2022/10/27 09:57
- Visual Basic(VBA) excel VBA if文について 3 2022/03/27 17:42
- Visual Basic(VBA) vba 重複データ合算 5 2023/07/05 18:55
- Visual Basic(VBA) 【VBA】For文を使用し、行をコピーして別シートに貼り付ける方法を教えてください。 4 2022/07/19 09:01
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
[エクセル]連続する指定範囲か...
-
エクセルで、絶対値の平均を算...
-
ExcelのINDEXとMATCH関数でスピ...
-
表にフィルターをかけ、絞った...
-
ノーツのデータをVBScriptで取...
-
Excel オートフィルタのリスト...
-
VBAで指定期間の範囲を抽出し、...
-
配列がとびとびである場合の書き方
-
Excel数式
-
VBAの二次元配列?
-
【VBA】ユーザーフォーム リス...
-
VBA listBoxについて
-
配列のSession格納、及び取得方...
-
指定数字の抽出方法
-
DataSetから、DataTableを取得...
-
array関数で格納した配列の型を...
-
SUMPRODUCT関数を用いた最小値
-
Excel2000で
-
2次元配列への格納方法について
-
.NET - 配列変数を省略可能の引...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで、絶対値の平均を算...
-
[エクセル]連続する指定範囲か...
-
表にフィルターをかけ、絞った...
-
ExcelのINDEXとMATCH関数でスピ...
-
Excelのセルの色指定をVBAから...
-
Excel オートフィルタのリスト...
-
DataSetから、DataTableを取得...
-
array関数で格納した配列の型を...
-
読み込みで一行おきに配列に格納
-
.NET - 配列変数を省略可能の引...
-
【VBA】ユーザーフォーム リス...
-
配列がとびとびである場合の書き方
-
SUMPRODUCT関数を用いた最小値
-
iniファイルのキーと値を取得す...
-
VBAでの100万行以上のデータの...
-
エクセルでエラーを無視して一...
-
配列のSession格納、及び取得方...
-
VBA 配列に格納した値の平均の...
-
VB6.0 ファイルの一括読込み
-
Datatableへの代入
おすすめ情報