Sponsored links

【AutoLISP エラー処理】UNDO[元に戻す] – [開始(BE)] [終了(E)]

Sponsored links
AutoLISP
Sponsored links

AutoCADコマンドUNDO[元に戻す] の[開始(BE)] と [終了(E)] を前後に入れることでプログラム内で行った操作が1つのセットになります。

しかし、エラー中断も想定しておかないと、 プログラム最後の[終了(E)] が実行されずに、予期せぬ操作がセットになってしまうことも。

Sponsored links

UNDO[元に戻す] – [開始(BE)] [終了(E)]

AutoCADコマンドUNDO[元に戻す]は、コマンド操作を取り消すコマンドです。
恐らく、多くの人が、ショートカット「ctrl」+「Z」でしているアレです。

このコマンドには、[開始(BE)] [終了(E)]というオプションがあって、一連の操作をセットにできます。UNDO一回でそのセットになっているすべての操作が元に戻ります。

AutoLISPプログラムに取り入れたUNDO活用例

(defun c:Test1 (/ r)
  (setq r 10)
   (repeat 10
     (command-s "._circle" "0,0,0" r "")
     (setq r (1+ r))
   );repeat
(princ))

これは、円が10個、原点 (0,0,0) に現れるだけのコマンドです。
コマンド名はTest1です。試してみてください。

そして、「ctrl」+「Z」、リボンやメニューバーのアイコンクリックなど、いつもしている方法でUNDO[元に戻す]してみてください。

このコマンドは、円コマンドを10回繰り返したので、消すまでにUNDO[元に戻す]が10回必要です。

しかし、UNDO[元に戻す]のオプション[開始(BE)]と[終了(E)]を加えることで、一度のUNDOで元に戻すことができます。

UNDO[元に戻す]のオプション[開始(BE)]と[終了(E)]

コマンドUNDO[元に戻す]には、一連の操作を1つのセットにする[開始(BE)]と[終了(E)]というオプションがあります。

それを先ほどのコマンドTest1に加えたものがこちらです。

(defun c:Test1-ud (/ r)
(command-s "._UNDO" "_BE") ;UNDO[元に戻す] [開始(BE)]
 (setq r 10)
   (repeat 10
     (command-s "._circle" "0,0,0" r "")
     (setq r (1+ r))
   );repeat
	(command-s "._UNDO" "_E") ;UNDO[元に戻す] [終了(E)]
(princ))

コマンド名は、Test1-ud です。
こちらも読み込んで試してみてください。今度はAutoLISPプログラムで行った操作が1つのセットになっているので、一度のUNDOですべての円が消えます。

エラー中断すると。。。

しかし、このコマンドでエラー中断があると、最後の(command-s “._UNDO” “E”)、セットの終了が実行されないので、予期せぬ操作がセットになってしまう可能性があります。

UNDO[元に戻す] – [開始(BE)] [終了(E)]をAutoLISPプログラムに組み入れるときは、エラー処理も加えましょう。

エラー処理例

AutoLISPプログラム

(defun c:test2  (/ r)
   
   (setq OldErr *error*);標準エラー処理を保存
   (setq *error* JagaERR);エラー処理をJagaERRにする
   	(command-s "._UNDO" "_BE") ;UNDO[元に戻す] [開始(BE)]
;-------------------------------------------------------------------  
   (setq r 10)
   (repeat 10
     (command-s "circle" "0,0,0" r "")
     (setq r (1+ r))
   );repeat
   
;-------------------------------------------------------------------
    	(command-s "._UNDO" "_E") ;UNDO[元に戻す] [終了(E)]
    (setq *error* OldErr);エラー処理を戻す
(princ))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun JagaERR (msg)
  (command-s "._UNDO" "_E") ;UNDO[元に戻す] [終了(E)]
  (command-s "._UNDO" "1") ;UNDO[元に戻す] 1 回
  (setq *error* Olderr)  ;エラー処理を戻す
  (princ "/nJagaErr: ") ;JagaErrが実行されたか確認するためJagaErr: を表示
  (princ msg) ;AutoCADからのエラーメッセージを表示する 
(princ));defun	
Jagaimo
Jagaimo

例なので、test JagaERR など、他記事と同じコマンド/関数名を使っています。
同じ名前のコマンド/関数名を読み込むと上書きされるから、実際にいろいろ作るときには名前を工夫して、同じ名前のコマンド/関数が無いようにしてね!!

コマンドの最初にする処理

(setq OldErr *error*) (setq *error* JagaERR)

*error*の設定を変数OldErrに保存し、*error*に自作エラー処理関数のJagaERRを入れます。

(command-s “._UNDO” “_BE”)

AutoCADコマンドのUNDO[元に戻す] とオプション [開始(BE)]で、一連の操作のセットを開始します。

コマンドの最後にする処理

(command-s “._UNDO” “_E”)

AutoCADコマンドのUNDO[元に戻す] とオプション[終了(E)]で、一連の操作のセットを終了します。

(setq *error* OldErr)

*error* に、最初に変数OldErrに入れておいた情報を入れて、最初の状態に戻します。

(setq *error* nil) で、空にすれば、AutoLISP標準の設定に戻ります。
しかし、人によってはカスタマイズしたエラー処理を使っている場合もあるので、変数に入れて保存しておいて最後/エラー時に戻すほうが無難です。

自作エラー処理関数

この部分が、今回使う自作エラー処理JagaErrです。
エラー中断時にこのエラー処理が実行されます。

(defun JagaERR (msg)
  (command-s "._UNDO" "END") ;UNDO[元に戻す] [終了(E)]
  (command-s "._UNDO" "1") ;UNDO[元に戻す] 1 回
  (setq *error* Olderr)  ;エラー処理を戻す
  (princ "/nJagaErr: ") ;JagaErrが実行されたか確認するためJagaErr: を表示
  (princ msg) ;AutoCADからのエラーメッセージを表示する 
(princ));defun	

(command-s “._UNDO” “_E”)

AutoCADコマンドのUNDO[元に戻す] とオプション[終了(E)]で、一連の操作のセットを終了します。

(command-s “._UNDO” “1”)

これはコマンドが通常に終った時には無い部分です。
コマンドUNDO[元に戻す]で1つ前に戻しています。

このプログラム全体が、UNDO[元に戻す] – [開始(BE)] [終了(E)]で一つの操作セットになっているので、コマンド実行前戻った状態になります。

しかし、エラー中断されたとき、どこでエラーが起きたのか知りたい場合はこの処理は入れない方がいいでしょう。

(setq error Olderr)

コマンドの最後に行う、”エラー処理設定を最初の設定に戻す” を実行します。

エラー中断させてエラー処理を試そう

エラー処理を入れたコマンドtest2のエラーが起きるバージョンです。
コマンド名はtest2-Errです。

(defun c:test2-Err  ( / r)
   
   (setq OldErr *error*);標準エラー処理を保存
   (setq *error* JagaERR);エラー処理をJagaERRにする
   	(command-s "._UNDO" "_BE") ;UNDO[元に戻す] [開始(BE)]
;------------------------------------------------------------------- 
  
 (setvar "osmode" 0) ; Oスナップオフ
   (setq r 10)
   (repeat 10
     (command-s "circle" "0,0,0" r "")
      (setq r (1+ r))
     (if (= r 18) (progn (alert "エラー") (alert 1))) ;!!!エラー!!!  
   );repeat
   
;-------------------------------------------------------------------
    	(command-s "._UNDO" "_E") ;UNDO[元に戻す] [終了(E)]
    (setq *error* OldErr);エラー処理を戻す
(princ))

実行すると、途中でエラーと表示されたアラートボックスが出てきます。

そして、エラー中断するとすべての円が消えて元通りになります。
(setvar “osmode” 0) でシステム変数を変えてオブジェクトスナップをオフにしていますが、それも元に戻ります。

コマンドラインを見ると
JagaErr: 引数のタイプが間違っています: stringp 1
(JagaErr: bad argument type: stringp 1)
と出てきて、無事にJagaErrが実行されたことがわかります。

エラーの内容

興味がある方向けに、エラー処理を試すためにわざと起こしたエラーの内容です。

(if (= r 18) (progn (alert “エラー”) (alert 1)))で、9個目の円を描く前に、エラーメッセージをだして、(alert 1)を入れています。

AutoLISP関数 alertに渡す引数のタイプは文字列です。しかし、ここではダブルクォーテーション””が無い、数字の1を渡しているので、「引数のタイプが間違っています」というエラーになります。
stringp 1 は、文字列(string)が欲しいところに1が入ってるよ!と言う意味です。
(alert “1”) とすれば、文字列になるので、1 とメッセージボックスがでてきてエラーは起きません。

文字列 ”1” と数値 1 の違いについてはコチラの記事を参考にしてください。

注意点

コマンドによっては、例えば、図形の色を変更するコマンドを(while T ….. ) で繰り返す。コマンドで、(while T ….. )の外に[開始(BE)] [終了(E)]があると、繰り返した操作がすべて一つのセットになって、UNDOですべて消えてしまいます。

さらに、(while T ….. )は、ESCでキャンセルする以外コマンドを終えることができませんが、ESCでユーザーがキャンセルする場合も、エラー処理関数が実行されます。

その場合、エラー処理に、(command-s “._UNDO” “1”)で、戻すコマンドが入っていると、予期せぬ物まで消えてしまいます。
while で繰り返しているコマンドに限らず、コマンドの途中、ESCでキャンセルするのは誰もがすることだと思うので、その状況も考えてプログラムしましょう。

普段よく使う、馴染みあるコマンドUNDO。一見シンプルですが、
エラー処理にUNDOが必要かどうか、[開始(BE)] [終了(E)]を置く位置、エラー中断時に戻した方がよいのか。などなど、
状況に合わせて考える必要があります。

まとめ

  • 通常、AutoLISPプログラムに出てきた操作はUNDO[元に戻す]時、一つ一つ戻すことになる。
  • UNDO[元に戻す] – [開始(BE)] [終了(E)]を組み入れることで、一連の操作をセットにして、作業をやり直すのきに、1回のUNDO[元に戻す]で1操作セット戻せる。
  • UNDO[元に戻す] – [開始(BE)]をしておいて、[終了(E)]まで行かないままエラー中断すると、予期せぬ操作セットを作る可能性があるので、UNDO[元に戻す] – [開始(BE)] [終了(E)]を組み込むならエラー処理するべき。
  • UNDO[元に戻す]自体が必要か、 [開始(BE)]と [終了(E)]の位置、元に戻すをエラー処理にいれた方がいいかなどなど、プログラムや好みに合わせて熟考した方がいい。

関連記事

UNDOを使ったコマンド例です。

各レイアウトを保存する時に、レイアウト一つ以外全部消して別名保存して、また最初に戻して次のレイアウト一つ残して全部消して別名保存してまた戻して、、、を繰り返しています。
レイアウトを消す作業が入っているので途中でエラーが起きた時に最初に戻す処理は必須です。

ブロックをたくさん挿入するコマンドで一つ一つ戻すのが大変なので、動作を一つにまとめています。

Comments