アフィリエイト広告を利用しています
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日以上新しい記事の更新がないブログに表示されております。

Build a Mobile Site
スマートフォン版を閲覧 | PC版を閲覧
Share by: