2012-04-30 11 views
2

私の目的は、Excelのセル範囲に2次元のバリアントの値を割り当てることです。配列に範囲を割り当てるときのVBAメモリの問題

割り当ては正常ですが、私はメモリの問題(リーク)に直面しています。私がExcelを起動すると、プロセスには多少のRAMが必要になります。次のコードを実行した後(新しいブックを作成し、範囲を割り当て、保存せずにブックを閉じる)、プロセスには33MoのRAMが必要です。

誰かが私が間違っていることを考えているのですか?ここで

よろしく、 アレクサンダー

コード

Option Explicit 

Sub test() 
    Dim nLines As Long 
    Dim xSize As Long 
    Dim j As Long 
    Dim i As Long 

    'Creating New Empty Workbook 
    Application.Workbooks.Add 
    Range("A1").Select 

    Application.ScreenUpdating = False 

    nLines = 10000 
    xSize = 200 

    Dim myRange As Range 
    Dim myArray() As Variant 

    ReDim myArray(1 To nLines, 1 To xSize) 

    'Assigning some values 
    For j = 1 To nLines: 
     For i = 1 To xSize: 
     myArray(j, i) = i * 4/3# 
     Next i 
    Next j 

    Set myRange = Range(ActiveCell, ActiveCell.Offset(nLines - 1, xSize - 1)) 
    myRange .Value = myArray 

    'Cleaning up 
    Erase myArray 
    Set myRange = Nothing 

    'Closing workbook without saving 
    Application.ActiveWorkbook.Close (False) 

    Application.ScreenUpdating = True 

End Sub 
+2

Moが何であるか分かりませんが、Excel実行時に11 MBの説明できないRAMがVBAなしでもかなり一般的です... – Aprillion

+1

'私は間違っていると思いますか?あなたが作成しているアレイを処理するための-45MbのRAMがかなり普通です:)あなたが読んでみたいかもしれない「Excel Memory Limits - Charles Williamns」の興味深い記事は? http://www.decisionmodels.com/memlimitsc.htm –

+0

あなたの答えをありがとう。 11 MB(フレンチでは、ごめんなさい)、重要なリークではない、と私は同意するが、私が投稿したコードは、私が非常に大きな範囲のためにしなければならないことの一例に過ぎない。私が200の代わりにxSize = 2000を設定すると、100 MBのリークが発生します...コードを1行ずつデバッグすると、 "Set myRange = Nothing"という命令はメモリを解放しません。何か案が ? – Alexander

答えて

8

VBAはCではない、どのような方法でExcelのメモリフットプリントを制御することができるにカウントされません。 Excelはメモリ管理にはそれほど優れているわけではなく、多くの場合、マクロを実行しているか、マクロ内で何をしているのかは、Excelが割り当てるメモリ量それをもう一度解放することに決めました。

言われているように、混乱を減らすためにコード内でできることがいくつかあります。

  1. Range("A1").Select

    これはExcelでそれらを操作する前に、細胞を選択するために、一般的に悪い習慣です。セルを選択する必要があるのは、マクロのビューアに何かを示している場合だけです。さらに、このコードは実際にワークブックを追加しただけでExcelの特定のバージョンで実際に問題を引き起こす可能性があります。このコードはすべて削除する必要があります(とにかくロジックには影響しません)。

  2. Set myRange = Range(...

    あなただけの範囲で1つのアクションを実行しているので、このコードは必要ありません。 myRange変数をまったく作成する必要はないので、何も設定しない、またはもっと重要なことに気を付ける必要はありません。つまり、何も設定しても実際に何もメモリを達成しないという事実です。 「を選択」と「ActiveWorkbook」の明示はなく、ユーザが他のを持っている場合は特に、信頼性のない動作を引き起こす可能性がありますへの呼び出しに基づいて

  3. ActiveCellと再び

    Application.ActiveWorkbook、これらの未修飾の参照スプレッドシートはExcelの同じインスタンスで開きます。最初に追加したブックへの参照を保存する方がよいでしょう。

すべてのすべてで、私はこのようにコードを変更します

Sub test() 
    Const nLines As Long = 10000, xSize As Long = 200 
    Dim i As Long, j As Long 
    Dim newWorkbook As Workbook 

    Application.ScreenUpdating = False 

    'Creating New Empty Workbook 
    Set newWorkbook = Application.Workbooks.Add 

    'Assigning some values 
    Dim myArray(1 To nLines, 1 To xSize) As Double 
    For j = 1 To nLines: 
     For i = 1 To xSize: 
     myArray(j, i) = i * 4/3# 
     Next i 
    Next j 

    With newWorkbook.Sheets(1) 
     .Range(.Cells(1, 1), .Cells(nLines - 1, xSize - 1)).Value = myArray 
    End With 

    'Closing workbook without saving 
    newWorkbook.Close (False) 

    'Cleaning up 
    Erase myArray 
    Set newWorkbook = Nothing 

    Application.ScreenUpdating = True 
End Sub 

閉会挨拶:

VBAコーディングレッスンさておき - なお、新規を開く行為ブックは、一時的な配列を作成するよりも多くの新しいメモリを割り当てるようにExcelに依頼します。これは、新しいブックを閉じた後であっても、自由に動かすことができます。これらの増加を回避することはできません。 Excelのメモリフットプリントは現在のワークブックには関連付けられていないこと、複数のワークブックをサポートするインスタンスのライフタイム全体、バックアップ、最適化された計算ツリー、元に戻す履歴などには注意が必要です。新たに立ち上げられたExcelのインスタンスのフットプリントと、単に「たくさんのもの」が実行されたインスタンスのフットプリントを比較します。

また、Excelがそのメモリを解放することを決定していないという理由だけで、それがリークにならないことにも注意してください。 Excelは、リサイクル可能な/再利用可能なオブジェクトにメモリを割り当てている可能性があります。反復的にコードを再実行すると、毎回メモリが少しずつ増加する可能性がありますが、Excelは一定量のインスタンスアクション履歴を追跡することもできます。

(偶然)私の要点を説明します。ここでは、新しいインスタンスを開いてコードを1回、9回以上実行した後に40回以上実行したときのExcel(2007)のメモリフットプリントを示します。

enter image description here

それはあなたのコードのせいではありません、責任はそれを心配するあなたにではなく、あなたのビジネスユーザーはそれを心配している場合、彼らは彼らのターゲット・開発などのExcelの古いバージョンを選択するべきではありませんプラットフォーム。

+0

+1は「VBAはCではありません」とtaskmgrのスクリーンショットです。うまく答えました! – Blackhawk

関連する問題