Layer Freeze

ademercan1
Advocate
Advocate

Layer Freeze

ademercan1
Advocate
Advocate

Hi
The following code was written to freeze the layer "A1" in all viewports in the layout "FP5". But instead of freezing the layer in the viewport, it freezes the general layer. I'd like your help with this.

 

(defun c:ww (/ dc) (vl-load-com)
  (setq dc (vla-get-ActiveDocument
    (vlax-get-acad-object)))
  (vlax-for m (vla-get-Block (vla-Item
      (vla-get-Layouts dc) "FP5"))
    (if (= (vla-get-ObjectName m) "AcDbViewport")
      (progn
        (vla-Display m :vlax-True)
        (vla-put-ViewportOn m :vlax-True)
        (vla-Update m)
        (vla-put-MSpace dc :vlax-True)
        (vla-put-Freeze (vla-Item
          (vla-get-Layers dc) "A1")
            :vlax-True)
        (vla-put-MSpace dc :vlax-False)
      )
    )
  )
  (vla-Regen dc 1)
  (prin1)
)
0 Likes
Reply
2,985 Views
42 Replies
Replies (42)

Anonymous
Not applicable

I do not know if I understand,
What I did was very simple!

 

(defun C:Brincando nil
	(foreach layout ( layoutlist )
		(setvar "CTAB" layout)
		(command
			"_.MSPACE"
			"_.VPLAYER" "_FREEZE" "LAYER NAME" "" ""
			"_.PSPACE"
		)
		);foreach
  (princ)
)

 

0 Likes

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

I do not know if I understand,
What I did was very simple!....


... if there is only one  Viewport in each Layout.  I don't think that's the OP's situation -- they're going for all Viewports in only one particular Layout, if I understand correctly.

Kent Cooper, AIA
0 Likes

ademercan1
Advocate
Advocate

You got it right. but it should be done with active-x, not command

0 Likes

Kent1Cooper
Consultant
Consultant

Could it have something to do with the fact that the Paper Space in a Layout is also a Viewport?  When I do (ssget) and look for all Viewports, it "finds" the Paper Space Viewport in addition to those that are "looking into" Model Space.  The CVPORT System Variable is at 1 when in Paper Space, and 2 and upward for each Model Space Viewport.  So if getting Viewports with those (vla...) methods finds Paper Space [as finding them with (ssget) does], do you need to check on the CVPORT value before applying the Layer freezing, to avoid freezing it in Paper Space too?

Kent Cooper, AIA
0 Likes

ademercan1
Advocate
Advocate

would you please complete the missing code above

0 Likes

Kent1Cooper
Consultant
Consultant

@ademercan1 wrote:

would you please complete the missing code above


No.  Sorry -- I'm conversant with a limited set of the (vl-...) and (vlax-...) functions, but the (vla-...) functions are mostly beyond my experience, and they're not documented in the AutoLisp Reference, so I can't look them up there to see what the syntax and required arguments would be.  There should be others around here who can help you with that, and who I hope can first determine whether my supposition is correct about the CVPORT issue.

Kent Cooper, AIA
0 Likes

ronjonp
Advisor
Advisor

@ademercan1 wrote:

You got it right. but it should be done with active-x, not command


I don't know of a non-command call way to mimic VPLAYER.

0 Likes

ademercan1
Advocate
Advocate

 

ronjonp:

0 Likes

ronjonp
Advisor
Advisor

@ademercan1 wrote:

...

 

ronjonp:


Huh? All I'm saying is I don't know of a way freeze a layer in a viewport without using (command "vplayer" ..)

Your example above will freeze the layer for the entire document.

 

You also might want to check that there is actually a layer named "A1" and a tab named "FP5" before proceeding otherwise the code will error out.

(defun c:ww (/ dc)
  (vl-load-com)
  (if (and (tblobjname "layer" "A1") (member "FP5" (mapcar 'strcase (layoutlist))))
    (progn (setq dc (vla-get-activedocument (vlax-get-acad-object)))
	   ...
	   (vla-regen dc 1)
    )
  )
  (prin1)
)
0 Likes

ademercan1
Advocate
Advocate

The method you propose for the above code applies. However, for files opened with vla-Open, the recommended method does not apply. Active-x functions only work with files opened with Vla-Open. Therefore, I asked if active-x can be done instead of command.

0 Likes

ronjonp
Advisor
Advisor

@ademercan1 wrote:

The method you propose for the above code applies. However, for files opened with vla-Open, the recommended method does not apply. Active-x functions only work with files opened with Vla-Open. Therefore, I asked if active-x can be done instead of command.


What makes you think that ActiveX functions are limited to files opened with vla-open ?

 

Are you trying to process these files using ODBX ... if so then as stated before I don't know of a non-command call way to do it.

0 Likes

ademercan1
Advocate
Advocate

Translation from google. Therefore, some sentences may not be understood clearly. If a file is opened with ObjectDBX or vla-Open, you cannot use command or vl-cmdf to process lisp in that file. Because it doesn't work.

0 Likes

ronjonp
Advisor
Advisor

@ademercan1 wrote:

Translation from google. Therefore, some sentences may not be understood clearly. If a file is opened with ObjectDBX or vla-Open, you cannot use command or vl-cmdf to process lisp in that file. Because it doesn't work.


Hahaha .. lost in translation 🙂 .. we're in agreement now. I think you're stuck opening the files with a script and using (command).

0 Likes

ademercan1
Advocate
Advocate

🙂🙂🙂

Did the year 2019 script is no longer left. And with a fast-running language like active-x. But we finally agreed, which is pleasing.

0 Likes

doaiena
Collaborator
Collaborator

The frozen layers for a given pvport are stored in the entity as xdata, under the "ACAD" app name. The code is 1003 /int/ and the value is the layer name /string/. For some reason i can't remove an entry from the xdata. I can only add new entries /add other layers to be frozen/. I'm not sure if i am missing something, or it isn't possible at all.

 

Here is the code i came up with. Have a look at it. It works for other entities containing xdata, but not for pvports. If you find out why it isn't working, please let me know.

(defun c:test (/ LM:RemoveOnce doc layerName layoutName codes vals arrPos codeArr valArr codeLst varLst)

;;--------------------=={ Remove Once }==---------------------;;
;;                                                            ;;
;;  Removes the first occurrence of an item from a list       ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  x - item to be removed                                    ;;
;;  l - list from which to remove first occurrence of item    ;;
;;------------------------------------------------------------;;
;;  Returns:  Resultant list following the removal            ;;
;;------------------------------------------------------------;;

(defun LM:RemoveOnce ( x l / f )
    (setq f equal)
    (vl-remove-if '(lambda ( a ) (if (f a x) (setq f (lambda ( a b ) nil)))) l)
);defun

(setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq layerName "A1" layoutName "FP5")

(if (and (tblsearch "layer" layerName) (vl-position layoutName (layoutlist)))
(progn

(vlax-for item (vla-get-Block (vla-Item (vla-get-Layouts doc) layoutName))
(if (= (vla-get-ObjectName item) "AcDbViewport")
(progn

;This is the part of the function that doesn't work on pvport entities.
;Get the pvport's xdata (vla-getxdata item "ACAD" 'codes 'vals)

;if the pvport has xdata and the layer name is present in the xdata,
;record the layer's position in the array, in the var "arrPos"
(if (and codes vals (setq arrPos (vl-position layerName (mapcar 'variant-value (vlax-safearray->list vals))))) (progn
;Create an empty array for the xdata codes, that is 1 item shorter than the original
(setq codeArr (vlax-make-safearray vlax-vbInteger (cons 1 (- (length (vlax-safearray->list codes)) 1))))

;Create an empty array for the xdata values, that is 1 item shorter than the original (setq valArr (vlax-make-safearray vlax-vbVariant (cons 1 (- (length (vlax-safearray->list vals)) 1))))

;Create lists with the layer information removed from them /1 item shorter than the original xdata/ (setq codeLst (LM:RemoveOnce (nth arrPos (vlax-safearray->list codes)) (vlax-safearray->list codes))) (setq varLst (LM:RemoveOnce (nth arrPos (vlax-safearray->list vals)) (vlax-safearray->list vals)))
;Fill the newly created arrays with the code and data lists (vlax-safearray-fill codeArr codeLst) (vlax-safearray-fill valArr varLst)

;Set the xdata for the object (vla-SetXData item codeArr valArr)
));if xdata ));if vp );vlax-for ));if layer and layout (princ) );defun

 

marko_ribar
Advisor
Advisor

To both @ademercan1  and @doaiena ...

The problem maybe lie in the fact that you are iterating through collection of main Paperspace VLA-OBJECT not directly connected to your desired specific Layout... (You are using (vla-get-block layout) and IMHO it returns original Paperspace VLA-OBJECT...) Possibly solution is to get pvports with simple (ssget "_X" (list '(0 . "VIEWPORT") '(-4 . "<not") '(69 . 1) '(-4 . "not>") (cons 410 "FP5"))) and then operate only on those selected in that layout... Look at picture in attachment to see what was IMO your case of using (vla-get-block)...

I don't know will it fix the problem with freezing specific layer "A1" in "FP5" layout, but it may be more confident way of applying XDATA change to viewports that reside only on that specific layout...

activedocument-chk.png

Marko Ribar, d.i.a. (graduated engineer of architecture)

marko_ribar
Advisor
Advisor

According to my observations, give it a try and let us know if it works (I can't test it, I am away from ACAD)...

;; (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object)))) -> ModelSpace/PaperSpace

(defun c:remlayerfromvportsxdatasinspecificlayout (/ LM:RemoveOnce doc layerName layoutName codes vals arrPos codeArr valArr codeLst varLst)

;;--------------------=={ Remove Once }==---------------------;;
;;                                                            ;;
;;  Removes the first occurrence of an item from a list       ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  x - item to be removed                                    ;;
;;  l - list from which to remove first occurrence of item    ;;
;;------------------------------------------------------------;;
;;  Returns:  Resultant list following the removal            ;;
;;------------------------------------------------------------;;

(defun LM:RemoveOnce ( x l / f )
    (setq f equal)
    (vl-remove-if '(lambda ( a ) (if (f a x) (setq f (lambda ( a b ) nil)))) l)
);defun

(setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq layerName "A1" layoutName "FP5")

(if (and (tblsearch "layer" layerName) (vl-position layoutName (layoutlist)))
(progn

;; (vlax-for item (vla-get-Block (vla-Item (vla-get-Layouts doc) layoutName)) - excluded by M.R.
(ssget "_X" (list '(0 . "VIEWPORT") '(-4 . "<not") '(69 . 1) '(-4 . "not>") (cons 410 layoutName))) ;; - revision by M.R.
(vlax-for item (vla-get-activeselectionset doc) ;; - revision by M.R.
(if (= (vla-get-ObjectName item) "AcDbViewport")
(progn

;This is the part of the function that doesn't work on pvport entities.
;Get the pvport's xdata
(vla-getxdata item "ACAD" 'codes 'vals)

;if the pvport has xdata and the layer name is present in the xdata,
;record the layer's position in the array, in the var "arrPos"
(if (and codes vals (setq arrPos (vl-position layerName (mapcar 'variant-value (vlax-safearray->list vals)))))
(progn

;Create an empty array for the xdata codes, that is 1 item shorter than the original
(setq codeArr (vlax-make-safearray vlax-vbInteger (cons 1 (- (length (vlax-safearray->list codes)) 1))))

;Create an empty array for the xdata values, that is 1 item shorter than the original
(setq valArr (vlax-make-safearray vlax-vbVariant (cons 1 (- (length (vlax-safearray->list vals)) 1))))

;Create lists with the layer information removed from them /1 item shorter than the original xdata/
(setq codeLst (LM:RemoveOnce (nth arrPos (vlax-safearray->list codes)) (vlax-safearray->list codes)))
(setq varLst (LM:RemoveOnce (nth arrPos (vlax-safearray->list vals)) (vlax-safearray->list vals)))

;Fill the newly created arrays with the code and data lists
(vlax-safearray-fill codeArr codeLst)
(vlax-safearray-fill valArr varLst)

;Set the xdata for the object
(vla-SetXData item codeArr valArr)
));if xdata

));if vp
);vlax-for

));if layer and layout

(princ)
);defun

Of course, all credits to @doaiena ... It's the same code...

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)

marko_ribar
Advisor
Advisor

I tried it once again and it won't work... It crushes when needed to (entmod) entity data... What I figured out is that is has to do something with both XDATA and DXF data and something unknown which "VPLAYER" command does and it's impossible to mimic that by my attempts... Here are the codes, if you are interested, but they don't work...

 

;; (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object)))) -> ModelSpace/PaperSpace

(defun c:thawlayerfromvportsxdatasinspecificlayout ( / doc layerName layoutName codes vals arrPos codeArr valArr codeLst valLst k ed )

(setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq layerName "A1" layoutName "FP5")

(if (and (tblsearch "layer" layerName) (vl-position layoutName (layoutlist)))
(progn

;; (vlax-for item (vla-get-Block (vla-Item (vla-get-Layouts doc) layoutName)) - excluded by M.R.
(ssget "_X" (list '(0 . "VIEWPORT") '(-4 . "<not") '(69 . 1) '(-4 . "not>") (cons 410 layoutName))) ;; - revision by M.R.
(vlax-for item (vla-get-activeselectionset doc) ;; - revision by M.R.
(if (= (vla-get-ObjectName item) "AcDbViewport")
(progn

;This is the part of the function that doesn't work on pvport entities.
;Get the pvport's xdata
(vla-getxdata item "ACAD" 'codes 'vals)

;if the pvport has xdata and the layer name is present in the xdata,
;record the layer's position in the array, in the var "arrPos"
(if (and codes vals (setq arrPos (vl-position layerName (mapcar 'variant-value (safearray-value vals)))))
(progn

;Create an empty array for the xdata codes, that is 1 item shorter than the original
(setq codeArr (vlax-make-safearray vlax-vbInteger (cons 1 (- (length (safearray-value codes)) 1))))

;Create an empty array for the xdata values, that is 1 item shorter than the original
(setq valArr (vlax-make-safearray vlax-vbVariant (cons 1 (- (length (safearray-value vals)) 1))))

;Create lists with the layer information removed from them /1 item shorter than the original xdata/
(setq k -1)
(setq codeLst (vl-remove-if '(lambda ( x ) (setq k (1+ k)) (if (= k arrPos) t nil)) (safearray-value codes)))
(setq k -1)
(setq valLst (vl-remove-if '(lambda ( x ) (setq k (1+ k)) (if (= k arrPos) t nil)) (safearray-value vals)))

;Fill the newly created arrays with the code and data lists
(vlax-safearray-fill codeArr codeLst)
(vlax-safearray-fill valArr valLst)

;Set the xdata for the object
(vla-SetXData item codeArr valArr)
));if xdata

(setq ed (entget (vlax-vla-object->ename item) '("*")))
(setq ed (vl-remove-if '(lambda ( x ) (or (and (= (car x) 331) (eq (tblobjname "LAYER" layerName) (cdr x))) (and (= (car x) 1003) (= (cdr x) layerName)))) ed))
(entupd (cdr (assoc -1 (entmod ed))))

));if vp
);vlax-for

));if layer and layout

(princ)
);defun



(defun c:freezelayerfromvportsxdatasinspecificlayout ( / doc layerName layoutName codes vals codeArr valArr codeLst valLst precodeLst appcodeLst sufcodeLst prevalLst appvalLst sufvalLst ed ped sed )

(setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq layerName "A1" layoutName "FP5")

(if (and (tblsearch "layer" layerName) (vl-position layoutName (layoutlist)))
(progn

;; (vlax-for item (vla-get-Block (vla-Item (vla-get-Layouts doc) layoutName)) - excluded by M.R.
(ssget "_X" (list '(0 . "VIEWPORT") '(-4 . "<not") '(69 . 1) '(-4 . "not>") (cons 410 layoutName))) ;; - revision by M.R.
(vlax-for item (vla-get-activeselectionset doc) ;; - revision by M.R.
(if (= (vla-get-ObjectName item) "AcDbViewport")
(progn

;This is the part of the function that doesn't work on pvport entities.
;Get the pvport's xdata
(vla-getxdata item "ACAD" 'codes 'vals)

(if (and codes vals)
(progn

;Create an empty array for the xdata codes, that is 1 item larger than the original
(setq codeArr (vlax-make-safearray vlax-vbInteger (cons 0 (length (safearray-value codes)))))

;Create an empty array for the xdata values, that is 1 item larger than the original
(setq valArr (vlax-make-safearray vlax-vbVariant (cons 0 (length (safearray-value vals)))))

;Retrieve safearray-lists
(setq codeLst (safearray-value codes))
(setq valLst (safearray-value vals))

;Create lists with the layer information added to them /1 items larger than the original xdata/
(setq precodeLst (reverse (cddr (reverse codeLst))))
(setq sufcodeLst (list (cadr (reverse codeLst)) (last codeLst)))
(setq prevalLst (reverse (cddr (reverse valLst))))
(setq sufvalLst (list (cadr (reverse valLst)) (last valLst)))
(setq appcodeLst (list 1003))
(setq appvalLst (list layerName))

(setq codeLst (append precodeLst appcodeLst sufcodeLst))
(setq valLst (append prevalLst appvalLst sufvalLst))

;Fill the newly created arrays with the code and data lists
(vlax-safearray-fill codeArr codeLst)
(vlax-safearray-fill valArr valLst)

;Set the xdata for the object
(vla-SetXData item codeArr valArr)
));if xdata

(setq ed (entget (vlax-vla-object->ename item) '("*")))
(if (not (vl-position (cons 331 (tblobjname "LAYER" layerName)) ed))
(progn
(setq ped (reverse (member (assoc 72 ed) (reverse ed))))
(setq sed (member (assoc 90 ed) ed))
(setq ed (append ped (list (cons 331 (tblobjname "LAYER" layerName))) sed))
))
(entupd (cdr (assoc -1 (entmod ed))))

));if vp
);vlax-for

));if layer and layout

(princ)
);defun

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)

ademercan1
Advocate
Advocate

Thank you for all your efforts. As I said, entmod or command type functions work in the active document. In documents opened with vla-open or ObjectDBX functions, functions such as command, vl-cmdf do not work. Even if this code is currently written according to the active document, it must be decoded with active-x as it will also be used in vla-open functions. I keep working for the solution.

0 Likes