AutoCAD Architecture Customization
Welcome to Autodesk’s AutoCAD Architecture Customization Forums. Share your knowledge, ask questions, and explore popular AutoCAD Architecture Customization topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Tags of Objects Through XRefs - Making Correct

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
Hugh_Compton
1218 Views, 11 Replies

Tags of Objects Through XRefs - Making Correct

 

When an object in an XRef is tagged (and the object has an object based PSD) the tag will not update to reflect changes made in the XRef. 

 

This can be fixed in the XRef by running the PropertyDataBrowser command and unticking the Overrides (shown in the leftmost tickbox when two tick boxes present).

 

This is a pain.  Does anyone know of an automatic way to keep the tags up to date?

 

PS I have attached my VB.Net code attempt for this.  It almost works BUT the MultiViewBlock Overrides are ReadOnly.  GRrr!

11 REPLIES 11
Message 2 of 12
David_W_Koch
in reply to: Hugh_Compton

Assuming that you have already attached the relevant property sets to the objects in the file which is being externally referenced, when you tag the object through an externally referenced instance of that file, when the Edit Property Set Data dialog appears, you can set the desired location from which the tag to reference the property data by changing the setting for the Data source property (first property under each property set listed).  The default will be the current drawing (a property override in the file with the external reference), but you can change it to be file being referenced.  You would have to do this for each tag placed.  This also presumes that you have not chosen to suppress the appearance of the Edit Property Set Data dialog.

 

The only way to get this to automatically function properly, you have to work within the ACA Drawing Management feature (Project Browser/Project Navigator).  When doing so, ACA "knows" where the property set should live when tagging in a View file (in the Construct file, either directly on an object that is placed directly in the Construct file, or as an override in the Construct file for an object that is part of an Element externally referenced by the Construct file.  Outside of the Drawing Management environment, you have to manually tell ACA where the source should be, with the default being in the current drawing, or, after placement, by using the PropertyDataBrowse command.  Expecting the user to remember to set the data source for each tag or taking the time to verify all are set correctly after the fact was considered "too much" at my firm, so we place all tags that display property data from object-base property sets in the same file as the object.  I have never tried to write code to remove overrides, so I cannot offer any insights as to how to make that work.


David Koch
AutoCAD Architecture and Revit User
Blog | LinkedIn
EESignature

Message 3 of 12
Gary_J_Orr
in reply to: David_W_Koch

This might need a little work for your specific use but was part of a utility function (in lisp) that I wrote for 04 then updated for 06... the overall function tagged all of the spaces from an xref, then deleted the overrides, it also did a double check to remove any duplicates (one of which I created as part of the main tagging function which I have not included).

Experiment/use at your own risk, yada, yada, yada...

 

(vl-load-com)

;this next as a command line app, we can use it to clear ANY xref data overrides.
(defun c:deldataover ()
  ;see if the xref has an extension dictionary. If it does go to work
  (princ "\nDeleting Data Overrides")
  (setq xrefset (ssget "X" (list '(0 . "INSERT"))))
  (if xrefset (setq xrefcounter (sslength xrefset)) (setq xrefcounter 0))
  (while (> xrefcounter 0)
    (setq xrefcounter (- xrefcounter 1))
    (setq xrefename (ssname xrefset xrefcounter))
    (setq insobj (vlax-ename->vla-object xrefename))
    (setq blkdata (tblsearch "block" (vla-get-name insobj)))
    (if (assoc 1 blkdata)
      (progn
	(if (= :vlax-true (vla-get-hasextensiondictionary insobj))
	  (progn
	    (setq extdict (vla-getextensiondictionary insobj))
	    (vlax-for dictmember extdict
	      (setq membname (vla-get-name dictmember))
	      ;find the over ride dictionary if there is one
	      (if (= (strcase membname) "AEC_PROP_SET_OVERRIDES")
		(progn
		  (setq ovrdict dictmember)
		  ;since we can't delete the override dictionary itself,
		  ;delete the container object(s) in the over ride dictionary
		  (vlax-for ovrdictmemb ovrdict
		    (vla-delete ovrdictmemb)
		    );for
		  );true progn
		);if
	      );for
	    );true progn
	  );if has ext dict
	);true progn
      );if xref
    );while xrefs
  (delwrongtags)
  );defun deldataover

(defun delwrongtags ( / workingset deltaggrp sameasfirst)
  (princ "\nChecking for erroneous tags\n")
  ;select all MV_blocks in drawing,
  (setq workingset (ssget "X" (list '(0 . "AEC_MVBLOCK_REF"))))
  (if workingset
    (progn
      (setq workingcounter (sslength workingset))
      (while (> workingcounter 0)
	(princ "\nNumber of remaining tags: \n")
	(princ workingcounter)
	(princ "\n\|")
	(princ "\n\/")
	(princ "\n\-")
	(princ "\n\\")
	(setq workingcounter (- workingcounter 1))
	(setq workingname (ssname workingset workingcounter))
	(setq workingitem (entget workingname))
	;that have an anchor
	(if (assoc 360 workingitem)
	  (setq itemanchor (entget (cdr (assoc 360 workingitem))))
	  )
	(if itemanchor
	  (progn
	    ;that is a tag anchor
	    (if (= "AEC_ANCHOR_TAG_TO_ENT" (strcase (cdr (assoc 0 itemanchor))))
	      (progn
		(setq taggeditem (entget (cdr (assoc 345 itemanchor))))
		;whose tagged item has attached data
		
		(setq delflag T)
		(if (/= nil (setq istheredata (member '(102 . "{ACAD_XDICTIONARY") taggeditem)))
		  ;check the 360 group to make sure that we are reading the correct xdictionary
		  ;by testing it against (3 . "AEC_PROPERTY_SETS")
		  ;if it passes the above test skip it and exit the loop, otherwise
		  ;continue in case there is more than one 102-360-102 group in the ent data
		  (while (/= nil istheredata)
		    (setq 360ent (entget (cdr (assoc 360 istheredata)) '("*")))
		    (if (and (/= nil 360ent) (/= nil (assoc 3 360ent)))
		      (if (= "AEC_PROPERTY_SETS" (strcase (cdr (assoc 3 360ent))))
			(progn			  
			  ;if data has been attached, then removed, it leaves the dictionary
			  ;so we need to check to see if there are actually any entries in it
			  ;get the property sets dictionary for the item (it follows the item's xdict)
			  (setq nextdict (dictnext (cdr (assoc -1 360ent)) T))
			  (while nextdict
			    ;get the first property set in the item's property sets dictionary
			    (setq entrylist (member (assoc 3 nextdict) nextdict))
			    ;if we find a property set, clear the delete flag
			    (if entrylist
			      (progn
				;to keep existing tag
				(setq delflag nil)
				;to delete newly created tag if this creates multiple instances, ie
				;if we discover another tag that is referencing the selected space
				;we need to set a flag to ask the user if they would like to keep both
				(if (equal (cdr (assoc -1 entdata)) (cdr (assoc -1 taggeditem)))
				  ;and if it is not the first tag created
				  (if (not (equal doubledown workingname))
				    (setq sameasfirst T);set a marker
				    )
				  )
				);true progn
			      );if entrylist
			    (setq nextdict (dictnext (cdr (assoc -1 360ent))))
			    );while nextdict
			  
			  (setq istheredata nil)
			  );true progn
			(progn
			  (setq istheredata (member '(102 . "{ACAD_XDICTIONARY") (cdr istheredata)))
			  );false progn
			);if AEC Property Sets
		      );if
		    );while
		    
		  ;if it does not have a reference, then delete it
		  );if 102 group
		(if delflag
		  (if deltaggrp
		    (ssadd workingname deltaggrp)
		    (setq deltaggrp (ssadd workingname))
		    )
		  )
		);true progn
	      );if
	    );true progn
	  );if anchor
	);while workingcounter
      );true progn
    );if
  (if (and sameasfirst doubledown)
    (progn
      (setq keeper
	     (strcase
	       (getstring "\nThis Utility created a duplicate Tag on the selected item. \nWould you like to keep the duplicate? Yes or No? <N>: ")
	       )
	    )
      (if (= "" keeper) (setq keeper "N"))
      (if deltaggrp
	(progn
	  (if (= "Y" (substr keeper 1 1));cond test
	    (ssdel doubledown deltaggrp); it has a duplicate, keep the first tag
	    (ssadd doubledown deltaggrp); it has a duplicate, delete the first tag
	    );if yes - keeper
	  );true progn
	(if (/= "Y" (substr keeper 1 1))
	  (setq deltaggrp (ssadd doubledown)); it has a duplicate, delete the first tag
	  )
	);if deltaggrp
      );if equal true progn - this is the first tag
    );if - there is a second tag on the same space and we marked it earlier
  (if deltaggrp
    (command "erase" deltaggrp "")
    );if deltaggrp
  (princ "\nDone Checking\n")
  );defun delwrongtags

 ...

 

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 4 of 12
Hugh_Compton
in reply to: Hugh_Compton

Gary

 

I gave your code a quick test and it works well!   I will try and disect it when I have a bit more time but you definitely have a very good grasp of Property Sets and tags.

 

Thanks

Message 5 of 12
Gary_J_Orr
in reply to: Hugh_Compton

You can get rid of the (delwrongtags) call in the main function  (as well as that entire code block) to address your original post (simply deleting override property sets so the tag can see the original property sets within any xrefs).

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 6 of 12
Hugh_Compton
in reply to: Hugh_Compton

 

I've shortened the Lisp as per your last post, it now runs very quickly.  What would be good is if instead of having to run the command to start the lisp, it was run every time the 'AecScheduleTag' command is used.... I can write an Event Reactor in dotnet but is it possible for it to be in the lisp? (I am terrible at using lisp code).... 

Message 7 of 12
Gary_J_Orr
in reply to: Hugh_Compton

short answer... yes it is possible... but that one might take a while to remember (I haven't done anything serious with lisp since 08/09)... but I might be able to dig up some other old code as a starting point.
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 8 of 12
Hugh_Compton
in reply to: Hugh_Compton

Hi Gary

 

Don't worry about looking into this - it's pretty easy to write a command catcher in .net.  What I'm not sure about is whether there is any background overhead of CAD catching the tagging command....

 

Your code is still highly useful and will not only save time but will also reduce errors (i.e. when a property set has it's value changed and the tags need to be updated).

Message 9 of 12
Gary_J_Orr
in reply to: Hugh_Compton

well heck, here I was hoping to have something to do today (I've been out of work for a loooong time and have begun to feel useless without problems to solve 😉

 

but here is a list of the available reactors in lisp (pass-throughs to Active-X actually) from the help files:

 

reactor-type

One or more of the following symbols:

:VLR-AcDb-Reactor

:VLR-Command-Reactor

:VLR-DeepClone-Reactor

:VLR-DocManager-Reactor

:VLR-DWG-Reactor

:VLR-DXF-Reactor

:VLR-Editor-Reactor

:VLR-Insert-Reactor

:VLR-Linker-Reactor

:VLR-Lisp-Reactor

:VLR-Miscellaneous-Reactor

:VLR-Mouse-Reactor

:VLR-Object-Reactor

:VLR-SysVar-Reactor

:VLR-Toolbar-Reactor

:VLR-Undo-Reactor

:VLR-Wblock-Reactor

:VLR-Window-Reactor

:VLR-XREF-Reactor

with one "usage" example:

Constructs an editor reactor that notifies of a command event

(vlr-command-reactor data callbacks) 

Arguments

 

data

Any AutoLISP data to be associated with the reactor object; otherwise nil if no data is to be associated with the reactor.

 

callbacks

A list of pairs of the following form:

(event-name . callback_function)

where event-name is one of the symbols listed in the “Command reactor events” table below, and callback_function is a symbol representing a function to be called when the event fires. Each callback function accepts two arguments:

reactor_object The VLR object that called the callback function.

list A list containing a single element, the string identifying the command.

 

hopefully the cut/paste doesn't screw a bunch of stuff up...

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 10 of 12
Hugh_Compton
in reply to: Hugh_Compton

 

Thanks Gary - that looks very useful...

 

I've opted for a fairly simple approach and add it to my QSave command using the CUI editor (I use CTRL + S to save so I just added it to this keyboard shortcut).  It is such a quick routine that I am sure I can take the few extra milliseconds it takes for drawings to save. 

 

Not sure how somebody of your obviously high calibre can be out of work 🙂

 

Take it easy,

Hugh

Message 11 of 12
Gary_J_Orr
in reply to: Hugh_Compton

That last is simple... someone did a study of CAD/BIM Managers a few years ago and discovered that most of them had a degree in AEC or programming, so now that has become a minimum requirement now... My 15 plus years of doing this means nothing to the hiring managers/recruiters/automated systems that check against those minimum requirements...
I can't get back to production either because everyone puts me in that "over-qualified" group, not believing that I would be just as happy solving design issues (which draws on my previous 15 years in construction as well) as I am solving software issues/challenges...
But oh well...
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 12 of 12
Gary_J_Orr
in reply to: Hugh_Compton

Just so you know: the delwrongtags part, while considerably slower, also makes sure that you don't have any tags that are referencing items that have not yet been tagged in the source drawing... just adds to the reduction of errors overall...

 

now for the fun part:

I couldn't help myself and went in a built a complex command reactor that could handle a variety of events and take action depending on what command was doing what, then realized just how complicated it would be to explain such and simplified it back to address your specific question (which is now redundant since you "opted out" with your qsave function but what the heck)...

 

;define the event handler to call the required function
;to keep it simple this requires that you already have the required function loaded
(defun AEC_TAG_Reaction (fevent flist / )
  ;the following statements are to help with debugging
  (princ "\nReactor Data&colon; ")
  (princ (vlr-data fevent))
  ;we don't need this variable but it helps us in some circumstances
  (setq CurrCMD (strcase (vl-princ-to-string (car flist))))
  (if (= CurrCMD (strcase "AECSCHEDULETAG"))
    (progn
      (princ "\nWe completed an AEC Tag Event\n")
      ;requires that you have already loaded the function of course
      (c:deldataover)
      )
    (princ "\nNothing to do\n")
    );end if
  );end AEC_TAG_Reaction defun

;create the reactor
;wrapping it in a function isn't required but gives us control
;saving it to a variable lets us work with it when needed (like removing it)
;add to acaddoc.lsp (acad.lsp if you reload for each doc) or an .mnl file
;to initialize after loading call with (Create_Reactor)
(defun Create_Reactor ( / )
  (if (not *AEC_TAG_Reactor*)
    (setq *AEC_TAG_Reactor*
	   (vlr-command-reactor
	     "GOMO Command Reactor"
	     '(
	       (:vlr-commandEnded . AEC_TAG_Reaction)
	       );reactor list
	     );reactor
	  );setq
    );end if
  );end Create_Reactor defun

;here is a helpful function for clearing during testing
;this is specific to this example
;it can also be used in a doc reactor that fires when you close a doc
(defun CleanCMDReactor ( / )
  (if *AEC_TAG_Reactor*
    (vlr-remove *AEC_TAG_Reactor*)
    (setq *AEC_TAG_Reactor* nil)
    )
  )

 

BTW: the "work" functions that are in the "deldataover" command are mostly activex so it should be fairly simple to translate into Visual Studio for Visual Basic/C++

The "managed" wrappers in .net may limit you a bit so load the native "oldstyle" activex components and have fun (grins)

-Gary

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)

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

Post to forums  

Autodesk Design & Make Report

”Boost