Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Change block layer after insertion

20 REPLIES 20
Reply
Message 1 of 21
msarqui
1450 Views, 20 Replies

Change block layer after insertion

Hello!

 

I am wondering if is possible to have a lisp routine to:

 

After use the INSERT command, the routine will automatically change the layer of the inserted block to a specific layer according of its name.

 

i.e.

Step 1 : I will insert a block named Block A using the normal autocad INSERT command (I do not want to insert the block without the Insert window dialog box)

Step 2 : After the insertion, the routine will select the last insertion (or the last object, or any other best way to select this block and will take it's name)

Step 3 : The routine has a list that says:

              (If the last insertion (or object) is named Block A, put it in the layer Layer A with color Bylayer and linetype Bylayer)             

              (If the last insertion (or object) is named Block B, put it in the layer Layer B with color Bylayer and linetype Bylayer)

              and so on... I can make the approprieated list by myself folowing my standards.

 

I think it will be nice to avoid an error if the block is not in the list. So:

              (If the last insertion (or object) name is not in the list, do nothing)

 

To finish, it will be nice to create the layer if it does not exist. Also, Unlock, Thaw and Turn on the layer if it's Locked, Frozen or Off.

 

This was the logical way I imagined, but you can improve it as you wish.

 

Thanks for help!

20 REPLIES 20
Message 2 of 21
Kent1Cooper
in reply to: msarqui


@msarqui wrote:

....a lisp routine to:

 

After use the INSERT command, the routine will automatically change the layer of the inserted block to a specific layer according of its name.

 

i.e.

Step 1 : I will insert a block named Block A using the normal autocad INSERT command (I do not want to insert the block without the Insert window dialog box)

Step 2 : After the insertion, the routine will select the last insertion (or the last object, or any other best way to select this block and will take it's name)

Step 3 : The routine has a list that says:

              (If the last insertion (or object) is named Block A, put it in the layer Layer A with color Bylayer and linetype Bylayer)             

              (If the last insertion (or object) is named Block B, put it in the layer Layer B with color Bylayer and linetype Bylayer)

              and so on... I can make the approprieated list by myself folowing my standards.

 

I think it will be nice to avoid an error if the block is not in the list. So:

              (If the last insertion (or object) name is not in the list, do nothing)

 

To finish, it will be nice to create the layer if it does not exist. Also, Unlock, Thaw and Turn on the layer if it's Locked, Frozen or Off.

....


You can have the dialog box by using (initdia) before the Insert.  You don't need to extract the name from the inserted Block, but can get it from the INSNAME System Variable, which will hold the name of the Block just Inserted.  And you don't need to do the (if) approach to the determination of the appropriate Layer name, but can work with corresponding positions in two lists, of Block names and of Layer names.  The Layer command can ensure the Layer exists and is thawed, unlocked and on, without having to check for any of those things.

 

A quickie, minimally tested:

 

(defun C:IBL (/ blist bname blay); = Insert Block on appropriate Layer
  (initdia)
  (command "_.insert")
  (while (> (getvar 'cmdactive) 0) (command pause)); allowing use of options
  (setq
    blist '("BLOCK A" "BLOCK B" "BLOCK C" "BLOCK D")
      ;; do all capitalized in blist; (strcase) below will make
      ;; sure User's entry, if typed, is not case-sensitive
    bname (strcase (getvar 'insname))
  ); setq
  (if (member bname blist)
    (progn ; then
      (setq blay
        (nth
          (vl-position bname blist)
          '("Layer A" "Layer B" "Layer C" "Layer D")
        ); nth & blay
      ); setq
      (command
        "_.layer" "_thaw" blay "_make" blay "_unlock" blay ""
        "_.chprop" (entlast) "" "_layer" blay "_color" "BYLAYER" "_ltype" "BYLAYER" ""
      ); command
    ); progn
  ); if [no else argument]

); defun

 

You could add things like saving the current Layer at the beginning and returning to it afterwards, error handling, and all the other usual stuff.  You could also make it more sophisticated to test whether the User actually went through with the Insertion -- if they don't [e.g. pick Cancel in the Insert dialog box], and if the last Block that happens to have been inserted is one whose name is in the list, it will change the Layer of whatever was last drawn, whether or not it's a Block at all, let alone whether it's one with the right name.

Kent Cooper, AIA
Message 3 of 21
msarqui
in reply to: Kent1Cooper

Hi Kent,

 

Thanks for the tips and the routine. I learned some interesting things with it.

 

I noticed you put the color and linetype to “bylayer” for all. I'm wondering if it would be possible to do this separately. Let me explain: not all blocks will be “bylayer”. Some of them will have different colors and lynetypes.

 

Also, your “list” approach mades me see my problem in a different point of view. I think the following will be more interesting:

 

If the inserted block is in the (list 1)

Put it on the “layer 1” with color “bylayer” and linetype “bylayer”.

If the inserted block is in (list 2)

Put it on the “layer 2” with color “1” and linetype “bylayer”.

If the inserted block is in (list 3)

Put it on the “layer 3” with color “120” and linetype “hidden”.

and so on...

 

I think this will be more flexible and easier because of the large number of blocks and possibilities that I have.

 

So, thanks for your time.

Message 4 of 21
pbejse
in reply to: msarqui

Would you rather use a command reactor msarqui?

 

IF this is going to be a permanent thing with ALL of your drawings. I would suggest loading the required Layers/Linetypes and what not on your startapp suite.

 

I can add the loading on a reactor but by following my suggestion it will require less codes for testing the existence of the those listed above.

 

What say you msarqui?

 

Message 5 of 21
Kent1Cooper
in reply to: msarqui


@msarqui wrote:

.... 

I noticed you put the color and linetype to “bylayer” for all. I'm wondering if it would be possible to do this separately. Let me explain: not all blocks will be “bylayer”. Some of them will have different colors and lynetypes.

 

Also, your “list” approach mades me see my problem in a different point of view. I think the following will be more interesting:

 

If the inserted block is in the (list 1)

Put it on the “layer 1” with color “bylayer” and linetype “bylayer”.

If the inserted block is in (list 2)

Put it on the “layer 2” with color “1” and linetype “bylayer”.

If the inserted block is in (list 3)

Put it on the “layer 3” with color “120” and linetype “hidden”.

and so on...

 

I think this will be more flexible and easier because of the large number of blocks and possibilities that I have.

....


I set it up for all of them to be Bylayer for color and linetype only because that's what your original Step 3 asked for.

 

In the more complicated scenario you describe, I would suggest using (cond) rather than (if), because it will stop looking for which list a Block name is in once it locates it.

 

(cond

  ((member bname list1)

    (command "_.chprop" (entlast) ""

Kent Cooper, AIA
Message 6 of 21
msarqui
in reply to: pbejse

Hello

 

I do not know reactors, so I looked here http://www.afralisp.net/visual-lisp/tutorials/reactors-part-1.php and I tried to learn a bit. I'm not sure if I understand what they are. I imagine that a reactor is an automatic action and permanent for all projects I start, or for each determined decision I make.

 

Your question made me great doubts about the best way to proceed.

For every new project I start, I use a template that has all the layers and linetypes preloaded. But if at some point I have accidentally purged a layer, the routine would have to create it again. My set list template has no more than 20 layers and 6 linetypes.
My logical thinking is not to use the reactor. If I could have a basic routine with only two or three actions, maybe something like this:

 

Action 1 - (If the last inserted block is in the “list 1”, create “layer 1” and put the last inserted block on the "layer 1" with color “Bylayer” and linetype “Bylayer”)

Action 2 – (If the last inserted block is in the “list 2”, create “layer 2”, load linetype “Hidden” and put the last inserted block on the "layer 2" with color “1” and linetype “Hidden”)

Action 3 – (If the last inserted block is not on any list, do nothing)

 

So, like this I can go adding new actions or adjusting old ones according to my needs. And I think it will be more flexible to me.

I hope my explanation will help because my mind is blowing... hahaha.

 

Thanks

Message 7 of 21
msarqui
in reply to: Kent1Cooper

Hi Kent,

 

You're correct. It was my wish in Step 3. That was my mistake because I did not explained myself well. Actually, not all blocks will be bylayer. Some will have different colors and linetypes.


I will try your suggestion with the (cond). I return later with the results.


Thank you very much

Message 8 of 21
Kent1Cooper
in reply to: msarqui


@msarqui wrote:

.... 

I noticed you put the color and linetype to “bylayer” for all. I'm wondering if it would be possible to do this separately. Let me explain: not all blocks will be “bylayer”. Some of them will have different colors and lynetypes.

 

.... I think the following will be more interesting:

 

If the inserted block is in the (list 1)

Put it on the “layer 1” with color “bylayer” and linetype “bylayer”.

If the inserted block is in (list 2)

Put it on the “layer 2” with color “1” and linetype “bylayer”.

If the inserted block is in (list 3)

Put it on the “layer 3” with color “120” and linetype “hidden”.

and so on...

....


[[EDIT: Sorry about my previous uncompleted Reply -- I don't know how that went out accidentally.  Here's the broader treatment (but all untested).]]

 

I had it make them all Bylayer as to color and linetype only because that's what your original Step 3 asked for in both sample lines [it didn't indicate that those might be different for other possibilities].

 

For the more complicated scenario you describe, (cond) is the way to go, rather than a series of (if) functions, because (cond) will stop testing for membership in further lists once it finds a list that the Block name is in, whereas a series of (if)'s will be required to keep checking even after it's done what it needs to do.  After the insertion:

 

(cond

  ((member bname list1)

    (command "_.chprop" (entlast) "" "_layer" "Layer 1" "_color" "bylayer" "_ltype" "bylayer" "")

  ); end list1 condition

  ((member bname list2)

    (command "_.chprop" (entlast) "" "_layer" "Layer 2" "_color" 1 "_ltype" "bylayer" "")

  )

  ((member bname list3)

    (command "_.chprop" (entlast) "" "_layer" "Layer 3" "_color" 120 "_ltype" "hidden" "")

  )

  .... and so on ....

); cond

 

Come to think of it, you could probably shorten that a little by not repeating the first part of the CHPROP command every time:

 

(command "_.chprop" (entlast) "" "_layer"); common to all

(cond

  ((member bname list1)

    (command "Layer 1" "_color" "bylayer" "_ltype" "bylayer" "")

  ); end list1 condition

  ((member bname list2)

    (command "Layer 2" "_color" 1 "_ltype" "bylayer" "")

  )

  ((member bname list3)

    (command "Layer 3" "_color" 120 "_ltype" "hidden" "")

  )

  .... and so on ....

); cond

 

Or, better yet, you could use multiple lists, and spell out a CHPROP command only once, which might really make the overall code shorter if there are a lot of possibilities:

 

(setq

  bclass ; = Block CLASSification by list number

    (cond

      ((member bname list1) 1)

      ((member bname list2) 2)

      ((member bname list3) 3)

      ((member bname list4) 4)

      ((member bname list5) 5)

    ); cond & bclass

  clist '(0 "bylayer" 1 120 "bylayer" 251); = Color LIST

  ltlist '(0 "bylayer" "bylayer" "hidden" "phantom" "continuous"); = LineType LIST

); setq

(command "_.chprop" (entlast) ""

  "_layer" (strcat "Layer " (itoa bclass)); construct Layer name

  "_color" (nth bclass clist); find that category's color

  "_ltype" (nth bclass ltlist); find that category's linetype

  "" ; finish CHPROP

); command

 

The zeros at the beginnings of the clist and ltlist are just place-holders for the position in the list that will never be called on, because of the way (nth) works -- they could be anything at all [your mother's maiden name, pi, etc.].

Kent Cooper, AIA
Message 9 of 21
Kent1Cooper
in reply to: Kent1Cooper

I left out the Layer part [other than changing the Block to it]....

 

(setq

  bclass ; = Block CLASSification by list number

    (cond

      ((member bname list1) 1)

      ((member bname list2) 2)

      ((member bname list3) 3)

      ((member bname list4) 4)

      ((member bname list5) 5)

    ); cond & bclass

  clist '(0 "bylayer" 1 120 "bylayer" 251); = Color LIST

  ltlist '(0 "bylayer" "bylayer" "hidden" "phantom" "continuous"); = LineType LIST

  blay (strcat "Layer " (itoa bclass)); construct Block LAYer name

); setq

(command

  "_.layer" "_thaw" blay "_make" blay "_unlock" blay ""

  "_.chprop" (entlast) ""

    "_layer" blay

    "_color" (nth bclass clist); find that category's color

    "_ltype" (nth bclass ltlist); find that category's linetype

    "" ; finish CHPROP

); command

 

Kent Cooper, AIA
Message 10 of 21
pbejse
in reply to: msarqui


@msarqui wrote:

Hello @pbejse

 

I do not know reactors, so I looked here http://www.afralisp.net/visual-lisp/tutorials/reactors-part-1.php and I tried to learn a bit. I'm not sure if I understand what they are. I imagine that a reactor is an automatic action and permanent for all projects I start, or for each determined decision I make.

 

Your question made me great doubts about the best way to proceed.

For every new project I start, I use a template that has all the layers and linetypes preloaded. But if at some point I have accidentally purged a layer, the routine would have to create it again. My set list template has no more than 20 layers and 6 linetypes.

 

So, like this I can go adding new actions or adjusting old ones according to my needs. And I think it will be more flexible to me.

I hope my explanation will help because my mind is blowing... hahaha.

 

Thanks


 

True.

 

No worries msarqui, i'm just offering an alternative. i would prefer layers and linetypes are pre-loaded, but its not a big deal. it only means more coding. One good thing about reactor is you dont have to remember a particular function name to use it. Holler If you ever decide to take the path of reactors and i'll write a quick one for you.

 

GTG Cheers

 

Message 11 of 21
msarqui
in reply to: pbejse

Hi,

 

After a full day of hard work, mistakes, research, learning and more, I got something that works for what I need. I used the base of the second Kent's routine and added some things to fit in what I needed.

I tested it and it works!!!!!!!!
What do you think?

 

(defun C:IBL (/ currentlayer list1 list2 list3 L1 L2 L3 LT1 LT2 LT3 lt bname); = Insert Block on appropriate Layer
(setq currentlayer (getvar "clayer"))
(initdia)
(command "_.insert")
(while (> (getvar 'cmdactive) 0) (command pause)); allowing use of options

 

(setq
list1 '("BLOCK A" "BLOCK B")
list2 '("BLOCK C" "BLOCK D")
list3 '("BLOCK E" "BLOCK F")
;; do all capitalized in blist; (strcase) below will make
;; sure User's entry, if typed, is not case-sensitive
bname (strcase (getvar 'insname))
);setq

 

;I think this way it's easer to add and manager new layers
;If the layer name needs to be change, I will do here only
(setq
L1 "Architecture"
L2 "Telecom"
L3 "Structure"
);setq

 

;I think this way it's easer to add and manager new ltypes;
;If the ltypes needs to be change, I will do here only
(foreach lt '("Center" "Hidden" "Phantom")
(if (not (tblsearch "ltype" lt)) ;if the lltype does not exists
(command "_.-linetype" "_l" lt "acadiso.lin" "") ;create it
); end if
); end foreach

 

(setq
LT1 "Center"
LT2 "Hidden"
LT3 "Phantom"
);setq

 

(cond
((member bname list1)
(if (not (tblsearch "layer" L1)) ;if the layer does not exists
(command "-layer" "m" L1 "lt" LT1 "" "c" "1" "" "") ;create it with my standard configuration
);end if;
(command "_.chprop" (entlast) "" "_layer") ;put this block
(command L1 "_color" "bylayer" "_ltype" "bylayer" "") ;in this layer with my standard configuration for it
);end list1 condition

((member bname list2)
(if (not (tblsearch "layer" L2))
(command "-layer" "m" L2 "lt" LT2 "" "c" "2" "" "")
);end if;
(command "_.chprop" (entlast) "" "_layer")
(command L2 "_color" 3 "_ltype" "bylayer" "")
);end list2 condition

((member bname list3)
(if (not (tblsearch "layer" L3))
(command "-layer" "m" L3 "lt" LT3 "" "c" "3" "" "")
);end if;
(command "_.chprop" (entlast) "" "_layer")
(command L3 "_color" 6 "_ltype" "hidden" "")
);end list3 condition
);cond

 

(setvar "clayer" currentlayer)
(princ)
); defun

Message 12 of 21
hmsilva
in reply to: msarqui

msarqui,
you want to change the blocks after inserting, to a specific layer, and want to have the ability to modify the block color and line type, to do this, your blocks must have already color and LType set to ByBlock, if not, you'll have to redefine the block Color and LType to ByBlock.
As you wrote:
"because of the large number of blocks and possibilities that I have."
I think the code could be huge to load, and maybe allocate too much memory, without need.
One hypothesis is to create a main code, that only test the block name and calls a second code that will make the changes you want, layer, ltype and color...

 

(defun C:IBL (/ list1 list2 list3 bname); = Insert Block on appropriate Layer
(initdia)
(command "_.insert")
(while (> (getvar 'cmdactive) 0) (command pause)); allowing use of options
(setq
list1 '("BLOCK A" "BLOCK B")
list2 '("BLOCK C" "BLOCK D")
list3 '("BLOCK E" "BLOCK F")
;; do all capitalized in blist; (strcase) below will make
;; sure User's entry, if typed, is not case-sensitive
bname (strcase (getvar 'insname))
);setq
(cond
((member bname list1)(c:blk001))
((member bname list2)(c:blk002))
((member bname list3)(c:blk003))
);cond
);defun - IBL

;;first sub-routine
(defun c:blk001 (/ currentlayer)
  (setq currentlayer (getvar "clayer"))
  (if (not (tblsearch "ltype" "Center")) ;if the lltype does not exists, only loads the necessary ltype
(command "_.-linetype" "_l" "Center" "acadiso.lin" "") ;create it
); end if
  (if (not (tblsearch "layer" "Architecture")) ;if the layer does not exists
(command "-layer" "m" "Architecture" "lt" "Center" "" "c" "1" "" "") ;create it with my standard configuration
);end if
(command
  "_.layer" "_thaw" "Architecture" "_make" "Architecture" "_unlock" "Architecture" ""
  "_.chprop" (entlast) ""
  "_layer" "Architecture" "_color" "bylayer" "_ltype" "bylayer" ""
);command - put this block in this layer with my standard configuration for it
(setvar "clayer" currentlayer)
);defun - blk001

;; blk002 blk003 and so on

 To load the sub-routines You can use the acaddoc.lsp with the autoload function

 

(autoload "C:/MyLisp/blk001.LSP" '("blk001")); change to your customization directory

 

with the autoload function will only load the sub-routine if it is not loaded, if is, just run it. I think this way you will not have to load so much code without need.

 

hope that helps

Henrique

EESignature

Message 13 of 21
Kent1Cooper
in reply to: msarqui


@msarqui wrote:

.... I got something that works for what I need. I used the base of the second Kent's routine and added some things to fit in what I needed.

I tested it and it works!!!!!!!!
What do you think?

....


If it works, that's most important, but I do think some things....

 

At the least, I would consolidate some of your redundant (command) functions, e.g. change this:

(command "_.chprop" (entlast) "" "_layer") ;put this block
(command L1 "_color" "bylayer" "_ltype" "bylayer" "")

to this:

(command "_.chprop" (entlast) "" "_layer") L1 "_color" "bylayer" "_ltype" "bylayer" "")

and likewise in the other similar places.

 

Also, if you assign a linetype to either a Layer or an object from within a Layer or Chprop command, it is not necessary for that linetype to be loaded into the drawing already -- AutoCAD will find it.  [It won't if you try to do it by (subst)/(entmod), or (entmake), or, if I remember rightly, VLA Properties].  So you don't need your linetype loading portion.

 

But the more I consider your statement "...because of the large number of blocks and possibilities that I have...", the more I think you're better off using multiple lists and (nth) functions to get pieces of information out of them, as in my third suggested approach [and the subsequent adjustment to it].  Here's why:

 

If you really have considerable numbers of Block names and classifications/groupings with their associated Layers and colors and linetypes, the amount of code you need to do what you want could get pretty cumbersome [hmsilva's concern].  As you have it, if there are, say, 20 classifications, then you will need variables list1 through list20, L1 through L20, and LT1 through LT20, with the correspondingly bloated localized variables list, and all the added lines of code to define them [three added lines for every one, for its Block name list, Layer name, and linetype], and the whole Layer and Chprop portion spelled out separately for every one of them [whether in a lengthy version of a single routine, or pulled out into separate ones as hmsilva suggested].

 

By contrast, the following suggested routine [which is set up to replicate what your version does, though I imagine you really use different Block names] will expand by much less with each additional classification/grouping needed.  Each will add a sublist in the bclasslist variable, and just one item to each of the five following list variables.  No matter how many more Block names and classifications are added, there will be no added variables needed.  And the Layer and Chprop operations are spelled out only once, covering all classifications, and remain unaffected by any amount of increase in the number of Block names and classifications.

 

Also, since it creates any new Layer(s) needed with the New option rather than the Make option, it does not change the current Layer at any time, so it's not necessary to save the current Layer at the beginning or return to it at the end.  That also means there's no need to consider adding error handling [as you probably should in your latest version], since there would be nothing for an error handler to restore to the way it should be, because nothing like that is changed by the routine.

 

So here's how I'd do it [tested, but lightly]:

 

(defun C:IBL ; = Insert Block and move to appropriate Layer
  (/ bname bclasslist blaylist bclist bltlist lclist lltlist bci bclass blay)
  (initdia)
  (command "_.insert")
  (while (> (getvar 'cmdactive) 0) (command pause)); allowing use of options
  (setq
    bname (strcase (getvar 'insname)); NAME of just-inserted Block
    bclasslist ; list of Block CLASSification LISTs
      ;; do all capitalized in these lists; (strcase) above will
      ;; ensure User's entry, if typed, is not case-sensitive
      (list
        '("BLOCK A" "BLOCK B")
        '("BLOCK C" "BLOCK D")
        '("BLOCK E" "BLOCK F")
        ;;; add classifications/groupings here as needed
      ); list & classlist
    ;;; add items as needed to the following 5 lists:
    blaylist '("Architecture" "Telecom" "Structure"); = Block LAYer LIST
    bclist '("bylayer" 3 6); = Block assigned Color LIST
    bltlist '("bylayer" "bylayer" "hidden"); = Block assigned LineType LIST
    lclist '(1 2 3); = Layer Color LIST
    lltlist '("Center" "Hidden" "Phantom"); = Layer LineType LIST
  ); setq
  (while
    (and
      (not bclass); hasn't found it yet
      (< bci (length bclasslist)); hasn't run out of lists to look in
    ); and
    (if (member bname (nth (setq bci (if bci (1+ bci) 0)) bclasslist)); = Block Classification Index
      (setq bclass bci); then
    ); if
  ); while
  (if bclass ; won't exist if not in any list
    (progn ; then
      (setq blay (nth bclass blaylist)); find LAYer name to put Block on
      (if (tblsearch "layer" blay); Layer is in drawing
        (command "_.layer" "_thaw" blay "_unlock" blay ""); then -- ensure it's ready [could omit unlocking]
        (command "_.layer" "_new" blay "_color" (nth bclass lclist) blay "_ltype" (nth bclass lltlist) blay ""); else -- create it
      ); if
      (command
        "_.chprop" (entlast) ""
          "_layer" blay
          "_color" (nth bclass bclist); find that category's assigned color
          "_ltype" (nth bclass bltlist); find that category's assigned linetype
        "" ; finish CHPROP
      ); command
    ); progn -- then [no else, if Block is not in any list]
  ); if
  (princ)
); defun

Kent Cooper, AIA
Message 14 of 21
hmsilva
in reply to: Kent1Cooper

Kent,

as usual,

a very well structured, simple and clean code.

Well done!

I have learned a few more things!

 

Henrique

EESignature

Message 15 of 21
Kent1Cooper
in reply to: hmsilva


@hmsilva wrote:

Kent,

as usual,

a very well structured, simple and clean code.

Well done!

I have learned a few more things!

 

Henrique


Thank you.  I've since been pondering whether I'd want to actually redefine the Insert command to do this with a limited number of Blocks that I know I will always want on particular Layers.  [In my case, I would not use the color or linetype overrides, but would have those be characteristics of the Layers, which would shorten the code, but the concept is the same.]  If I ever have any reason to put one of them on some other Layer, I could use .insert to do it, so I don't think it locks me into anything I might regret.  But if I do it in a system-wide way, I'd need to educate other Users about it.  I could also do it just on my computer.  I'll have to think about that some more....

Kent Cooper, AIA
Message 16 of 21
pbejse
in reply to: hmsilva


@hmsilva wrote:

Kent,....

a very well structured, simple and clean code.

...


It sure is. kudos to Kent and  Henrique Smiley Happy

 

Im off to revisit command function approach.

 

Cheers

 

pBe

 

//Off topic

Message 17 of 21
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:

....

      (if (tblsearch "layer" blay); Layer is in drawing
        (command "_.layer" "_thaw" blay "_unlock" blay ""); then -- ensure it's ready [could omit unlocking]
        (command "_.layer" "_new" blay "_color" (nth bclass lclist) blay "_ltype" (nth bclass lltlist) blay ""); else -- create it
      ); if

....


Come to think of it, the Layer might be in the drawing, and turned off rather than [or in addition to] being frozen, so the 'then' argument would be better this way:

...

        (command "_.layer" "_thaw" blay "_on" blay "_unlock" blay ""); then -- ensure it's ready [could omit unlocking]

 

I probably didn't think of that because I don't usually set things up to test whether a Layer is there, but just have them Make it regardless, and the Make option will turn it on if it's off.  [So will the Set option, but (setvar 'clayer "LayerName") will not.]  I think I did it this way this time to avoid having to save and restore the current Layer.  But if, whether or not the Layer exists, a Layer command is going to be invoked anyway [i.e. you're not avoiding the need for the command if the Layer already exists], and you don't mind its changing the current Layer, then maybe it does make just as much sense to use the Make approach.  You could replace the entire (if) function quoted above with:

 

      (command "_.layer" "_thaw" blay "_make" blay "_unlock" blay "_color" (nth bclass lclist) "" "_ltype" (nth bclass lltlist) "" ""); [could omit unlocking]

 

It needs to Thaw it before it Makes it, because Make sets it current, which it can't do with a Frozen Layer.  Thawing won't be bothered if the Layer doesn't exist yet -- a message will go by [if command echoing is on] that it didn't find a Layer like that, but it will just go back to the Layer sub-prompt and carry on.

 

 

The two circumstance under which you shouldn't do it that way are:

1) if you don't want that Layer to be the current Layer after you're done, and don't want to bother to save the current Layer at the beginning and restore it at the end, or

2) if the Layer might already exist but with non-standard color and/or linetype, and you want to let it keep those non-standard settings [the Make approach will force them to the standard].

Kent Cooper, AIA
Message 18 of 21
hmsilva
in reply to: Kent1Cooper

Kent1Cooper wrote:

...

I've since been pondering whether I'd want to actually redefine the Insert command to do this with a limited number of Blocks that I know I will always want on particular Layers.  [In my case, I would not use the color or linetype overrides, but would have those be characteristics of the Layers, which would shorten the code, but the concept is the same.]  If I ever have any reason to put one of them on some other Layer, I could use .insert to do it, so I don't think it locks me into anything I might regret.  But if I do it in a system-wide way, I'd need to educate other Users about it.  I could also do it just on my computer.  I'll have to think about that some more....

 

Kent,

I'm currently rewriting part of the customization files (using your structure, message 13) for our topography department, without redefine the Insert command, because they already insert blocks using a lisp that after inserting, change the block to the correct layer (with many, many, many more lines of code, than your approach), I chose to use the "command" (message 17) instead of the "if", because when they are inserting blocks, they are only to insert blocks, so there is no problem in the layer of the last inserted block become the corrent layer. Regarding other departments, I have to think about it.

 

Thank you.

Henrique

EESignature

Message 19 of 21
msarqui
in reply to: Kent1Cooper

Kent1Cooper wrote:

 

Come to think of it, the Layer might be in the drawing, and turned off rather than [or in addition to] being frozen, so the 'then' argument would be better this way:

...

        (command "_.layer" "_thaw" blay "_on" blay "_unlock" blay ""); then -- ensure it's ready [could omit unlocking]

 

Well, this one is the best for me until now. Thanks Kent.

 

I was wondering, because the large number of blocks, do you think it will be more pratical to put the list of blocks in an external txt file and load it?

I mean, something like this:

 

list 1 '(command "_.load" blocks1.txt)

list 2 '(command "_.load" blocks2.txt)

list 2 '(command "_.load" blocks3.txt)

 

Or it's not a good ideia? Just a curiosity...

 

I would like to thank you for taking your time about it. I am very glad to learn from you.

 

And yes 

 

Message 20 of 21
Kent1Cooper
in reply to: msarqui


@msarqui wrote:

....

I was wondering, because the large number of blocks, do you think it will be more pratical to put the list of blocks in an external txt file and load it?

I mean, something like this:

 

list 1 '(command "_.load" blocks1.txt)

list 2 '(command "_.load" blocks2.txt)

list 2 '(command "_.load" blocks3.txt)

 

Or it's not a good ideia? Just a curiosity...

....


I don't think there would be any real advantage, but if you would find it any easier to maintain such lists outside of the routine itself, you can certainly keep them in separate files.  But it would need to be by way of the AutoLISP (load) function, rather than the Load command, which is for Shape files.  [You could do it by way of the (open) and (read-line) functions instead, but that would be more cumbersome, because that would operate by text strings, and those would need to be converted somehow to make lists out of them.]

 

I would suggest, if you want to do it by separate file, that to work with the structure of my latest routine, the Blocks.lsp [or whatever you want to call it] file would contain something like this:

 

(setq bclasslist ; list of Block CLASSification LISTs
  (list
    '("BLOCK A" "BLOCK B")
    '("BLOCK C" "BLOCK D")
    '("BLOCK E" "BLOCK F")
    ;;; add classifications/groupings here as needed
  ); list & classlist

); setq

 

or better yet [and this simplification could be used in my routine]:

 

(setq bclasslist ; list of Block CLASSification LISTs
  '( ; "quoted" list rather than explicity (list) function
    ("BLOCK A" "BLOCK B") ; without preceding apostrophes
    ("BLOCK C" "BLOCK D")
    ("BLOCK E" "BLOCK F")
    ;;; add classifications/groupings here as needed
  ); list & classlist

); setq

 

and the main routine would contain something like this, anywhere prior to its (while) function:
 

(load "blocks.lsp")

 

You could also do it with a separate file for each list, if you really want to:

 

Blocks1.lsp would be:

(setq blocks1 '("BLOCK A" "BLOCK B"))

 

Blocks2.lsp would be:

(setq blocks2 '("BLOCK C" "BLOCK D"))

 

Blocks3.lsp would be:

(setq blocks3 '("BLOCK E" "BLOCK F"))

 

And the main routine would contain:
 

(load "blocks1.lsp")

(load "blocks2.lsp")

(load "blocks3.lsp")

(setq bclasslist (list blocks1 blocks2 blocks3))

 

But that way, if you ever need to add another classification, you would need to:

1) make an additional file for its Block name list;

2) add a (load) line in the main routine for that file;

3) add its list variable name to the (setq bclasslist...) function in the main routine.

 

And if you ever need to remove one other than the last one, you would need to re-number at least some of the remaining ones, both in their list variable names and in their file names, and you would need to delete a file and remove its (load) line and variable name in the main routine.

 

In contrast, doing it all in one combined list-of-lists Blocks.lsp file means that all you would need to do is to add [or remove] the single line for the classification/grouping in that one file -- no adjustments at all would be needed in the main routine except those added elements in the following lists that would be needed if the classification lists were internal to that file, and no files would be needed created or deleted.

Kent Cooper, AIA

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost