
すみません。一度質問を載せた後で、補足で絵を載せようとしたのですができなかったので
再投稿させていただきます。(元の質問はけしました。)
--------------------------------------
こんにちは、今作成しているエクセルのVBAで配列を膨大に食ってしまい、メモリ不足に落ちいるという現象に悩まされています。
そのため、なるべくいらなくなった配列はEraseステートメントを使って解放しようとしてるのですが、
これが上手くいっている気がしません。
ためしにフォームと、ラベルを1つずつ用意し、下記のような配列をどこまで作れるか計算するプログラムを組んでみました。
1回目、ans(i) に"a"というaを1個のみ格納した場合で計算すると、配列は2970万個できます。
2回目、ans(i) に"aaa~a"というaを64個格納した場合で計算すると、配列は770万個できます。
まぁ、ここまでは当然の結果だと思います。
可変長のString型変数の場合は、割り当てられるメモリサイズが固定ではないらしいので
(前回の質問で教えてもらいました)
しかし3回目、ここでもう一回、1回目と同じ、"a"を一個のみ格納した場合で計算してみます。
私の予想では1回目と同じ2970万個程度の配列が作れると思っていました。
なぜなら、Eraseステートメントでメモリを解放していたし、
タスクマネージャーのPF使用量(おそらくメモリの値)を見ても2回目を実行した後の値は
1回目前と同じ値に戻っているからです。
しかし、実際試してみると、
2回目と同じ770万個の配列しかつくれませんでした。
つまり、Eraseステートメントを使用しても配列の上限値は元の状態に戻らなかったのです。
どうすれば、配列を再び2970万個作れる初期の状態に戻せるのでしょうか?
現時点ではエクセルを起動しなおせば、元に戻りますが、それでは困ります
(プログラムの途中で配列の数を減らしたり、コピーしたりを行っている為、
どうしてもプログラム中でメモリの解放を行いたいからです)
また、添付した絵は、実行した時のタスクマネージャーの様子です。
参考になれば幸いです
どうか、みなさんお知恵をお貸ししてください
---------------------------------------------------
'実行するときは、フォームとラベルを1つずつ用意して実行してください
Public Sub 配列上限取得計算()
On Error GoTo ErrEnd
Dim i As Long
Const kankaku As Long = 100000
Dim ans() As String
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
ReDim Preserve ans(1 To i + kankaku) As String
End If
'最初にaを1個のみ格納した場合は、2970万個まで配列が作れるが、次にaを64個格納した場合は770万個まで作れた。
'しかし、その直後にまた、aを1個のみ格納した場合で実行してみると、770万個しか作れない
'つまり、Eraseステートメントを使っているにも関わらず、同じ条件のプログラムでも配列の上限が下がってしまう。
'この現象をなんとか回避したい。元の状態にリセットするにはエクセルを起動しなおさないと直らない。
'1回目と3回目に実行するコード、2回目はコメントアウトしてください
ans(i) = "a"
'2回目に実行したコード、2回目はコメントアウトを解除してください。
' ans(i) = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
i = i + 1
Loop
Erase ans
Unload UserForm1
Exit Sub
ErrEnd:
Erase ans
MsgBox "これ以上の配列を設定できません。" & vbCrLf & "上限は" & i & "です。" & vbCrLf & Err.Description
Unload UserForm1
End Sub

No.2ベストアンサー
- 回答日時:
使用メモリが断片化して、2970万個分の連続領域が確保できない、というケースもありそうです。
初期化ですが、Excel再起動以外の方法は、私は知りません。
この回答への補足
そうですか・・・断片化と聞いて勝手に想像してみたのですが
"a"がアドレス一個分のメモリを消費
"aaaaaaa~a"がアドレス100個分のメモリを消費すると仮定した場合
最初に
a(0):001番地
a(1):002番地
a(2):003番地
といった具合だったのが
a(0):001~100番値
a(1):101~200番値
a(2):201~300番値
といった感じで、メモリのアドレスを占有するけれど
次に、"a"で格納しようとした場合、実際に使うのは1個分のアドレスだけど
a(0):001番値、002~100番地はデータのゴミ
a(1):101番値、102~200番地はデータのゴミ
a(2):201番値、202~300番地はデータのゴミ
という感じになって、002~100番地を有効に使えないようなイメージでしょうか。
どうにか解決策が知りたいです。
No.5
- 回答日時:
> BSTRキャッシュを無効というのは、String型以外にしろということでしょうか?
(用語の意味が分からないなら)ググらないと。
参考URL:http://keicode.com/com/bstr-cache.php
この回答への補足
すみません。ご親切にありがとうございます。
システム環境変数にOANOCACHE=1を追加して、PCを再起動してみましたが、特に変化は見られませんでした。
やはり、無理なのでしょうか
No.4
- 回答日時:
>そうですか、では、配列の上限値をもとの状態に戻すことは不可能なのでしょうか?
申し訳ありませんが可能かどうか私にはわかりません。
#2の方がいわれるように断片化が原因であるなら再起動するしか手はないと思いますが。
この回答への補足
なるほど、断片化が原因なら無理なんですね。
どうも、それっぽい感じもしますね。
NO2でちょっと勝手ながら断片化の解釈しちゃってますけど
あれだと、配列が同じ数だけしか作れない事の
つじつまがあいますし、Excelの再起動で直るわけですし。
そうなると、なるべく配列は減らして、影響を少なくなるように設計するしかなさそうですねぇ・・・
毎回マクロ実行するたびにexcel起動しなおさなければならないのもあれですが・・・
No.3
- 回答日時:
単にOSのキャッシュが効いてるだけでは。
BSTRキャッシュを無効にしてみるとか。
※ BSTR(VBAのString型の事)
この回答への補足
BSTRキャッシュを無効というのは、String型以外にしろということでしょうか?
残念ながら、扱う値は文字列なのです。
確かに、long型とかだと、値変えてもあまり変化ないですね。
string型だと可変長の長さを持っている為、
一度大きな文字列を入れてしまうと、文字列を後から入れなおしても
メモリの番地を詰めることができないということなんでしょうか・・・
文字列だと不可能なんですかね
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
VBAの配列サイズとメモリに関して
Visual Basic(VBA)
-
Redimした動的配列はEraseする必要があるのか
Visual Basic(VBA)
-
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
-
-
4
エクセル:マクロ「Application.CutCopyMode = False」って?
Excel(エクセル)
-
5
vbaのエラー対応(実行時エラー7:メモリが不足しています)
Visual Basic(VBA)
-
6
動的配列が存在(要素が有る)か否かを判定できますか?
Visual Basic(VBA)
-
7
Excel VBA 処理後データが重たくなる&処理スピードが遅いのを解決したい
Visual Basic(VBA)
-
8
エクセルのラベルの値(文字列)を垂直方向で中央揃えにするには?
Excel(エクセル)
-
9
【Excel VBA】 WorksheetやRangeオブジェクトとして宣言した変数の開放は必要でしょうか?
その他(Microsoft Office)
-
10
ReDim PreserveよりもReDimが遅い
Visual Basic(VBA)
-
11
エクセルVBA 配列からセルに「関数式」を一気代入したい
Visual Basic(VBA)
-
12
配列のペースト出力結果の書式について
Visual Basic(VBA)
-
13
ユーザーフォームをホイールでスクロールする方法(Excel2000VBA)
Excel(エクセル)
-
14
エクセル・VBA CheckBoxのオブジェクト名に変数を使うことは可能でしょうか?
Excel(エクセル)
-
15
メモリ不足になってしまう。
Visual Basic(VBA)
-
16
EXCELのVBAで作業ファイルを閉じてもメモリの解放をしなくて困っています
Excel(エクセル)
-
17
エクセルVBA テキストボックスに3桁ごとにコンマ
Visual Basic(VBA)
-
18
エクセルVBAで5行目からオートフィルタモードに設定したいたい
Excel(エクセル)
-
19
配列の値を置換するにはどうすればいいでしょう?
Excel(エクセル)
-
20
メモリが不足しています(VBA)
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列を使わずに、変数名を動的...
-
C言語 配列の長さの上限
-
C# Listを使わずに2次元配列の...
-
【速いブラインドタッチ】手を...
-
ExcelVBAで質問です。離れた二...
-
メモリの初期値
-
配列で格納したものをmsgboxで...
-
Excel、VBAのユーザーフォーム...
-
配列の参照渡しで型が一致しま...
-
C言語で特定列だけを抽出して配...
-
配列をEraseしてもメモリが開放...
-
C++ vectorに配列をプッシュしたい
-
銀行ATMの数字キーの配列
-
if文の判定条件に配列
-
2次元配列でエラーがでます。
-
C言語の配列:「*(w+a)=・・・...
-
先頭アドレスとは何ですか?
-
VBで構造体の配列を関数に渡す...
-
配列の総和
-
プログラムが書けません。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
先頭アドレスとは何ですか?
-
C# Listを使わずに2次元配列の...
-
配列を使わずに、変数名を動的...
-
複数の選択範囲の行番号を個別...
-
配列で格納したものをmsgboxで...
-
【速いブラインドタッチ】手を...
-
C言語で特定列だけを抽出して配...
-
配列をEraseしてもメモリが開放...
-
配列を含む構造体の初期値について
-
C# 配列の変数宣言について。
-
テキストファイルから文字列を...
-
メモリの初期値
-
C++ vectorに配列をプッシュしたい
-
Redimした動的配列はEraseする...
-
VBで構造体の配列を関数に渡す...
-
【C言語】配列の中に配列を入れ...
-
ExcelVBAで質問です。離れた二...
-
Functionの戻り値を2次元配列...
-
ガウスの消去法のプログラム
おすすめ情報