前回の
Bricscad VBAを使ってみよう[4] VBAの基本コード①
からの続篇です。
VBAを使用する(使用したい)目的は、条件分岐と繰り返し処理により複雑な処理が可能になり、多量のデーターを扱う場合でExcelとデーターのやり取りができることにあります。
今回は、条件分岐と繰り返しに関してですが、特に、VBAのコード作成で重要な「On Error Resume Next」を踏まえて検討しました。
1,条件分岐処理
複数の条件によって処理を分岐する場合、
IfステートメントとSelect Caseステートメントを用います。
1,Ifステートメント
===================
If A(評価1)Then
(処理1)
ElseIf A(評価2)Then
(処理2)
Elseif A(評価3)Then
(処理3)
Else
(それ以外の処理)
End If
===================
評価に使用する演算子
比較演算子
(例)
If A = 0 Then・・・・
等しい=、より大>、より小<、以上>=、以下<=、ではない<>
これは有りません><
And演算子
(例)
If A > 0 And B > 0 Then・・・・
Or演算子
If A > 0 Or B > 0 Then・・・・
2,Select Caseステートメント
Ifステートメントと同様に使える
===================
Select Case A
Case (評価1)
(処理1)
Case (評価2)
(処理2)
Else
(それ以外の処理)
End If
===================
Select Caseでは、toで範囲の指定や固定値のみの記述もでき、行数が多い程可読性が高い
===================
Select Case A
Case 0 to 10
(処理1)
Case 11 to 20
(処理2)
===================
Select Case A
Case 10
(処理1)
Case 20
(処理2)
===================
ここは、さらりと通り過ぎます^^
2,繰り返し処理
1,繰り返し処理
条件を満たすまで処理を繰り返す
Do ・・・Loopステートメント
と、・・・
回数を指定して処理を繰り返す
For・・・Nextステートメント
コレクションの各要素に対して処理を繰り返す
For Each・・・Nextステートメント
があります。
Exitステートメント
ループやプロシージャから抜けるときに使用します。
Exit (Do/For/Sub/Function)
2,On Error Resume Next
エラーが発生しても、無視して突き進む、On Error Resume Next は、VBAのコード作成に重要です。
プロシージャからExit Subする場合にESCキーを使用しますが、エラー処理が必須になります。
順を追って確認してみます。
下記コードは1回クリックして半径100の円を描きます。
Sub Sample_1() Dim insPt() As Double insPt = ThisDrawing.Utility.GetPoint(, "挿入点をクリック: ") Dim myCircle As AcadCircle Set myCircle = ThisDrawing.ModelSpace.AddCircle(insPt, 100) End Sub
円を一つだけ描いて終了します。
もう一度やろうと思って・・・再度実行・・・画面をクリック時に、気が変わってESCキーで終了・・・・するつもりが・・・
VBAのダイアログが、エラーですよ~と「Debug」ボタンを強調して出てきます。
実行時エラー -2147467259 (80004005)
GetPointオブジェクトのメソッドを失敗しました
Escキーのときに、GetPointがエラー番号-2147467259でストップしました。
このようにESCキー操作でエラー警告が出て停止して終了処理ができない状態になりました。
そこで、On Error Resume Next が必要になります。
On Error Resume Next は、
エラー発生時に時に、エラー発生行を飛び越えて次の行に進みます。
Sub Sample_2() On Error Resume Next Dim insPt() As Double insPt = ThisDrawing.Utility.GetPoint(, "挿入点をクリック: ") MsgBox Err.Number Dim myCircle As AcadCircle Set myCircle = ThisDrawing.ModelSpace.AddCircle(insPt, 100) End Sub
エラー行を無視して次に進んで、Msgboxが出てエラー番号が表示されました。
不特定の回数で繰り返し処理を行う場合は、Do・・・Loopステートメントを使用しますが、ループから抜ける時のESCキー操作時のエラーで、ストップせずに進ませるために、On Error Resume Next を使用します。
そして、このMsgBoxの代わりに、If Err Then・・・、If Err.number <> 0 Then・・・のエラー判定の処理が必要になります。
If Err Then Exit sub で終了することができますが、実際は終了時の行う処理を追加します。
On Error Resume Next ステートメントは、
エラーの原因となった行を無視し次の行に実行の制御を移し、実行はOn Error GoTo 0 まで中断されません。
On Error GoTo 0 ステートメントは、
プロシージャ内でのエラー処理On Error Resume Nextを無効にします。
Err オブジェクトのプロパティをリセットするので、 Err オブジェクトの Err.Clearメソッドと同じ効果があります。
3,Errオブジェクト
エラーの情報は、Errオブジェクトに格納されます。
Err オブジェクトの既定のプロパティは、Number です。
Numberプロパティはエラーの種類で割り振られた番号で、どんなエラーが発生したかを調べることができます。
Description プロパティは、エラーの簡単な説明で構成されます
ESCキー操作時は、Err.Number = -2147467259 でした。
エラーでない場合は、Err.Number = 0 です。
その他のエラー時にも、エラーの種類を識別する番号が格納されます。
Err オブジェクトのプロパティは、エラー処理ルーチン内の Exit Sub、Exit Function、Exit Property、または Resume Next ステートメントの後で 0 または長さ 0 の文字列 (“”) にリセットされます。
エラー処理ルーチン外で Resume ステートメントのいずれかの形式を使用した場合、Err オブジェクトのプロパティはリセットされません。 Err を明示的にリセットするには、Clear メソッドを使用できます。
4,エラー処理ルーチン
On Error ステートメントで、エラー処理ルーチンを有効にします。
エラーが発生した時・・・は、
If Err Then・・・もしくは、If Err.number <> 0 Then・・・
でエラー発生後に行う処理を記述します。
Sub Sample_3() Do On Error Resume Next Dim insPt() As Double insPt = ThisDrawing.Utility.GetPoint(, "挿入点をクリック: ") If Err.Number <> 0 Then If Err.Number = -2147467259 Then MsgBox "ESCキーが押されました" Exit Sub Else Exit Sub End If End If Dim myCircle As AcadCircle Set myCircle = ThisDrawing.ModelSpace.AddCircle(insPt, 100) On Error GoTo 0 Loop End Sub
連続処理が可能になり、ESCキーで終了できるようになりました。
3,エラー処理ルーチンでの分岐処理
前回の同心円作図で、追加する円の数をWin32APIを用いて、テンキーから取得しましたが、今回は、.Utility.GetReal と InputBox の2パターンで検討してみました。
ユーザーフォームを使用せずに、ESCキーで「同心円の数の設定」と「終了」を選択できるようにしました。
GetRealのテンキー入力の場合
ESCキーで、同心円:はい、終了:いいえ
無くてもいいが、テンキー入力の表示
ここでは、3を入力しEnter
入力時全角では入らないので、操作中に半角に切り替えてOK
Sub Sample_4() ''オートコンプリートの現在値を取得 Dim GetATComp As String GetATComp = ThisDrawing.GetVariable("AUTOCOMPLETEMODE") ''オートコンプリートを無効にする ThisDrawing.SetVariable "AUTOCOMPLETEMODE", "0" Do On Error Resume Next Dim insPt() As Double insPt = ThisDrawing.Utility.GetPoint(, "挿入点をクリック【ESCキー/終了or同心円】: ") If Err.Number <> 0 Then If Err.Number = -2147467259 Then Dim ErRet As VbMsgBoxResult ErRet = MsgBox("「はい:同心円設定」「いいえ:終了」", vbYesNo + vbQuestion) If ErRet = vbYes Then MsgBox "同心円の+数をテンキー入力", vbInformation Err.Clear Dim keynum As Long keynum = ThisDrawing.Utility.GetReal("テンキー入力/Enter:") Else ''終了する ''オートコンプリートの設定を戻す ThisDrawing.SetVariable "AUTOCOMPLETEMODE", GetATComp On Error GoTo 0 Exit Sub End If Else ''オートコンプリートの設定を戻す ThisDrawing.SetVariable "AUTOCOMPLETEMODE", GetATComp On Error GoTo 0 Exit Sub End If Else Dim myCircle As AcadCircle Set myCircle = ThisDrawing.ModelSpace.AddCircle(insPt, 100) ''円の間隔を文字高さの1/10にする Dim offsetObj As Variant, i As Long If keynum > 1 Then For i = 1 To keynum offsetObj = myCircle.Offset(100 / 10 * i) Next End If '作図図形範囲にZoom ThisDrawing.Application.ZoomExtents '図面を更新 ThisDrawing.Application.Update End If On Error GoTo 0 Loop End Subぜ
(注意点)
全角半角は自動で処理しませんので、半角を確認してください。
同心円用の数値入力時の入力値が特に2.3は、オートコンプリートで使えないので、システム変数の現在値を取得し変数に格納後、システム変数を”0”で無効にします。終了時に元の値に戻します。
オートコンプリートの現在値を取得
Dim GetATComp As String
GetATComp = ThisDrawing.GetVariable(“AUTOCOMPLETEMODE”)
オートコンプリートを無効にする
ThisDrawing.SetVariable “AUTOCOMPLETEMODE”, “0”
オートコンプリートの設定を戻す
ThisDrawing.SetVariable “AUTOCOMPLETEMODE”, GetATComp
使われる場合は、念のため 「AUTOCOMPLETEMODE」 の現在値を確認しておいてください。多分触っていなければ47です。
InputBoxからの入力の場合
InputBoxではオートコンプリートを無効にする必要はありません。
(BricsCADのコマンドバーでオートコンプリートが機能しています)
テンキー入力がInputBox入力に変りました。
コードもあっさりします。
Sub Sample_4() Do On Error Resume Next Dim insPt() As Double insPt = ThisDrawing.Utility.GetPoint(, "挿入点をクリック【ESCキー/終了or同心円】: ") If Err.Number <> 0 Then If Err.Number = -2147467259 Then Dim ErRet As VbMsgBoxResult ErRet = MsgBox("「はい:同心円設定」「いいえ:終了」", vbYesNo + vbQuestion) If ErRet = vbYes Then Err.Clear Dim keynum As Long keynum = InputBox("半角整数を入力", "同心円 + 数設定", "") Else ''終了する On Error GoTo 0 Exit Sub End If Else On Error GoTo 0 Exit Sub End If Else ・・・・以下同じ
上にあがるResumeやGoTo文も検討しましたが、どーしても前回描画の円をOffsetするのでやめました。
その他
繰り返し処理で、
Do ・・・Loopステートメント
Do Until・・・Loop
Do・・・Loop Until
Do While・・・Loop
Do・・・Loop While
や
For・・・Nextステートメント
For Each・・・Nextステートメント
がありますが、
とくにここではこれ以上は触れませんが、
コレクションの各要素に対して処理を繰り返す
For Each・・・Nextステートメントは、画層リスト取得にちょうどぴったりです。
画層数は図面ごとに異なります。 Layers コレクションから全画層名を取得しComboBoxに格納します。
Private Sub UserForm_Initialize() '全画層名をComboBoxLayに格納 Dim LayObj As AcadLayer For Each LayObj In ThisDrawing.Layers ComboBoxLay.AddItem LayObj.Name Next ComboBoxLay.Value = ThisDrawing.ActiveLayer.Name End Sub
ユーザーフォームで、わざわざ現在層を変える必要もないんですが・・
Private Sub CmdCancel_Click() Unload Me End Sub Private Sub CmdOK_Click() ''変数を宣言 Dim CurLay, SelLay As String ''現在画層名 CurLay = ThisDrawing.ActiveLayer.Name ''選択画層インデックス SelLay = ComboBoxLay.List(ComboBoxLay.ListIndex) ThisDrawing.SetVariable "CLAYER", SelLay MsgBox "現在画層を" & SelLay & "に変更しました" End Sub Private Sub ComboBoxLay_Change() With ComboBoxLay SelLay = .ListIndex End With End Sub Private Sub UserForm_Initialize() '全画層名をComboBoxLayに格納 Dim LayObj As AcadLayer For Each LayObj In ThisDrawing.Layers ComboBoxLay.AddItem LayObj.Name Next ComboBoxLay.Value = ThisDrawing.ActiveLayer.Name End Sub
今後の予定は・・・
Excelとの連携です。
VBAはExcelのVBAで数字を扱うことはしていましたので、VBA自体の構文には特に違和感は有りません。しかし、BricsCADの作図でVBAの利用は初めての取り組みで、しばらくは下調べに時間を費やしていました。
調べだすと、どんどんと広がってキリがなくなりますが、取り敢えずは必要そうなものを使えるようにしていけば、塵も積もれば山となりますね。
BricsCAD VBAを使ってみよう INDEX
BricsCAD VBAを使ってみよう[1] VBAのインストール
BricsCAD VBAを使ってみよう[2] UserFormその1
「BricsCAD VBA 」Creating UserForm
BricsCAD VBAを使ってみよう[3] UserFormその2
「BricsCAD VBA 」SerialNumber drawing with UserForm
BricsCAD VBAを使ってみよう[4] VBAの基本コード①
BricsCAD VBAを使ってみよう[5] VBAの基本コード②
BricsCAD VBAを使ってみよう[6] Excelとの連携①
「BricsCAD VBA to Excel」Get_CoordinateValues
BricsCAD VBAを使ってみよう[7] Excelとの連携②
「Excel VBA to BricsCAD」Get_Area
BricsCAD VBAを使ってみよう[8] Excelとの連携②-2
「Excel VBA to BricsCAD」Draw_ChannelSteel
BricsCAD VBAを使ってみよう[9] TABLEの自動作成と値入力
「BricsCAD VBA 」AutomaticCreation of TABLE
BricsCAD VBAを使ってみよう[10] Excelとの連携②-3
「Excel VBA to BricsCAD」SerialNumber_Ⅱ
BricsCAD VBAを使ってみよう[11] Excelとの連携②-4
「Excel VBA to BricsCAD」Draw_Rectang
BricsCAD VBAを使ってみよう[12] Excelとの連携②-5 指定画層にOffset
「Excel VBA to BricsCAD」Continuous Offset to Specified Layer
BricsCAD VBAを使ってみよう[13] Excelとの連携②-6 指定画層にHATCH
「Excel VBA to BricsCAD」Continuous Hatch to Specified Layer
以下検討中です。
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
「この特集記事の内容につきましては、
こちらの環境のみの検討結果です。
動作保証は出来かねますため、ご参考
資料としてお扱いください。
Windows10(64bit)
BricsCAD pro V20(64bit)
Office2019(64bit)
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇