69581


  1. 全てのfunction, subに一行ずつ `debug.print”function1通過”` と書く方法しかありませんか？
  2. 書くとしたら、正規表現置き換えの方法で、対応可能ですか？  
全エクスポートで、エディタの正規表現置換後、全インポートを予定しています。  
例) 全てのfunction, sub2行目に `debug.print "なまえ通過”` を挿入する方法がありますか?

  3. 他言語でも、アドバイスをいただけると、助かります。

よろしくお願いします。

[code]

    Sub Auto_Open()
    call aa
    end sub
    sub aa
    end sub
    sub bb
    end sub
    
[/code]

  * 通過したsubはAuto_Openとaa
  * 通過しなかったsubはbb


CC BY-SA 4.0
2020-08-13T08:26:04.120
69517
2020-08-15T16:04:08.607
2020-08-15T16:04:08.607
17199
17199
question
アルゴリズム vba awk graphviz
Excel VBA の1回の実行で、通過した通過しなかったfunction、subを分類する方法を教えて下さい


すべてのsubとfunctionの中にdebug.printを入れる以外にないと思います。

VBAのプログラム（Module)は、"ファイルのエクスポート"でテキストファイル(拡張子は".bas")に保存できますから、テキストファイルの中にdebug.printを挿入してゆけばいいでしょう。

だいたいの手順は、

・修正したいVBAプログラムのファイルを開く。（ファイルA)  
・修正したVBAプログラムを入れるファイルを生成する。 （ファイルB)

そして、以下の操作をファイルAのすべてのデータを読み終わるまで繰り返す。  
・ファイルAから１行読み出して、そこに"Sub"か"Function")が含まれていれば、  
・ファイルAから読み出した行と、debug.printの行をファイルBに追加する  
・"Sub"も"Function”も含まれていなければ、  
・ファイルAから読み出した行を、そのままファイルBに追加する

・ファイルBを閉じる。  
・ファイルのインポートで、ファイルBを読み込む。

＝＝＝  
プログラムはVBAに固執しないで、Pythonとか、テキストエディタのマクロ機能とか、使い慣れたもの・使いやすいものでやってください。

正規表現に精通されているのでは、正規表現でもかまわないと思います。


CC BY-SA 4.0
2020-08-14T01:25:19.567
69534
2020-08-14T01:25:19.567
217
69517
answer


Fumu 7さんの回答の実装例です。  
awkを使っています。WSLで確認しました。  
引数で指定したbasファイルのSubとFunctionの定義の後にdebug.printを埋め込みます。変換結果は元のファイルの先頭にDebug_を付加したファイルに書き込みます。  
書き込む内容はファイル名、行番号、定義の行です。  
※プロパティのアクセサは対象としていません。

【debug.print埋め込みスクリプト】

[code]

    #!/bin/sh
    conv_bas(){
        file=$1
        awk '{
            print $0
        }
        /^Sub/||/^Function/{
            sub(/\r/,"")
            printf("    debug.print(\"%s:%s:%s\")\r\n", FILENAME, FNR, $0);
        }
        ' ${file}
    }
    for file in $@
    do
        conv_bas ${file} > Debug_${file}
    done
    
[/code]

【実行例(抜粋)】

[code]

    Module11.bas:203:Function Left2Pos(left As Integer, width As Integer) As Integer
    Module11.bas:203:Function Left2Pos(left As Integer, width As Integer) As Integer
    Module11.bas:203:Function Left2Pos(left As Integer, width As Integer) As Integer
    Module11.bas:200:Function Pos2Left(pos As Integer, width As Integer) As Integer
    Module11.bas:203:Function Left2Pos(left As Integer, width As Integer) As Integer
    Module11.bas:200:Function Pos2Left(pos As Integer, width As Integer) As Integer
    Module11.bas:203:Function Left2Pos(left As Integer, width As Integer) As Integer
    　　　以下略
    
[/code]

* * *

このままでは集計が面倒です。  
呼び出し時に回数カウントし、集計結果を表示するデバッグ用のモジュールを作ってみました。

【集計モジュール】

[code]

    Option Explicit
    Dim debugCallCount As Object
    Sub DebugStartCallCont()
        Set debugCallCount = CreateObject("Scripting.Dictionary")
    End Sub
    Sub DebugRecordCallCont(Msg As String)
        debugCallCount(Msg) = debugCallCount(Msg) + 1
        
    End Sub
    Sub DebugPrintCallCont()
        Dim var As Variant
        Debug.Print ("==========================")
        Debug.Print ("Count:File:Line:Definition")
        Debug.Print ("==========================")
        
        For Each var In debugCallCount
            Debug.Print (debugCallCount.Item(var) & ":" & var)
        Next var
        Debug.Print ("==========================")
    End Sub
    
[/code]

【使い方】

集計を開始する処理の先頭に次のコードを記述します。

[code]

    Call DebugStartCallCont
    
[/code]

集計結果を表示したい箇所で次のコードを記述します。

[code]

    Call DebugPrintCallCont
    
[/code]

プロシジャの定義の後にDebugRecordCallContを記述します。  
以下のスクリプトで埋め込むのが簡単です。  
【DebugRecordCallCont埋め込みスクリプト】

[code]

    #!/bin/sh
    conv_bas(){
        file=$1
        awk '{
            print $0
        }
        /^Sub/||/^Function/{
            sub(/\r/,"")
            printf("    DebugRecordCallCont (\"%s:%s:%s\")\r\n", FILENAME, FNR, $0);
        }
        ' ${file}
    }
    for file in $@
    do
        conv_bas ${file} > Debug_${file}
    done
    
[/code]

【実行例】

[code]

    ==========================
    Count:File:Line:Definition
    ==========================
    1:Module11.bas:314:Sub MakeDiagram()
    1:Module11.bas:525:Sub Initialize()
    4:Module11.bas:531:Function RefOpt(name As String) As Variant
    10:Module11.bas:94:Sub RmSheet(xls As String, nm As String)
    16:Module11.bas:84:Function IsSheetExist(nm As String)
    6:Module11.bas:105:Sub AddWorkSheet(xls As String, nm As String)
    1:Module11.bas:500:Sub RmDiaShapes()
    1:Module11.bas:492:Sub RmShapes(nm As String)
    86:Module11.bas:148:Function ObjectProp(id As String) As TObject
    4:Module11.bas:265:Function CreateShape(sheet As Worksheet, fig_sheet As Worksheet, shape As String, id As String, pos As Integer, top As Integer) As String
    44:Module11.bas:165:Function FigProp(id As String) As TFig
    21:Module11.bas:197:Function GetBoxHeight(Title As String) As String
    21:Module11.bas:192:Function GetBoxWidth(Title As String) As String
    65:Module11.bas:200:Function Pos2Left(pos As Integer, width As Integer) As Integer
    20:Module11.bas:301:Function CreateCustomConnector(sheet As Worksheet, fig_sheet As Worksheet, beginObj As String, endObj As String)
    17:Module11.bas:251:Function CreateText(sheet As Worksheet, id As String, pos As Integer, top As Integer) As String
    55:Module11.bas:212:Function Name2No(ws As Worksheet, nm As String) As Integer
    7:Module11.bas:237:Function GetTopBrotherNo(nm As String) As Integer
    7:Module11.bas:224:Function GetParentNo(nm As String) As Integer
    58:Module11.bas:203:Function Left2Pos(left As Integer, width As Integer) As Integer
    =====================
    
[/code]


CC BY-SA 4.0
2020-08-15T11:59:33.227
69581
2020-08-15T11:59:33.227
35558
69517
answer