![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
こんにちは、配列がいくつまで取得できるのか計算するマクロを作っている時に変なことに気が付きました。
エクセルでフォームとラベルを1つ用意し、下記のようなプログラムをモジュールに書きます。
実行すると、10万ずつ数字が増えていき、数字が1000~2000万超えたあたりで、メモリ不足ですという
表示がでます。
ここで、ReDim PreserveのPreserveをとって、ReDimだけにすると、数字の増え方が目に見えて遅くなります。
ReDim Preserveとしたときは9.5秒ぐらいですが
ReDim の時は 30秒以上かかっています
3台のマシンでテストしましたが、どれも似たような結果になりました
普通に値を保持するredim Preserveの方が遅いと思うのですがなぜこのような結果になるのでしょうか?
ご教授お願いいたします。
Public Sub 配列上限取得計算()
On Error GoTo ErrEnd
Dim i As Long
Const kankaku As Long = 100000
ReDim ans(1 To kankaku) As String
ans(1) = 1
i = 2
UserForm1.Show vbModeless
Do
If i Mod kankaku = 0 Then
DoEvents
UserForm1.Label1 = i
'ここのPreserveをなくすと明らかに遅くなる
ReDim Preserve ans(1 To i + kankaku) As String
End If
ans(i) = i
i = i + 1
Loop
Erase ans
Unload UserForm1
Exit Sub
ErrEnd:
MsgBox "これ以上の配列を設定できません。" & vbCrLf & "上限は" & i & "です。" & vbCrLf & Err.Description
Erase ans
Unload UserForm1
End Sub
No.1ベストアンサー
- 回答日時:
こんにちは、
> ここで、ReDim PreserveのPreserveをとって、ReDimだけにすると、数字の増え方が目に見えて遅くなります。
> ReDim Preserveとしたときは9.5秒ぐらいですが
> ReDim の時は 30秒以上かかっています
ReDim は 新築
ReDim Preserve は 増築
という喩で説明になっているかと思います。
実際には、Eraseして、メモリの再割り当てをしつつ、配列のサイズ(ディメンション)を再定義するのがReDim
既存のメモリを維持しつつ、メモリを拡張、サイズを再定義するのがReDim Preserve
ということになります。
必然的にReDimを繰り返したら遅くなります。
ご提示のコードでPreserve キーワードを抜くと、
kankakuごとに、ReDimしている訳ですから、
せっかく格納したそれまでの値を消去していることになります。
可変長のString型変数の場合は特殊で、割り当てられるメモリサイズが固定ではありませんから
格納したり消去(長さ0の文字列を格納)したりするのに特に時間が掛かります。
ご提示のコードでPreserve キーワードを抜くと、
それまでに格納した文字長に比例したメモリサイズ、は無視されてしまいます。
本来の目的から外れたテストになってしまいます。
可変長の変数なのですから、要素数、だけではなくて、
要素数と文字長、の2点について、色々パラメータを変えながら
テストしてみた方がより有意義なものになるのではないかと思います。
Dim ans() As String
のように一旦、文字列型として、動的配列変数を予め定義しておいた方が
テストの精度が高まりますし、ReDimに掛かる時間も短くなります。
以上です。
詳しい解説をありがとうございます
>>可変長のString型変数の場合は特殊で、割り当てられるメモリサイズが固定ではありませんから
格納したり消去(長さ0の文字列を格納)したりするのに特に時間が掛かります。
ここで納得できました。試しにstringでlongにしてみると、普通のredimでも高速になりましたし、string型のときに要素数が増えれば増えるほどだんだん遅くなっていったのも、redimする度にすべての要素に長さ0の文字列を格納していたせいだと考えると、つじつまがあいます。
>>可変長の変数なのですから、要素数、だけではなくて、
要素数と文字長、の2点について、色々パラメータを変えながら
テストしてみた方がより有意義なものになるのではないかと思います。
その通りですね。ただ、実際にパラメータを変えてトライしてみたら、新たな疑問が発生してしまったんですが、この質問自体はもう答えてもらってるので、新しい質問として載せることにします。
ありがとうございました
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) Dateserialで データ抽出 2 2022/06/26 21:07
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Visual Basic(VBA) ExcelVBAで質問です。離れた二次元配列を一つにしたい 4 2022/07/26 19:06
- Visual Basic(VBA) userformでSheetを選択して開くコード 1 2023/05/15 16:27
- Visual Basic(VBA) ①ExcelVBAでカレンダーを作り、別のユザーフォームで日付を入力したいのですがエラーになります。 1 2023/02/17 18:39
- Visual Basic(VBA) EXCEL VBAにて動的にCheckBOXを複数作成し、同BOXにイベントを追加したい 1 2023/03/16 07:05
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Visual Basic(VBA) InputBoxでキャンセルボタンを押したらファイル自体を閉じたい 3 2022/07/23 17:52
- Visual Basic(VBA) 稀に1円合いません? Sheet1から金額と個数を貼り付ける下記コードで、金額を切り上げるコードを何 3 2022/09/05 15:11
このQ&Aを見た人はこんなQ&Aも見ています
-
「環境が人を育てる」って本当?環境によって人格や生き方は本当に変わるのか
環境が人生に与える影響は実際どれほどのものなのか、専門家の田宮由美さんに伺った。
-
VBA ReDim と ReDim Preserve の速度差
Visual Basic(VBA)
-
array関数で格納した配列の型を変更する
Visual Basic(VBA)
-
VBA データ(特定値)のある最終行を取得したい
Excel(エクセル)
-
-
4
〔Excel:VBA〕マクロの実行が異常に遅くなる
Excel(エクセル)
-
5
VBAでループ内で使う変数名を可変にできないか。
Visual Basic(VBA)
-
6
ExcelVba 有効なセルかどうかを判定するには
Visual Basic(VBA)
-
7
フレーム内のオプションボタン状態取得方法について
Excel(エクセル)
-
8
Chr(13)とChr(10)の違いは?
PowerPoint(パワーポイント)
-
9
for each の現在の配列ポインタ VBA
Excel(エクセル)
-
10
Excelのマクロ名の並び順の法則は?
Excel(エクセル)
-
11
配列をEraseしてもメモリが開放されていない?
Visual Basic(VBA)
-
12
VBAでブックを非表示で開いて処理して閉じる方法
Excel(エクセル)
-
13
エクセルVBA 大容量CSVファイルの読み込みが遅い
Visual Basic(VBA)
-
14
VBAの配列サイズとメモリに関して
Visual Basic(VBA)
-
15
エクセルVBA 配列からセルに「関数式」を一気代入したい
Visual Basic(VBA)
-
16
VBA 1次元配列を2次元に追加する
Visual Basic(VBA)
-
17
EXCEL VBA マクロ 実行する度に処理速度がどんどん遅くなる原因が知りたい
Excel(エクセル)
-
18
VBAでワークシートを引数としてサンプル関数に渡したい
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Excelのメモリ(配列)の上限は2G...
-
OutOfMemoryExceptionの回避策...
-
C言語
-
固定小数点の三角関数
-
配列の要素がすべてカラかどう...
-
テキストボックの文字を一行ず...
-
複数のtextboxの処理を一括で行...
-
構造体配列内の文字列検索のよ...
-
構造体配列の特定のメンバーをF...
-
jqueryで配列をMySQLのように扱...
-
VB.NETの配列の限界を教えてく...
-
VBA 変数名に変数を使用したい。
-
excel vbaの配列なんですが・・・
-
C#でbyte配列から画像を表示さ...
-
コンボボックスのインデックス...
-
countif/sumifのようなVBA関数
-
Dir関数で読み取り順を操作でき...
-
VB6で、一次元配列と二次元配列...
-
配列のペースト出力結果の書式...
-
エクセル VBA 変数を一括で宣言...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA 変数名に変数を使用したい。
-
C#でbyte配列から画像を表示さ...
-
vba フィルター 複数条件 3つ以...
-
Dir関数で読み取り順を操作でき...
-
Excel2010のinputboxで複数デー...
-
配列の中の最大値とそのインデ...
-
構造体配列の特定のメンバーをF...
-
COBOLの基本的な事なので...
-
構造体配列内の文字列検索のよ...
-
コンボボックスのインデックス...
-
エクセルでXY座標に並べられた...
-
エクセル(VBA)の空白配列の削除...
-
Redim とEraseの違いは?
-
定数配列の書き方
-
VB6のメモリ解放に関して
-
CheckBoxの配列化
-
複数のtextboxの処理を一括で行...
-
Excelのメモリ(配列)の上限は2G...
-
大量の変数を定義するにはどう...
-
OutOfMemoryExceptionの回避策...
おすすめ情報