A better block insert

A better block insert

Draftsman13
Contributor Contributor
867 Views
11 Replies
Message 1 of 12

A better block insert

Draftsman13
Contributor
Contributor

I need help once again.  I have a lisp routine to insert a dynamic block into a drawing.  This dynamic block contains mtext with stacked fractions.  Every now and then, the drawing will "lose" the fractions.  I think it may be the drawing containing the block gets inserted as a block and now I have two blocks referencing the same thing.  Is there a better way to insert/reference this block?  I want to keep it as an independent file so I can insert it into any drawing, so saving the block in my main file will not be a viable option.  Can utilizing layerstates be having some effect on this block.  I do have multiple layers in the block.  Here is my code for this operation and I have also included a copy of my block:

 

(defun c:sc1 (/ temperr *error* oldos oldor oldlayer p1 col) ; this starts the routine

(setq temperr *error*) ; saves *error*
(setq *error* myerr) ; sets the new error variable
(command-s "_.undo" "_mark") ; start of "undo" command

(graphscr)
(setvar "cmdecho" 0)
(setq oldos (getvar "osmode")) ; saves the current osnap settings
(setvar "osmode" 0) ; sets new osnap settings
(setq oldor (getvar "orthomode")) ; saves the current ortho setting
(setvar "orthomode" 1) ; turns the ortho on
(setq oldlayer (getvar "clayer")) ; saves the current layer

(command "_.-layer" "_set" "1ST_FL_NOTES" "") ; updates the current layer

(setq p1 (getpoint "\nSelect column location ")) ; asks user to select a point
(command "_.-insert" "1st hss col" p1 "" "" "") ; inserts col block

(setq col (entlast)) ; ties the block to the 'col' variable
(command "_.burst" col) ; burst the block

(setvar "osmode" oldos) ; sets the osnaps to previous settings
(setvar "orthomode" oldor) ; restores the ortho to previous setting
(setvar "clayer" oldlayer) ; sets the current layer to previous setting

(setq *error* temperr) ; restores original error

(princ)
) ; ends the command

 

This is a screen capture of what it looks like vs. what it should look like.

Capture.PNG

 

Any help would be appreciated because I hate doing the same thing multiple times.

 

0 Likes
868 Views
11 Replies
Replies (11)
Message 2 of 12

Sea-Haven
Mentor
Mentor

Try these couple of suggestions just set dwg path correct

 

(setvar 'clayer" "1ST_FL_NOTES" )

(if (= (tblsearch "block" "1st hss col") T)
(command "_.-insert" "1st hss col" p1 "" "" "") ; exists in dwg
(command "_.-insert" "c:\\mydegs\\1st hss col" p1 "" "" "") ; does not exist so bring in
)
0 Likes
Message 3 of 12

Draftsman13
Contributor
Contributor

Setting current layer to "1st_Fl_Notes" was written that way because it is supposed to create the layer if none existed in the drawing.  I have since found that to not be the case.

 

I like the idea of searching for the block before inserting, but my understanding was that if the block existed in the drawing, then the routine just used that one.  Is that not the case?  I have tried your coding, but cannot get it to work for some reason.  If I change the "\mydegs\" to the actual location of the file, it returns "invalid block name".  Also, it looks your check for the block existing is the same as my insert code, so I am not sure how that is a check.  Just trying to understand.  I do appreciate the input.

 

Not sure if it makes a difference, but I should mention I am working on ACAD 2016

0 Likes
Message 4 of 12

Anonymous
Not applicable

You can use the function Steal Lee-Mac 

a subfunction

 

;; Insert->Block
;; [STR] Nome do bloco

(defun Insert->Block (nome)
  (if (not (tblsearch "BLOCK" nome))
    (and (Steal "c:\\Block\\Block.dwg" (list (list "BLOCKS" (list nome)))) ;; << Location of your block
	 (command "_.Insert" nome pause 1 1 "" "_.Explode" "_Last" "")
    )
    (command "_.Insert" nome pause 1 1 "" "_.Explode" "_Last" "")
  )
)

Example of use:

 

(Insert->Block "Blockname")
0 Likes
Message 5 of 12

Draftsman13
Contributor
Contributor

Can you explain how I would use this?  Do I replace "BLOCK" with the name of the block I am looking for and I change 

"c:\\Block\\Block.dwg"

for the location on my hard drive?  is there anything else that needs to change?  How do I get my routine to activate the new defun?  If I make these changes and run the routine, it asks for a point and then exits the routine without inserting the block and without activating the error.

0 Likes
Message 6 of 12

Anonymous
Not applicable

This is just an example !!
I attached a screencast (Sorry it was too long)

And I don't know if this is what you're looking for   lol 😂

 

 

 

0 Likes
Message 7 of 12

Moshe-A
Mentor
Mentor

@Draftsman13  hi,

 

(myerr) function is missing.

to switch to other layer use "_make" option instead of "_set" this ensures layer creation if it not exist.

You insert a dynamic block with attribute and you BURST it, what's the point???

BURST is not a native command it's a lisp from express tools so you can invoke it like this: (c:burst) but in your lisp you can not feed your selection to burst's prompt select objects cause it's (ssget) which must be paused.

 

here is my comments in red.

 

Moshe

 

(defun c:sc1 (/ temperr *error* oldos oldor oldlayer p1 col) ; this starts the routine
(graphscr) ; this call should be the first (setq temperr *error*) ; saves *error* (setq *error* myerr) ; sets the new error variable

(setvar "cmdecho" 0) (command-s "_.undo" "_mark") ; start of "undo" command (command "_.undo" "_begin") (setq oldos (getvar "osmode")) ; saves the current osnap settings (setvar "osmode" 0) ; sets new osnap settings
(setq oldor (getvar "orthomode")) ; saves the current ortho setting (setvar "orthomode" 1) ; turns the ortho on

(if (setq p1 (getpoint "\nSelect column location ")) ; asks user to select a point
(progn (setq oldlayer (getvar "clayer")) ; saves the current layer (command "_.-layer" "_set" "1ST_FL_NOTES" "") ; updates the current layer
(command "_.-layer" "_make" "1ST_FL_NOTES" "") ; use make option
(command "_.-insert" "1st hss col" p1 "" "" "") ; inserts col block (setq col (entlast)) ; ties the block to the 'col' variable (command "_.burst" col) ; burst is not a native command it's lisp command from express tools
); progn ); if
(setvar "osmode" oldos) ; sets the osnaps to previous settings (setvar "orthomode" oldor) ; restores the ortho to previous setting (setvar "clayer" oldlayer) ; sets the current layer to previous setting (setq *error* temperr) ; restores original error (command "._undo" "_end")
(setvar "cmdecho" 1)
(princ) ) ; ends the command
0 Likes
Message 8 of 12

Draftsman13
Contributor
Contributor

@Moshe-A ,

I forgot to include the error code.  Your other suggestions make sense.  The "burst" command was a suggestion from a co-worker.  It was "explode" prior to that.  I store the dynamic block (SCOL-1) in a separate drawing (1st hss col).  The insert command is installing that drawing (1st hss col) as a block.  In order to get the dynamic block (SCOL-1) properties to work, I need to explode/burst the installed (1st hss col) block.  Hope that makes sense.  I like the idea of checking the drawing to see if the needed block is there, but at this point, I am unsure how to make that work.  I believe, if I can get the routine to use the block from the drawing instead of the stored drawing, I may be able to resolve the issue.

0 Likes
Message 9 of 12

Draftsman13
Contributor
Contributor

@Anonymous ,

That is how I thought it worked.  Thank you for the screencast.  Steal does not see the block I am looking for in the current drawing I have it in.  I will play with it a little more tonight, when I have time.  I see some of the potential for the steal command and how to use it now.

0 Likes
Message 10 of 12

Moshe-A
Mentor
Mentor

@Draftsman13 ,

 


I store the dynamic block (SCOL-1) in a separate drawing (1st hss col).  The insert command is installing that drawing (1st hss col) as a block.  In order to get the dynamic block (SCOL-1) properties to work, I need to explode/burst the installed (1st hss col) block.  Hope that makes sense.

no it does not make sense. if you want to insert SCOL-1 than why don't you store the block it self in library folder that is on the AutoCAD support files search path that will save you the need to check if the block is already inside.

burst and explode are not the same functions. 

 

your lisp is ok if you fix it according my comments plus wblock scol-1  out to library folder.

 

moshe

 

0 Likes
Message 11 of 12

Sea-Haven
Mentor
Mentor

You need to check also that "StealV1-6.lsp" is loaded, there may be a later version.

(if (not steal)(load "StealV1-6"))

(Steal "C:\\My Folder\\MyDrawing.dwg"  etc 

0 Likes
Message 12 of 12

dlanorh
Advisor
Advisor

Try this.

 

Read the CAPITALISED comments in the code and adjust accordingly

 

(defun rh:burst ( obj / o_lyr o_col a_lst objs p_lst d_lst)
  (cond ( (vlax-method-applicable-p obj 'explode)
          (setq o_lyr (vlax-get-property obj 'layer)
                o_col (vlax-get-property obj 'color)
          );end_setq
          (cond ( (= (vlax-get-property obj 'hasattributes) :vlax-true)
                  (foreach att (vlax-invoke obj 'getattributes)
                    (if (= :vlax-true (vlax-get-property att 'visible))
                      (setq a_lst (cons (list (vlax-get-property att 'tagstring) (vlax-get-property att 'textstring)) a_lst))
                    );end_if
                  );end_foreach
                  (foreach att (vlax-invoke obj 'getconstantattributes)
                    (if (and (= :vlax-true (vlax-get-property att 'visible))
                             (= :vlax-false (vlax-get-property att 'invisible))
                        );end_and
                        (setq a_lst (cons (list (vlax-get-property att 'tagstring) (vlax-get-property att 'textstring)) a_lst))
                    );end_if
                  );end_foreach
                )
          );end_cond
          (setq objs (vlax-safearray->list (vlax-variant-value (vla-explode obj))))
          (foreach e_obj objs
            (cond ( (= (vlax-get-property e_obj 'objectname) "AcDbAttributeDefinition")
                    (setq p_lst (assoc (vlax-get-property e_obj 'tagstring) a_lst))
                    (cond ( (= :vlax-true (vlax-get-property e_obj 'invisible))
                            (vla-delete e_obj)
                          )
                          (
                            (setq e_obj (rh:convert2txt e_obj (nth 1 p_lst)))
                            (if (= (vlax-get-property e_obj 'layer) "0") (vlax-put-property e_obj 'layer o_lyr))
                            (if (= (vlax-get-property e_obj 'color) 0) (vlax-put-property e_obj 'color o_col))
                          )
                    );end_cond
                  );end_cond attribute
                  (t
                    (if (= (vlax-get-property e_obj 'layer) "0") (vlax-put-property e_obj 'layer o_lyr))
                    (if (= (vlax-get-property e_obj 'color) 0) (vlax-put-property e_obj 'color o_col))
                  )
            );end_cond
          );end_foreach
          (vla-delete obj)
          (foreach att d_lst (vla-delete att))
        )
        (
          (alert (strcat "Cannot Explode " (substr (vlax-get-property obj 'objectname) 5) " Objects"))
        )
  );end_cond
);end_defun

(vl-load-com)

(defun c:sc1 (/ *error* sv_lst sv_vals c_doc c_spc path_to pt blk obj tmp) ; this starts the routine
  
  (defun *error* ( msg )
    (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc)) ;close open mark
    (mapcar 'setvar sv_lst sv_vals)                                             ;reset system variables to entry state
    (if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\nAn Error : " msg " occurred.")))
    (princ)
  );_end_*error*_defun
  
  (setq sv_lst (list 'cmdecho 'osmode 'clayer)  ;list of system variables to save (entry state)
        sv_vals (mapcar 'getvar sv_lst)         ;get the values and save them as a list
        c_doc (vla-get-activedocument (vlax-get-acad-object))
        c_spc (vlax-get-property c_doc (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace))
        path_to "d:/saves/"   ;; CHANGE THIS TO THE PATH TO "1ST HSS COL.DWG". USE "/" AS THE PATH SEPARATOR AUTOCAD UNDERSTANDS THE UNIX "/" SEPARATOR 
        blk "SCOL-1"          ;; CHANGE THIS TO THE ACTUAL BLOCK NAME IN THE DRAWING
  );end_setq

  ;; check if layer is in drawing. if not create it
  (cond ( (not (tblsearch "layer" "1ST_FL_NOTES")) (vlax-put (vla-add (vla-get-layers c_doc) "1ST_FL_NOTES") 'color 1))) ;; CHANGE THE FINAL 1 TO THE COLOUR YOU WANT FOR LAYER 1ST_FL_NOTES

  (mapcar 'setvar sv_lst '(0 0 "1ST_FL_NOTES"))
  
  (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc))
  (vla-startundomark c_doc)
  
  (setq pt (getpoint "\nSelect Column Location : ")) ; asks user to select a point
  
  ;; check if block is in drawing. if not import it
  (cond ( (not (tblsearch "block" blk))
          (setq tmp (strcat path_to "1st hss col.dwg"))           ;construct path string to drawing containing the block
          (command "_-insert" tmp pt "" "" "")                    ;insert the drawing (will automatically add the block inside to the block table)
          (command "_erase" (entlast) "")                         ;erase the last entity (drawing containing block)
        )
  );end_cond
  
  (setq obj (vla-insertblock c_spc (vlax-3d-point pt) blk 1 1 1 0))           ;Insert the block stored in variable blk at pt scale 1 rotation 0 (radians)
  (rh:burst obj)                                                              ;burst the object
  
  (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc)) ;close open mark
  (mapcar 'setvar sv_lst sv_vals)                                             ;reset system variables to entry state
  (princ)
);end_defun

I cannot open your attached drawing as I'm using AutoCAD 2012, so not tested using your block. Any problems let me know

I am not one of the robots you're looking for

0 Likes