VBAユーザー関数の外部制御

このQ&Aのポイント
  • VBAユーザー関数の外部制御について解説します。
  • ExcelのVBAで、ユーザー関数を外部から制御する方法について説明します。
  • ユーザー関数の再計算時間を短縮するための方法を紹介します。
回答を見る
  • ベストアンサー

VBAユーザー関数を外部から制御

ExcelのVBAで、標準モジュールにワークシートで使うユーザー関数を記述しています。 ユーザー関数は、使い勝手を組み込みのワークシート関数と同様にするため、 Application.Volatile (True) で自動再計算するようにしており、数百カ所以上のセルに使用しています。 しかし、他のVBAモジュールでユーザー関数の戻り値が変わるような操作をすると、その都度 数百か所以上が再計算されるため、非常に時間がかかります。 ユーザー関数のApplication.Volatile (False) にすると瞬間で終了する処理が、数分かかる場合も あります。 他のVBAモジュールから、一時的にユーザー関数の処理内容を変更するようなことは可能でしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • keithin
  • ベストアンサー率66% (5278/7940)
回答No.1

ご質問の直接の回答としては application.calculation = xlcalculationmanual で一旦再計算を手動に止めておき、一渡りの処理を終えたら application.calculation = xlcalculationautomatic で再計算させます。 ただし。 >組み込みのワークシート関数と同様にするため、 Application.Volatile (True) で自動再計算するようにしており ごく一般論でいうと、ワークシートのセルを引数に取るユーザー定義関数で作成しておき、通常はvolatileは制御しません。 例: public function test(byval target as range) as variant test = 引数として渡されたセルの値を元に何某の計算を行う end function といった具合に工夫して作成することで、引数として与えたセルに変更を加えた(=再計算チェーンに載ってくる)場合のみ適切に再計算され、シート上の全部の当該関数が毎度毎度一斉に再計算されるみたいな事態は回避します。

Barracuda
質問者

お礼

ありがとうございます。 application.calculation による制御で、自動計算による速度低下が回避できました。 > public function test(byval target as range) as variant ただ、ユーザー定義関数を上記のように変更しても、Application.Volatile (True)を入れなければ再計算しません。 私が作成したユーザー関数は、引数として渡されたセルだけでなく、引数に応じた、引数とは別のセルも参照して結果を返します。 これが関係しているのでしょうか。

その他の回答 (2)

  • keithin
  • ベストアンサー率66% (5278/7940)
回答No.3

再掲: >引数として与えたセルに変更を加えた(=再計算チェーンに載ってくる)場合のみ適切に再計算され 引数として与えたセルに変更を加えて無ければ、再計算チェーンに載らず放置されます。引数とせずコードの中で独自にどこかのセルの値を計算に使ってるだけでは、もちろん引数にはなりません。 どの値(変数)が変更された場合に再計算が必要なのか分析して、適切に引数として設計してください。

Barracuda
質問者

お礼

たびたびありがとうございます。 よく考えてみれば、ユーザー定義関数内で参照しているセルを変更しても、引数を変更しなければ関数が起動するはずはありませんね。 Application.Volatile (True) がなければ再計算しない理由がわかりました。

回答No.2

こんばんは。 > Application.Volatile (True) 基本的には、Volatile で、不揮発性を変更しても、無意味です。引数を入力の際に、再計算イベントが走りますから、多くを使う場合は不要です。要するに、入力するたびに、一斉に、再計算イベントが走ってしまって、処理が遅くなっているものだと思います。 実際、ワークシート関数で作れないものは、特殊な場合を除き、ほとんどありません。 >数百カ所以上のセルに使用しています。 ふつうは、VBAのユーザー定義関数を多用するのでしたら、プロシージャで処理したほうがよいです。 >他のVBAモジュールから、一時的にユーザー関数の処理内容を変更するようなことは可能でしょうか。 意味がよく分かりませんが、VBAでコードの内容を変えるという意味でしょうか。 もしそうなら、ユーザー定義関数の処理内容を変更することは、裏ワザとしてはあったとしても、VBAプログラマーとしては、それは禁じ手だと思います。

Barracuda
質問者

お礼

ありがとうございます。 > VBAでコードの内容を変えるという意味でしょうか。 その通りです。 30年以上前、Z80やMC6809のマシン語で処理速度を高めるため、処理内容に応じて自分自身のオペランドどころか、オペコードも書き換えるという裏技をよく使っていました。 当時から「禁じ手」であることは認識していましたが、ひょっとしたらVBAでもできるかもしれない、と思いました。

関連するQ&A

  • EXCELのVBAで、あるワークシートでのみ使うユーザーフォームを作り

    EXCELのVBAで、あるワークシートでのみ使うユーザーフォームを作りました。そのワークシート上での定数や、プロシージャや関数をワークシートのモジュールに置いています。そして、その定数や関数などをユーザーフォームのイニシャライズなどで使いたいと思いますが、ユーザーフォームのモジュールはワークシートのモジュールとは別なので、使えません。他への影響を考えると、標準モジュールには、置くのは不適切だと思います。 特定のワークシート上でのみ使うユーザーフォームと、そのワークシートとで、共通の定数や関数などを使う方法は、あるのでしょうか。どのようにすればよいのでしょうか。

  • vba 自作関数

    Function zei(myRng As Range) As Double Dim c As Range Dim goukei As Double 'Volatileについて 'シート内のどこかのセルを参照しているものとする 'シートのどこかに変更があったらそのセルが自動的に再計算される Application.Volatile goukei = Application.WorksheetFunction.Sum(myRng) zei = Int(goukei * 5 / 100) End Function これを標準モジュールに貼り付けてワークシート上で関数を呼び出し、 100を入れると#VALUE!が返るのですがどうしてでしょうか? 違う値を入れても必ず#VALUE!が返ります。

  • エクセルVBA IDの有無をユーザー定義関数で知る方法

    Sheet1上のA1セルにIDプロパティでのIDを設定した場合、これをワークシート関数で取得する方法が見つけられなかったのでユーザー定義関数を以下の通り作成しました。 Function IDCheck(CksCell As Range) As Boolean Application.Volatile (True) IDCheck = Sheets("Sheet1").Range(CksCell.Address).ID <> "" End Function これで、Sheet1上で=IDCheck(A1) というように記述すれば、IDが設定してあればTRUE、そうでなければFALSEを返すのでわかります。 ところが、このままでは自動計算のつもりでApplication.Volatile (True)を記述しているにもかかわらず、IDを削除してもワークシート上の表示はTRUEのままです。 どうしたらよいのでしょうか? もし、ワークシート関数で取得する方法があれば、そちらの方がベターです。

  • ユーザー定義関数を作りVBAで記述

    aaaと言う、ユーザー定義関数を作りVBAで記述して使う場合はどのように記述すればよいでしょうか。 通常のワークシート関数であれば、 Cells(1, 1) = Application.Sum(Range("G1:G100")) などとなりますが、 Cells(1, 1) = Application.aaa(Range("G1:G100")) とするとエラーになります。 初歩的な質問だとは思いますが、よろしくお願いします。

  • エクセルのユーザー定義関数で(VBA)

    エクセルのVBAで、セルに「=SheetName」と書き込めば、その関数を書き込んだセルが属するシート名をセルに代入さるようなユーザー定義関数を作りたいと考えています。 で、標準モジュールに Public Function SheetName(test) SheetName = ????? End Function と、書き込んでふと止まりました。 ユーザー定義関数を書き込んだシートの名前ってどうやって取得すればいいのでしょうか?VBでいうSenderみたいなのってあるんでしょうか? どなたか?詳しい方教えて頂けないでしょうか? 宜しくお願いいたします。

  • VBAでの複素数関数

    複素数の関数を使い計算処理を行っているのですが、VBAの複素数関数処理がかなり遅い(計算処理を行う個所が非常に多く、何度もループし、VBA関数を呼び出しています。)ので、スピードを上げる方法をどなたかご存知であれば、教えていただきたいのです。 よろしくお願い致します。

  • 複素数関数のユーザー定義方法等をお教えください

    カテゴリーにVBAがありませんでしたので VBに投稿させていただきます。 EXCEL2000VBAで複素数関数や三角関数等を用いて 加速度波形処理の勉強をしています。 過去のQ&Aで VBAアドインの複素数関数を用いた場合の 計算時間の長さを短縮する方法としまして (1)ユーザー定義で複素数関数計算を作成する。 (2)モジュールに直接書込む。 との記述がありました。(質問番号:81639) 上記(1)(2)につきまして詳しくお教えください。 自作のVBAにどのようにして上記(1)(2)を 作成又は書込みすれば良いのかがわかりません。 複素数関数計算のFUNCTION?等も お教えいただけましたら幸いです。 宜しくお願いします。

  • ユーザ定義関数がうまく動きません。

    ユーザ定義関数がうまく動きません。 2月のA1セル値が1になっていたりします。 どこがおかしいのかわかりません。解決方法を教えていただけませんでしょうか。 よろしくお願いします。 【シートの設定】 シート名は1月・・・12月です。 各シートの A1セルは「=sheetname()」 B1セルは「月のチェックシート」 が入っています。 【VBAの設定】 Function SheetName() As String 'Application.Volatile If Len(ActiveSheet.Name) = 3 Then SheetName = Left(ActiveSheet.Name, 2) Else SheetName = Left(ActiveSheet.Name, 1) End If End Function

  • VBAでワークシート関数を使用するときの注意点は

    WindowsXPのExcel2003のVBAで作った物を、別のPCで動作させたところコンパイルエラーが出て動きません。 作成段階でのTESTまでは何の不具合もなく正常なのですが、別のPCでは構文エラー(たぶん)が出るのです。 ワークシート関数の構文らしく、関数の前に"Application.WorksheetFunction."を付けていないのが原因と思われます。 質問は2つで、 1.全てのワークシート関数には"Application.WorksheetFunction."文を付けなければならないか? 2.作成PCと動作PCが違う場合、同じモジュールでも違う動作をするのか? また、その場合の原因も。 どなたかご教示下さい。 お願いします。

  • エクセルのユーザー関数が小文字に

    WindowsXP Proffessional OFFICE2003の構成でエクセルを使用していてサービスパックも入れています。 自分でユーザー関数を作って使用しているのですが標準、モジュールのほうで大文字で関数を書いているのにワークシートのほうで使用すると勝手に小文字に書き換えられてしまいます。 標準モジュール一つだけ関数マクロがあるだけでシートのほうには何も記述していません。 ちょっと前まで標準モジュール内の関数を大文字に指定していても小文字に戻されてしまうので、わざとシートのほうに大文字で関数を書くと標準モジュール内の関数が自動的に変わって問題は解決したと思ったのですが、エクセル本体?の関数が変わっておりません。 関数そのものの動きは思った通りに動いています。 こういうときはみなさんはどうなさいますか?

専門家に質問してみよう