2017-09-20 1 views
1

MS Access VBAで実行パスをトレースするアプリケーションで作業しています。しかし、私は問題に遭遇しました。 VBAでは、OnClickやその他のイベントを制御するためにハンドラを動的に割り当てることができますが、これらのコントロールからイベントを読み取る方法はありません。例:VBAでOnClickイベントのイベントハンドラをプログラムで特定する

With Forms("Order Entry").Controls("OK") 
If .OnClick = "" Then 
.OnClick = "fnProcessOrder" 
End If 
End With 

これは、機能「fnProcessOrder」を「OK」ボタンに動的に割り当てます。あなたがそのボタンの値を取得しようとする場合は、あなたはこれを取得:

With Forms("Order Entry").Controls("OK") 
    Debug.Print "My Handler -->" + .OnClick 
EndWith 

結果で:

--> [Event Procedure] 

、それ以上の詳細。これは、Microsoftがここに記載した動作であると思われます。 https://msdn.microsoft.com/en-us/vba/access-vba/articles/commandbutton-onclick-property-access

しかし、それ以上に進むにはどうしたらいいのでしょうか。

私はその情報がMSysObjectsテーブルとMSysQueriesテーブルにあると思っていましたが、そこには表示されません。私は、データベースDocumenterを使用して私のテストデータベースを抽出しようとしましたが、私は生成されたドキュメントからもその価値を得ています。

コントロールに割り当てられたVBA関数を見つける方法はありますか?

+0

いずれのツールにも制限があります。'' fnProcessOrder ''文字列リテラルが部分から連結される場合を考えてみましょう。 '.OnClick =" fnProcess "&itemType'です。 FWIW私は実行パスに関するあなたの仕事について、そしてあなたがそれについてどのように動いているかについて非常に興味があります。 「Rubberduck」(http://www.github.com/rubberduck-vba/Rubberduck)はここであなたの専門知識を利用することができます。今後の大きな課題の1つは、「コードパス解析」コード検査を20実装しようとしている。シンボルテーブルと抽象構文ツリーなしでこれをやっていますか? –

+0

さて、私は、pyparsing、lex、または手作業で何らかの基本的な処理を行う予定です。だから、間違いなくシンボルツリーになるでしょう、私はすでにそれを構築し始めました。 .OnClickプロパティを読み取れないと、他のすべてが保持されます。私は、バイナリを解析するために何かを書く必要はないと期待しています... –

+0

実際に割り当てられた値は、(例えば関数や内部ハンドルなどのメモリポインタのように) 。 OKボタンの隣に非表示のテキストコントロールを追加し、OnClickを動的に変更したときはいつでもそれを更新します。または、固定のOnClick関数を使用して、そのテキストフィールドを読み取り、それに応じてリダイレクトします。 – SunKnight0

答えて

1

実際、コードは私には見えません。イベントプロシージャにVBA関数を割り当てる場合は、次のような構文を使用する必要があります。=()は、Accessが関数を呼び出すことを認識させるために必須です。

は、追加の考慮事項として、あなたはこのようなコードがあるクラスモジュール(のがObserverを呼びましょう)を持つことができます。

Private WithEvents ctlInterest As Access.Textbox 

Public Sub Init(TargetControl As Access.Control) 
    Set ctlInterest = TargetControl 
    With ctlInterst 
    If .OnClick = "" Then 
     .OnClick = "[Event Procedure]" 
    End If 
    End With 
End Sub 

Private ctlInterest_OnClick() 
    fnProcess() 
End Sub 

を、あなたはそのように状にクラスを展開することができます....同じ結果を得、そしてあなたが複数イベントハンドラで終わるだろう

Private objObserver As Observer 

Private Sub Form_Load() 
    Set objObserver = New Observer 
    objObserver.Init(Me.txtInterest) 
End Sub 

詳細についてはthisが参考になる場合があります。

関数式が可能であり、いつでも動的に割り当てることができるという事実に関連して、一般的にすべてのイベントハンドラの可能なエントリポイントを特定するコードパス解析が必要です。つまり、そのためにはRubberduckのパーサが必要です。静的なコードパス解析は計画されていますが、まだ実装されていないことに注意してください。

また、エラー処理のためにコールスタックトレースを作成することを意図している場合は、サードパーティのアドインを参照する必要があります。たとえば、市販の製品であるvbWatchDogは、その情報をVBAで提供することができます。

+0

動的割り当てでは、OnClickの現在の値は変更できますが、アプリケーションの実行中に現在の値がどのようなものかを確認する方法はありますか?そうすれば、少なくとも私はそれをファイルに記録することができます。私はあなたが正しいかもしれないと思う。良いスタックトレースユーティリティは、行く方法かもしれません。 vbWatchDogはエラーを発生させずにスタックのロギングをサポートしますか? –

+1

ちょうどそれを明確にする - それは動的ではありません - それは上に示した構文で、複数のVBAプロシージャによって処理することができます。もちろん、 '= fnProcess()'の構文を使用した場合は当てはまりませんが、それがわかっていればいいと思います。 RE:vbWatchDog、あなたはエラーをトリッピングする必要のないLiveCallStackを使うことができますが、例えば 'fnProcess'関数の中でおそらくどこかでコールスタックを読み込むコードを書く必要があります。 – this

1

これは、イベントの完全なコードを返します。そのイベントの中で1つのサブを使うだけなら、それはうまくいくはずです。

Public Sub TestModulePrinter() 
    Dim subName As String 
    With Forms("Order Entry").Controls("OK") 
     subName = "Private Sub " & .Name & "_OnClick()" 
    End With 
    Dim i As Long 
    Dim IsPrinting As Boolean 
    With Forms("Order Entry").Module 
     For i = 1 To .CountOfLines 
      If Not IsPrinting Then 
       If Trim(.Lines(i, 1)) = subName Then 
        IsPrinting = True 
       End If 
      Else 
       If Trim(.Lines(i, 1)) = "End Sub" Then 
        IsPrinting = False 
       Else 
        Debug.Print .Lines(i, 1) 
       End If 
      End If 
     Next i 
    End With 
End Sub 
+0

私は、特定のコントロールを変更することなく、コントロールの現在のOnClick機能を探しています。私は、OnClickの値がプログラムの他の場所に設定されていると仮定しています。 –

+1

@AlbertPerrien待って、これは一度限りのことですか?そうであれば、コントロールの 'OnClick'プロパティに'値が変更されたときにブレークする 'ウォッチ式を使用するといいでしょう。 – this

+0

これは本当にまともな提案です!そのプロパティをキャッチするエラーハンドラで設定すると、アプリケーション内のすべてのアクティビティを中断して記録することができます。それはコンパイル時にVBエディタによって設定されたものを処理しませんが、それは素晴らしいスタートです。 –

関連する問題