web-dev-qa-db-ja.com

Excel vbaで「メモリ不足エラー」を防ぐためにメモリをクリアする方法は?

大きなスプレッドシートでVBAコードを実行しています。プロシージャ/コール間のメモリをクリアして、「メモリ不足」の問題が発生しないようにするにはどうすればよいですか?

ありがとう

24
Marc L

メモリを解放するための最善の方法は、大きなオブジェクトを無効にすることです。

Sub Whatever()
    Dim someLargeObject as SomeObject

    'expensive computation

    Set someLargeObject = Nothing
End Sub

また、グローバル変数は1つの呼び出しから別の呼び出しに割り当てられたままなので、永続性が不要な場合は、グローバル変数を使用しないか、不要になったときに無効にしてください。

ただし、これは次の場合には役立ちません。

  • プロシージャの後にオブジェクトが必要です(明らかに)
  • オブジェクトがメモリに収まらない

別の可能性は、クラッシュする前により多くのRAMを使用できる64ビットバージョンのExcelに切り替えることです(32ビットバージョンは通常、約1.3GBに制限されています)。

13
assylias

回避策を見つけました。最初はもっと時間がかかるように見えましたが、実際にはスワッピングが少なく、使用可能なメモリが多いため、すべてがスムーズに高速に動作します。これは科学的なアプローチではなく、動作する前にテストが必要です。

コード内で、Excelがワークブックを時々保存するようにします。 360 000行のシートをループしなければならず、ひどく詰まってしまいました。 10000ごとにコードを作成してワークブックを保存すると、32ビットExcelでもコードが魅力的に機能します。

同時にタスクマネージャーを起動すると、保存するたびにメモリ使用率が大幅に低下することがわかります。

12
Arne Larsson

明示的にはできませんが、ルーチンでメモリを解放する必要があります。

しかし、メモリを助けるためのいくつかのヒント

  • ルーチンを終了する前に、必ずオブジェクトをnullに設定してください。
  • オブジェクトで必要な場合は、必ずオブジェクトでCloseを呼び出してください。
  • 絶対に必要でない限り、グローバル変数を使用しないでください

ルーチンを何度も実行した後、メモリ使用量を確認することをお勧めします。メモリリークが発生する可能性があります。

4
Dreamwalker

大きなデータセットを操作する場合、配列が使用される可能性が非常に高くなります。私にとって、500 000行と30列のワークシートからいくつかの配列を作成すると、このエラーが発生しました。次の行を使用して、別の配列を作成する前に、不要になった配列を削除するだけで解決しました。

Erase vArray

また、30列のうち2列のみを使用する場合は、30列の1列ではなく、1列の配列を2つ作成することをお勧めします。速度には影響しませんが、メモリ使用量に違いがあります。

1

私の問題の解決策を探しているこのスレッドを見つけました。私は、他の人に役立つかもしれないと私が理解した別のソリューションを必要としました。私のマクロは行を削除し、上に移動し、行を別のワークシートにコピーしていました。メモリ使用量が数ギグに爆発し、約4000レコードのみを処理した後に「メモリ不足」を引き起こしていました。何が私にとってそれを解決しましたか?

application.screenupdating = false

コードの始めに(最後に必ずtrueにしてください)、それが実行を高速化することを知っていました。

この小さな変更を行った後、メモリ使用量は135 mbを超えませんでした。なぜそれが機能したのですか?本当にわからない。しかし、それは一見の価値があり、あなたに当てはまるかもしれません。

0
Stevetb77