5

ほとんどすべての UDF を使用する Excel モデルがあります。たとえば、120 列と 400 以上の行があります。計算は垂直に行われ、次に水平に行われます --- つまり、最初に列 1 のすべての計算が行われ、次に列 1 の最終的な出力が列 2 の入力になります。各列で、約 6 つまたは 7 つの UDF を呼び出します他の UDF を呼び出します。多くの場合、UDF は配列を出力します。

各 UDF への入力は、いくつかの変数、一部の範囲変数、一部の double です。範囲変数は、その内容がアクセスされる前に、内部で配列に変換されます。

私の問題は次のとおりです。UDF なしで Excel モデルを構築でき、シミュレーションを実行すると、すべての計算を X 時間で完了することができます。UDF を使用すると、シミュレーション時間が 3 倍以上になります。(明らかな質問に答えるには、はい、UDF を使用する必要があります。モデルに小さな変更を加えたい場合 (別の資産タイプ (金融モデル) を追加するなど) は、モデルを作り直すのにほぼ 1 日かかります) UDF を使用しない場合は、新しい法的/財務構造に適合しますが、UDF を使用すると、異なる財務構造に対応するのに約 20 分かかります。)

いずれにせよ、画面の更新をオフにしました。関数にコピーと貼り付けはありません。バリアント型の使用は最小限で、すべてのデータは 1 つのシートに含まれています。内容を取得する前に、すべての範囲型変数を配列に変換します。 .

VBAコード/Excelファイルをより高速に実行するために、より高速なコンピューターまたは同等のものを入手する以外に、他に何ができますか? これについてさらに説明が必要な場合はお知らせください。

ありがとう!

4

5 に答える 5

4

Excel が UDF を処理する方法にスローダウンのバグがあります。UDF が計算されるたびに、Excel は VBE タイトル バーを更新します (ちらつきを確認できます)。多数の UDF の場合、これは非常に遅くなります。手動計算モードでのバイパスは非常に簡単です。Application.Calculate などを使用して VBA から計算を開始するだけです (OnKey で F9 などをトラップできます)。

詳細については、 http://www.decisionmodels.com/calcsecretsj.htmを参照してください。

于 2009-12-05T09:16:39.103 に答える
4

いくつかの一般的なヒント。

  1. 関数を取り上げて、ボトルネックが実際にどこにあるかを調べます。Excelでのタイマーの使用については、この質問を参照してください。世の中には VBA プロファイラーがあると思いますが、おそらくそこまでする必要はありません。(注: 最初にデータの 1 つのセルでこれを行います...)

  2. デザインについて考えてみてください... 400x120 セルのデータは多くありません。そして、何時間もかかるのは苦痛に違いありません。(過去に、1,000秒が戻るのを1分待ってからクラックしましたVLOOKUPS())とにかく、UDFのスタックを持っている代わりにfor..each、範囲を通過して必要なことを行う単純なサブルーチンを持たないのはなぜですか. 48,000 個のセルには、数秒または数分かかる場合があります。次に、サブルーチンをユーザーのボタンまたはメニュー項目に関連付けることができます。

興味深いことに、オプション 2 をざっと見て、MyUDF() を作成しました。sub を使用しDoMyUDF()てアクティブな選択のためにそれを呼び出すと、すべてのセルに UDF を配置するよりも 10 倍高速に動作しました。

Option Explicit



Function MyUDF(myVar As Variant) As Variant
  MyUDF = myVar * 10
End Function

Sub DoMyUDF()
  Dim r As Range
  Dim c As Variant

  Dim t As Single
  t = Timer


  If TypeName(Selection) <> "Range" Then
    Exit Sub
  End If


  Set r = Selection.Cells

  Application.DisplayStatusBar = True

  For Each c In r
    c.Value = MyUDF(c.Value)

    Application.StatusBar = "DoMyUDF(): " & Format(Timer - t, "#0.0000ms")
  Next

  Debug.Print "DoMyUDF(): " & Format(Timer - t, "#0.0000ms")

End Sub

UDFに置き換えるMyUDF()と、4.5 分しか節約できないかもしれませんが、他にも経済を構築できる可能性があります。特に、同じ計算を何度も繰り返している場合はなおさらです。

于 2009-08-18T15:18:59.710 に答える
3

UDF(出力セルごとに1回呼び出される)を、ループ内のセルの範囲で動作できるマクロに置き換えることを検討しましたか?

UDFのセットアップ/ティアダウンは非常に遅く、各UDF呼び出しが他のUDFと共通して行うこと(たとえば、重複する入力からの読み取り)は余分な労力になります。

これにより、パフォーマンスを10〜50倍向上させることができました。1か月以内に4000〜30000のUDF呼び出しを含むスプレッドシートがあり、それらをいくつかの名前付き範囲で動作する単一のマクロに置き換えました。

于 2009-12-05T09:40:05.647 に答える
2

スプレッドシートからではなく、VBA から再計算を開始していることを確認してください 。つまり、Application.Calculate は、スプレッドシートで F9 キーを押すよりもはるかに高速です (私のテスト ケースでは 100 回)。

于 2010-01-28T08:58:02.857 に答える
2

再計算を制御して最小限に抑える

wks.EnableCalculation = False

また

Application.Calculation = xlCalculationManual

また、VBA とワークブック間の交換を最小限に抑えます。セルのブロックを一度に読み取り、配列に書き込む方が高速です

MyArray = range("B2:B20000") 

セルごとではなく(それぞれ...)。

于 2009-08-18T13:52:19.343 に答える