- ベストアンサー
VBAでの複素数関数
複素数の関数を使い計算処理を行っているのですが、VBAの複素数関数処理がかなり遅い(計算処理を行う個所が非常に多く、何度もループし、VBA関数を呼び出しています。)ので、スピードを上げる方法をどなたかご存知であれば、教えていただきたいのです。 よろしくお願い致します。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
実際にモデルを作りステップ実行してみましたら、アドインはRUNメソッドで関数名に対応したユーザー定義関数を呼び出し、その中では、またユーザー定義関数etMacroRegIdで関数のレジスタID(?よく分かりませんが)を取得し、再度RUNメソッドが実行されているようです。 (専門家ではないので詳しくは分かりません。違っているかもしれません。)大変な処理をしているんだなとビックリしました。 実際、どのような関数を使用され、どのような処理か分かりませんので2000件くらいのデータに対し複素関数計算をアドインVBAで実行させ、同様の結果が出るユーザー定義関数(アドインを使わない関数です)を作り数種類のパターンで比較してみました。 結果は、アドインよりも自分で作ったユーザー定義関数が1/2~2/3程度の時間で済みました。(たまたまかもしれません) 全部の複素関数を作ったわけではないので不確実ですが、ユーザー定義で複素関数計算を作りこんだほうが(またはモジュールに直接書いたほうが)速い場合があると思われます。 ただし、複素数から実数、虚数部分を取り出すような部分はアドインを使ったほうが速いかもしれません。アドインと自作関数(直接の計算)を使い分ける必要があるように思いました。そうすれば、少しは早くなるかもしれません。解決にはならないと思いますが一応報告します。
その他の回答 (2)
- arata
- ベストアンサー率49% (139/279)
Excelの複素数関数を使用していて、この実行が遅いので、これをなんとかするというのを前提に回答します。 関数自体の性能は、どうしようもありませんので、VBA側で足を引っ張っている部分を修正します。 (ですから、複素数関数に関係なくどのようなExcelのマクロでも高速化の可能性があります。) 遅い要因としては、 1.ワークシートに書き込むたびにExcelが描画をするため、遅くなる 2.ワークシートに書き込むたびにExcelの自動計算が動作するため、遅くなる 3.Excelのオブジェクトへの参照が頻繁に発生するために、遅くなる などの原因があります。もちろん、ロジック自体に要因がある場合がありますが、それはソースをみないとなんともいえませんので・・・ 1ですが、描画をとめる命令があります。 ■描画停止 Application.ScreenUpdating = False ■描画再開 Application.ScreenUpdating = True マクロのはじめで、停止させて、終わる前で再開させてください。 マウスカーソルも砂時計にしておいたほうがいいかも。 ■マウスカーソルを砂時計にする Application.Cursor = xlWait ■マウスカーソルを元にもどす Application.Cursor = xlDefault 2は、自動計算をマニュアルにします。 ■自動計算を手動にする Application.Calculation = xlCalculationManual ■自動計算を自動にする Application.Calculation = xlCalculationAutomatic 自動計算をマニュアルにしている場合で、プログラムが、ワークシート内の自動計算の結果を利用している場合は、手動では問題がありますので、計算結果を利用する前に計算を強制的に実行してください。 Application.Calculate Calculateは、ワークシートに対して実行させることもできます。また、自動計算を自動に設定しただけでは、再計算は実行されませんので、手動にした場合は、自動に戻すときに、一度Calculateで強制的に計算をさせてください。 3はですが、例えば、下記のようなプログラムがあった場合ですが、 Dim i As Long Dim x As Long For i = 1 to 10 x = ThisWorkbook.Worksheets(1).Range("B1").value * ThisWorkbook.Worksheets(1).Cells(i,1).value Next ThisWorkbook.Worksheets(1).Range("B1").valueを10回も探しにいきますので、変数に値をとっておいて、実行させるようにします。 Dim i As Long Dim x As Long Dim x1 As Long x1 = ThisWorkbook.Worksheets(1).Range("B1").value For i = 1 to 10 x = x1 * ThisWorkbook.Worksheets(1).Cells(i,1).value Next ThisWorkbook.Worksheets(1).Cells(i,1).valueの部分も、ThisWorkbook.Worksheets(1)は、固定ですから、早く見つけ出せるように変数に入れるようにします。 Dim i As Long Dim x As Long Dim x1 As Long Dim objSheet As Worksheet Set objSheet = ThisWorkbook.Worksheets(1) x1 = ThisWorkbook.Worksheets(1).Range("B1").Value For i = 1 To 10 x = x1 * objSheet.Cells(i, 1).Value Next こんなところでしょうか。 質問の解釈を間違っていましたらごめんなさい。
補足
大変ご丁寧な回答に感激しております。 前提としまして、エクセル側の計算式を使わず、プログラム上で計算を実行したいのです。 頂いた回答の3につきまして、遅くなっている原因の一つだと思い、エクセルオブジェクトを変数に代入し処理する方法は対応しました。 あとは、やはり分析ツールVBAの複素数関数処理が非常に遅いことです。 これを回避する方法があれば、と色々考えたりしているのですが、私の学力では限界にきています。。。 私の質問内容が足りなく、お手間をおかけしてしまいました。 ありがとうございまいた。
- nishi6
- ベストアンサー率67% (869/1280)
>VBAの複素数関数処理 とはどのような処理でしょうか。よろしかったら内容を教えて下さい。
補足
VBAの複素数関数処理とは、アドインの中に入っている分析ツールVBAの複素数関数処理です。
お礼
参照設定を使い何度もループさせていたので、 おっしゃられた通り、複素数に詳しい方に関数を作ってもらい(自分では作れませんでした)、モジュール内に直接書き込みプログラムを完成させました。 スピードは、当初 複素数関数を含んだ計算処理を実行した時は40分かかる計算が、なんと、4分になりました。(本当です)1/10です。 もう驚きです。 スッキリした気分です。 解決にならないどころか、とても参考になりました。 ご助言していただき、ありがとうございました。嬉しいです!