アフィリエイト広告を利用しています
Ad×Ad


Ad×Adは表示されるだけで報酬がもらえます。
以下から登録すると100ptもらえます。
 → アドアド -あなたの街の無料広告サイト-
検索
最新記事

広告

posted by fanblog

2016年06月19日

自動埋め込みツール公開

EXCEL 2007 VBAで、デバッグ用の関数をソースファイル(inoファイル)に埋め込むツールを作りましたので公開します。(EXCELでVBAを開き、UserFormに他のコントロールを配置して各イベントにコピペしてください。)

但し欠点が2つあります。
1.改行コードがLF→CRLFになる。→TeraPadで改行コードをCRLF→LF変更できます。
2.日本語が化けます。日本語の処理は、Arduino IDE上でやりましょう。
上記欠点を分かった上でお試しください。

ツールの本体は、UserFormに書きました。<選択>を押すとファイル選択のダイアログが開くのでinoファイルを選んでください。ファイルを開いたら、<挿入する>を押してください。そうすると保存するファイル名を聞かれるので適当な名前をつけてください。

debugPrint, debugRegPrint, breakPointの3つの関数呼び出しを、ターゲットのソースコードの関数定義の先頭行にコメント文として追加します。コメント文とした理由はターゲットのRAMに余裕がないかもしれないので、適宜コメントを外す方が実践的かなあと思ったからです。またdebugPrintは関数名を表示させるものなので引数の文字列に関数名を自動的に入れるようにしました。

デザイン
userForm

以下、ソースコードです。
debugPrintに渡す関数名は以下のように探すことにしました。
C言語の関数名は、'{' の前か前行にあります。ですがここでは'}'のある行かその前行だと決め打ちして作っています。ですのでうまくヒットしない場合もあります。また配列やif文、while文、for文、switch文は関数名ではないので除外します。まだ除外し忘れているものがあるかもしれません。


Option Explicit

Private Sub btnDeleteBreakPoint_Click()

End Sub

Private Sub btnGetFilePath_Click()
'参照ボタンがクリックされた

   Dim fType, prompt As String
   Dim fPath As Variant
   Dim ws As Worksheet
   Set ws = Worksheets("Sheet1")

   'ダイアログのタイトルを指定
   prompt = "inoファイルを選択して下さい"
   'ファイル参照ダイアログの表示
   fPath = Application.GetOpenFilename(fType, , prompt)

   If fPath = False Then
   'ダイアログでキャンセルボタンが押された場合は処理を終了します
       End
   End If

   'TextBox1にファイル名をセット
   TextBox1.Text = fPath

End Sub

Private Sub btnAddDebugPoint_Click()
'debugPrint(), debugRegPrint(),breakPoint()を追加する
   'ファイルを開く
   Dim strBuf As String
   Dim strArray() As String
   Dim pos As Integer
   Dim i As Long
   
   
   Open TextBox1.Text For Input As #1
   Line Input #1, strBuf
   
   'strBuf末尾にCRが含まれているかどうか判定
   pos = 1
   pos = InStr(pos, strBuf, vbLf)
   
   If pos = 0 Then
   '改行コードがCRLFの場合(切り出したstringには改行コードは含まれない為)
       ReDim Preserve strArray(0)      '既に1行読み込んでいる為
       strArray(0) = strBuf
       i = 1
       Do Until EOF(1)
           Line Input #1, strBuf       ' ファイルから一行読み込み
           ReDim Preserve strArray(i)  ' 配列長を変更
           strArray(i) = strBuf        ' 配列の最終要素に読み込んだ値を代入
           i = i + 1                   ' 配列の要素数を加算
       Loop
   Else
   '改行コードがLFの場合(VBAはLFを改行と見做さないのでinoファイル全体が1つの文字列になる)
       Dim tmp As Variant              'LFコードでsplitして格納
       tmp = Split(strBuf, vbLf)       'strBufをLFコードで区切りtmpに格納

       ReDim Preserve strArray(UBound(tmp))
       i = 0
       For i = 0 To UBound(tmp)
           strArray(i) = tmp(i)
       Next i
   End If
   
   Close #1
   
   
   Dim j As Long
   Dim funcName As String
  
   'strArray()の解析(関数名を取り出してdebugPrint文を追加)
   For i = 0 To 20000
       ''{'を含む行を見つける
       pos = InStr(1, strArray(i), "{")
       If pos = 0 Then
           '何もしない
       ElseIf pos >= 1 Then
           funcName = ""
           If checkString(strArray, i, funcName) = True Then
               '関数名の個所なのでdebugXXX()を挿入する
               '次の行からdebugXXX文を3行追加し、新strArray配列を作る
               ReDim Preserve strArray(UBound(strArray) + 3)    '配列要素を+3する
               For j = UBound(strArray) To i + 3 Step -1
                   strArray(j) = strArray(j - 3)
               Next j
               strArray(i + 1) = "/***********/    //debugPrint(""" & funcName & """);"
               strArray(i + 2) = "/*  DEBUG  */    //debugRegPrint(""*"",);"
               strArray(i + 3) = "/***********/    //breakPoint();"
               i = i + 4
           Else
               '関数名の個所ではなかったので何もしない
           End If
       End If
       If i = UBound(strArray) Then
           Exit For
       End If
   Next i
   
   '新しくファイルを作成する
   Open Application.GetSaveAsFilename(TextBox1.Text) For Output As #1
   For i = 0 To UBound(strArray)
       Print #1, strArray(i)
   Next i
   Close #1

End Sub

Private Function checkString(strArray() As String, strPointer As Long, funcName As String) As Boolean
   '関数名の個所かどうか判定する 関数名ならTrueを返す
   Dim pos As Integer
   Dim nameFlag As Boolean
   nameFlag = True
   
   pos = InStr(1, LTrim(strArray(strPointer)), "{")
   If pos = 1 Then
       Call getName(Trim(strArray(strPointer - 1)), funcName, nameFlag)
   ElseIf pos > 1 Then
       Call getName(Trim(strArray(strPointer)), funcName, nameFlag)
   End If
   
   checkString = nameFlag
  
End Function

Private Sub getName(funcString As String, funcName As String, nameFlag As Boolean)

   If InStr(1, funcString, "=") = 0 And InStr(1, funcString, "(") > 2 And InStr(1, funcString, "if") = 0 _
       And InStr(1, funcString, "switch") = 0 And InStr(1, funcString, "while") = 0 _
       And InStr(1, funcString, "for ") = 0 And InStr(1, funcString, "for(") = 0 Then

       '関数名である
       Dim tmp As Variant
       If InStr(1, funcString, "//") > 0 Then
           tmp = Split(funcString, "//")
           funcString = Trim(tmp(0))
       End If
       
       If InStr(1, funcString, "{") = 0 Then
           funcName = funcString
       Else
           tmp = Split(funcString, "{")
           funcName = Trim(tmp(0))
       End If
       
       nameFlag = True
   Else
       '配列名である(または関数の引数だけの行もかな?)
       nameFlag = False
   End If
   
End Sub

Private Sub btnDeleteDebugPoint_Click()
'debugPrint(), debugRegPrint(),breakPoint()を削除する


End Sub

Private Sub TextBox1_Change()

End Sub

Private Sub UserForm_Click()
'    UserForm1.Show (vbModeless)
End Sub




VBAから上記を直接実行させてもよいのですが、シートを開いたときにすぐに実行できるように、ボタンにUserFormをオープンするプロシージャを書いただけです。下記はお好みで決めてください。

デザイン
ボタン


Sub Macro1()
'
' Macro1 Macro
' Arduino IDEのソースコードにデバッグ用のコードを挿入するマクロ。
'
'

   UserForm1.Show (vbModeless)


End Sub

この記事へのコメント
コメントを書く

お名前: 必須項目

メールアドレス: 必須項目


ホームページアドレス: 必須項目

コメント: 必須項目

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/5166189
※ブログオーナーが承認したトラックバックのみ表示されます。

※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック
×

この広告は30日以上新しい記事の更新がないブログに表示されております。