Help with routine to create layer

Help with routine to create layer

msarqui
Collaborator Collaborator
1,189 Views
10 Replies
Message 1 of 11

Help with routine to create layer

msarqui
Collaborator
Collaborator

Hello,

 

I made this simple routine to create a layer :

 

(defun c:createLayerTex (/ acadObj doc layers newLayer)

(setq acadObj (vlax-get-acad-object)
 doc (vla-get-ActiveDocument acadObj)
 layers (vla-get-Layers doc)
 newLayer (vla-Add layers "Tx-0-Textes")
);setq

 

;I set the following vla-put, because If the layer already exists, and If it does not have this properties, I would like to replace those informations.
  (vla-put-color newLayer 5)
  (vla-put-linetype newLayer "Hidden")
  (vla-put-layeron newLayer :vlax-true)
  (vla-put-freeze newLayer :vlax-false)
  (vla-put-Lock newLayer :vlax-false)


);defun

 

My problem is:

If I already have this layer in my drawing, and it is not current, nothing happens. That is OK.

But, If I already have this layer in my drawing, and it is current, the following message appears :

Command: CREATELAYERTEX
; error: Automation Error. Invalid layer

 

Any help?

Thanks.

0 Likes
Accepted solutions (1)
1,190 Views
10 Replies
Replies (10)
Message 2 of 11

Kent1Cooper
Consultant
Consultant

This is one of the reasons I prefer to just use a Layer command:

 

(setq LayName "Tx-0-Textes")

(command "_.layer" "_thaw" LayName "_make" LayName "_unlock" LayName "_color" 5 "" _ltype" "hidden" "" "")

 

It takes care of a lot of that other stuff for you.  It won't care whether or not the Layer already exists in the drawing, even for Thawing before it even exists.  [You need to do that because if it does exist but is Frozen, it can't be made current, so you can't use its name in the "_make" option.]  It will make it current, whether or not it exists already.  It will turn it on if it's off.  It will force the color and linetype to your standards if the Layer already exists but with different settings for those.

 

If you don't necessarily want the new Layer to be current when it's done, you can either:

A.  precede the above with (setq clay (getvar 'clayer)) and follow it with (setvar 'clayer clay), or

B.  use the "_new" option instead of "_make", add an "_on" option in case it exists but is off, and give it the Layer name specifically for the "_on" option and for the color and linetype assignments in lieu of the Enters that accept the current Layer name as default.

 

Yes, technically, this would be "slower" than the other method, but not by an amount that would be even remotely detectable by a User [certainly far less time than it takes to click and release a mouse button], unless you have a very large number of Layers to create lumped together into a collective routine.

Kent Cooper, AIA
0 Likes
Message 3 of 11

hmsilva
Mentor
Mentor

msarqui wrote:

My problem is:

If I already have this layer in my drawing, and it is not current, nothing happens. That is OK.

But, If I already have this layer in my drawing, and it is current, the following message appears :

Command: CREATELAYERTEX
; error: Automation Error. Invalid layer


Hi msarqui,

 

using vla-Add method to add a layer to layer collection, we'll have to ensure that ltype is loaded before we set a layer with it, and if layer is the current one, we can not change the freeze property...

 

Something like this will do the trick

 

(defun c:createLayerTex (/ acadObj currlay doc flag layers ltypes newLayer)
  (setq acadObj  (vlax-get-acad-object)
        doc      (vla-get-ActiveDocument acadObj)
        layers   (vla-get-Layers doc)
        ltypes   (vla-get-Linetypes doc)
        currlay  (vla-get-ActiveLayer doc)
        newLayer (vla-Add layers "Tx-0-Textes")
  );setq

  (vlax-for lt ltypes
    (if (wcmatch (strcase (vla-get-name lt)) "HIDDEN")
      (setq flag t)
    )
  )
  (if (null flag)
    (vla-load ltypes "Hidden" "acadiso.lin")
  )

  ;I set the following vla-put, because If the layer already exists, and If it does not have this properties, I would like to replace those informations.
  (vla-put-Lock newLayer :vlax-false)
  (vla-put-layeron newLayer :vlax-true)
  (if (not (wcmatch (strcase (vla-get-name currlay)) "TX-0-TEXTES"))
    (vla-put-freeze newLayer :vlax-false)
  )
  (vla-put-color newLayer 5)
  (vla-put-linetype newLayer "Hidden")
  (princ)
);defun

 

Hope this helps,
Henrique

EESignature

0 Likes
Message 4 of 11

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

.... 

It takes care of a lot of that other stuff for you. ....


And another thing:  It does not require the linetype to be loaded into the drawing already -- it will find it.

Kent Cooper, AIA
0 Likes
Message 5 of 11

msarqui
Collaborator
Collaborator

Hi Henrique


@hmsilva wrote:

...and if layer is the current one, we can not change the freeze property...

 

Something like this will do the trick 

  (if (not (wcmatch (strcase (vla-get-name currlay)) "TX-0-TEXTES"))
    (vla-put-freeze newLayer :vlax-false)
  )

I've been studying your code to learn and realized that maybe this wil be necessary only if I have this way:

(if (not (wcmatch (strcase (vla-get-name currlay)) "TX-0-TEXTES"))
    (vla-put-freeze newLayer :vlax-true)
  )

Because if the layer is freeze, it certainly will not be the current one.

Am I right?

 

Thanks for your help.

 

0 Likes
Message 6 of 11

msarqui
Collaborator
Collaborator

Hi Kent

You're right. Sometimes the best thing is to keep it simple and straightforward. I had done before the way you said and it works very well. However, I would like to know how to get around this problem in VLISP because I'm trying to learn it.
Thanks a lot.

0 Likes
Message 7 of 11

hmsilva
Mentor
Mentor
Accepted solution

@msarqui wrote:

Hi Henrique


@hmsilva wrote:

...and if layer is the current one, we can not change the freeze property...

 

Something like this will do the trick 

  (if (not (wcmatch (strcase (vla-get-name currlay)) "TX-0-TEXTES"))
    (vla-put-freeze newLayer :vlax-false)
  )

I've been studying your code to learn and realized that maybe this wil be necessary only if I have this way:

(if (not (wcmatch (strcase (vla-get-name currlay)) "TX-0-TEXTES"))
    (vla-put-freeze newLayer :vlax-true)
  )

Because if the layer is freeze, it certainly will not be the current one.

Am I right?


Hi msarqui,

 

No.

Your code is generic, you don't know if layer exists, if is freeze or locked or current or... as I had previously said, '...and if layer is the current one, we can not change the freeze property...' so, if we 'put' 'true' or false' we are modifying the propertie (even if we don't change the property current value) and will give the ' ;error: Automation Error. Invalid layer'

 

As your code is generic, you could modify it to a function,

i.e.

;; usage
;; (createLayer "test" nil nil)
;; to create a layer "test" with default color and linetype
;; (createLayer "test" 1 nil)
;; to create a layer "test" with color 1 and default linetype
;; (createLayer "test" 3 "center")
;; to create a layer "test" with color 3 and linetype center
(vl-load-com)
(defun createLayer (layname color ltype / acadObj currlay doc flag layers ltypes newLayer)
  (setq acadObj  (vlax-get-acad-object)
        doc      (vla-get-ActiveDocument acadObj)
        layers   (vla-get-Layers doc)
        ltypes   (vla-get-Linetypes doc)
        currlay  (vla-get-ActiveLayer doc)
        newLayer (vla-Add layers layname)
  )
  (if ltype
    (progn
      (vlax-for lt ltypes
        (if (wcmatch (strcase (vla-get-name lt)) (strcase ltype))
          (setq flag t)
        )
      )
      (if (null flag)
        (vla-load ltypes ltype "acadiso.lin")
      )
      (vla-put-linetype newLayer ltype)
    )
  )
  (vla-put-Lock newLayer :vlax-false)
  (vla-put-layeron newLayer :vlax-true)
  (if (not (wcmatch (strcase (vla-get-name currlay)) (strcase layname)))
    (vla-put-freeze newLayer :vlax-false)
  )
  (if color
    (vla-put-color newLayer color)
  )
)

 

Hope this helps,
Henrique

EESignature

0 Likes
Message 8 of 11

redtransitconsultants
Collaborator
Collaborator

You just need to search the layer table for the name to check if it exists already. Here's some code to do that... 

(if (tblsearch "LAYER" "MY-LAYER-NAME") ;Check if the layer exists
  (progn
    ;;Found layer, do something
  ) ;End if progn
  (progn
    ;;Cannot find layer, skip, or do something else
  ) ;End if progn
) ;End of if

 

Additionally, you could get the currently layer and store it in memory temporarily, change the layer to something else like 0, do something, then when done change it back and the user wouldn't know the difference.

 

(setq oldlayer (getvar "CLAYER"))
(setvar "CLAYER" "0")

;;Do something here

(setvar "CLAYER" oldlayer)

 

 

 

Steve Hill,Civil Designer / .NET Developer / AutoCAD and AutoCAD Civil 3D Certified Professional
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature

http://redtransitconsultants.com/
Autodesk Exchange Store
Twitter | LinkedIn | YouTube

0 Likes
Message 9 of 11

msarqui
Collaborator
Collaborator

@redtransitconsultants wrote:

You just need to search the layer table for the name to check if it exists already. 


Hi Steve,

 

I had already tried that. I do not know why but I could never do tblsearch work with VLISP. Maybe I am missing something.


@redtransitconsultants wrote:

Additionally, you could get the currently layer and store it in memory temporarily, change the layer to something else like 0, do something, then when done change it back and the user wouldn't know the difference.


Well, I had also thought of changing the layer, but I thought this would be a palliative solution. I think Henrique showed a great way to solve the issue.

Thanks!

0 Likes
Message 10 of 11

msarqui
Collaborator
Collaborator

@hmsilva wrote:

 

Hi msarqui,

No.

Your code is generic, you don't know if layer exists, if is freeze or locked or current or... as I had previously said, '...and if layer is the current one, we can not change the freeze property...' so, if we 'put' 'true' or false' we are modifying the propertie (even if we don't change the property current value) and will give the ' ;error: Automation Error. Invalid layer'


 

Hi Henrique, 

You are right. I made some tests and the error came out again. I understand now the logic. Thanks for the explanation.


@hmsilva wrote:

As your code is generic, you could modify it to a function,

i.e.

;; usage
;; (createLayer "test" nil nil)
;; to create a layer "test" with default color and linetype
;; (createLayer "test" 1 nil)
;; to create a layer "test" with color 1 and default linetype
;; (createLayer "test" 3 "center")
;; to create a layer "test" with color 3 and linetype center
(vl-load-com)
(defun createLayer (layname color ltype / acadObj currlay doc flag layers ltypes newLayer)
  (setq acadObj  (vlax-get-acad-object)
        doc      (vla-get-ActiveDocument acadObj)
        layers   (vla-get-Layers doc)
        ltypes   (vla-get-Linetypes doc)
        currlay  (vla-get-ActiveLayer doc)
        newLayer (vla-Add layers layname)
  )
  (if ltype
    (progn
      (vlax-for lt ltypes
        (if (wcmatch (strcase (vla-get-name lt)) (strcase ltype))
          (setq flag t)
        )
      )
      (if (null flag)
        (vla-load ltypes ltype "acadiso.lin")
      )
      (vla-put-linetype newLayer ltype)
    )
  )
  (vla-put-Lock newLayer :vlax-false)
  (vla-put-layeron newLayer :vlax-true)
  (if (not (wcmatch (strcase (vla-get-name currlay)) (strcase layname)))
    (vla-put-freeze newLayer :vlax-false)
  )
  (if color
    (vla-put-color newLayer color)
  )
)

This is amazing! I have lots of "create layers routines" and now I can use only this function to do that. This is really good!

Thanks again.

Marcelo

0 Likes
Message 11 of 11

hmsilva
Mentor
Mentor

You're welcome, Marcelo!
Glad I could help

Henrique

EESignature

0 Likes