TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: CADwoman on February 18, 2005, 11:06:50 AM
-
Hi,
Does anyone know of a lisp that can detach all unloaded xrefs? I'm not sure if this is possible at all.
Thanks
-
Written very quickly. Read "may require an edit or two".
Subsequently modified to sport behavior requested by CADwoman:
For every unloaded xref:
▪ Dump it if it's an overlay
▪ Otherwise reload it
I've no idea what to call it so that's up to you. :)
(defun c:YouNameIt
( /
_SafeInvoke
data
flags
blocks
detachList
reloadList
)
(defun _SafeInvoke ( object method )
(null
(vl-catch-all-error-p
(vl-catch-all-apply
'vlax-invoke-method
(list
object
method
)
)
)
)
)
(while (setq data (tblnext "block" (null data)))
(if
(and
(eq 4
(logand 4
(setq flags
(cdr (assoc 70 data))
)
)
)
(assoc 71
(entget
(tblobjname "block"
(cdr (assoc 2 data))
)
)
)
)
(if (eq 8 (logand 8 flags))
(setq detachList
(cons
(cdr (assoc 2 data))
detachList
)
)
(setq reloadList
(cons
(cdr (assoc 2 data))
reloadList
)
)
)
)
)
(if (or detachList reloadList)
(setq blocks
(vlax-get-property
(vlax-get-property
(vlax-get-acad-object)
'ActiveDocument
)
'Blocks
)
)
)
(foreach name detachList
(princ
(strcat
"Unloading "
name
" ... "
(if
(_SafeInvoke
(vlax-invoke-method
blocks
'Item
name
)
'Detach
)
"\n"
" <error>\n"
)
)
)
)
(foreach name reloadList
(princ
(strcat
"Reloading "
name
" ... "
(if
(_SafeInvoke
(vlax-invoke-method
blocks
'Item
name
)
'Reload
)
"\n"
" <error>\n"
)
)
)
)
(princ)
)
Edit1: Modified per Mr. Madsen's excellent tip later in this thread.
Edit2: Temporarilly remove function definition.
Edit3: Added abilities per CADwoman's request.
Edit4: Fixed up name of variable.
-
Thanks! You're amazing! This is exactly what I want. I wonder if we can add some intelligence to it so that it will detach only unloaded xrefs that are "overlayed" and reloaded the ones that are "attached".
Written very quickly. Read "may require an edit or two".
(defun c:DetachUnloadedXrefs ...
<snipperage>
)
-
Please, you're making my wife laugh. But seriously, a little bit of study and you could pen little utilities like this yourself. Consider looking into Mr. Madsen's most excellent LISP course(s); highly recommended.
Forgive me, I find humour in the strangest places:
This is exactly what I want. <cough> I wonder if we can add ...
The overlay / attach status is bit coded in the dxf group 70 flags (value 8) so it would require nominal effort to add that functionality.
Have a great weekend,
Michael
-
Michael, you can find unloaded xrefs only by looking for code 71. If present, the xref is unloaded. Otherwise it'll be missing no matter if it's unresolved or not.
-
Ahhh, behavior as noted confirmed. Thank you Stig.
I don't note that in my 2004 DXF Guide, did you observe that empirically?
(Original program updated to reflect info Stig provided).
-
It's undocumented in the DXF reference but documented in the ObjectARX docs (for AcDbBlockTableRecord::isUnloaded method).
-
Thank you Stig, great info.
Function modified to reflect CADwoman's other wants.
-
Here's a variant that does the same thing by iterating the blocks collection instead of walking the block table (I like it better than the first Q&D) ...
(defun c:YouNameIt ( / name data modList method )
(vlax-for block
(vlax-get-property
(vlax-get-property
(vlax-get-acad-object)
'ActiveDocument
)
'Blocks
)
(if
(and
(eq :vlax-true
(vlax-get-property
block
'IsXref
)
)
(assoc 71
(setq data
(entget
(tblobjname
"block"
(setq name
(vlax-get-property
block
'Name
)
)
)
)
)
)
)
(setq modList
(cons
(list
name
block
(if (eq 8
(logand 8
(cdr (assoc 70 data))
)
)
'Detach
'Reload
)
)
modList
)
)
)
)
(if (null modList)
(princ "No qualifying xrefs.\n")
(foreach sublist
(vl-sort
modList
'(lambda (a b) (< (car a) (car b)))
)
(princ
(strcat
(vl-princ-to-string
(setq method
(caddr subList)
)
)
"ing "
(car sublist)
" ... "
(if
(null
(vl-catch-all-error-p
(vl-catch-all-apply
'vlax-invoke-method
(list
(cadr sublist)
method
)
)
)
)
"<done>\n"
"<error>\n"
)
)
)
)
)
(princ)
)
-
Thank you! I'm just starting to write LISPs, so I have lots to learn. Thanks again. I'll look for Mr. Madsen's LISP course.
Please, you're making my wife laugh. But seriously, a little bit of study and you could pen little utilities like this yourself. Consider looking into Mr. Madsen's most excellent LISP course(s); highly recommended.
Forgive me, I find humour in the strangest places:
This is exactly what I want. <cough> I wonder if we can add ...
The overlay / attach status is bit coded in the dxf group 70 flags (value 8) so it would require nominal effort to add that functionality.
Have a great weekend,
Michael
-
i was playin with this a little, and as usual, i'm missin sumthin.
i'd like it to detach unloaded xrefs, whether they are attached or overlay'd, quietly. no prompts, no muttering, no nuttin. i was playin with removing some of the prompts, and it killed the function
-
You can see if this will work for you.
(defun XrefBindDetach (Doc / )
; Doc = document object that you want to preform the routine on
; Will detach xref's that are not loaded, and will bind (as block)
; xref's that are loaded.
(vlax-for Blk (vla-get-Blocks Doc)
(if (= (vla-get-IsXref Blk) :vlax-true)
(if
(vl-catch-all-error-p
(vl-catch-all-apply 'vla-get-XrefDatabase (list Blk))
)
(vla-Detach Blk)
(vla-Bind Blk T) ; Remove this line if you don't want to bind loaded ones.
)
)
)
(princ)
)
-
i needed it to work in the current file so i took a swing at modifying the code thusly:
(defun XrefDetach ()
(vlax-for Blk (vla-get-Blocks (vla-get-activedocument (vlax-get-acad-object)))
(if (= (vla-get-IsXref Blk) :vlax-true)
(if
(vl-catch-all-error-p
(vl-catch-all-apply 'vla-get-XrefDatabase (list Blk))
)
(vla-Detach Blk)
)
)
)
(princ)
)
it'll detach unloaded overlay'd, but blows up on unloaded attached and i get this message:
Command: (XREFDETACH)
; error: Automation Error. Description was not provided.
so i've noodled something up somewhere :cry:
-
Your code worked here with attached and overlay'ed. Are the xref's nested? That may be a problem. Can you post a sample drawing? That is weird.
-
that's it, it is nested in another xref and attached to this file on it's own. that means it can't be detached until after it's parent xref is detached.
i'd post a sample, but the smallest file is over 25mb and all of it is propietary. at lunch i'll see if i can't build a sample that is somewhat smaller.
thanks for the time.
-
further info;
if an xref is unloaded but nested (attached) in an xref that is loaded (attached), i get the same error message.
is there a way to skip nested xrefs?
-
I can look into it when I have time. I'm not sure how to check to see if something is nested, unless you search all the xref's defenitions for other xrefs.
Maybe if you seach each layout instead of the block collection. I think you only get the top level xref's that way, and then you can detach unloaded one from there.
Untested code.
(defun XrefDetach ()
(vlax-for Layout (vla-get-Layouts (vla-get-activedocument (vlax-get-acad-object)))
(vlax-for i (vla-get-Block Layout)
(if
(and
(= (vla-get-ObjectName i) "AcDbBlockReference")
(vlax-property-available-p i 'Path)
(vl-catch-all-error-p
(vl-catch-all-apply 'vla-get-XrefDatabase (list i))
)
)
(vla-Detach i)
)
)
)
(princ)
)
-
hmmm... that one didn't work at all
-
Here you go. I have had some time now. The reason why the last one didn't work it because some of the tests that were run could only be run on objects for the block collection. So we shall combind both.
(defun XrefDetach (/ tmpObj)
(vlax-for Layout (vla-get-Layouts (vla-get-activedocument (vlax-get-acad-object)))
(vlax-for i (vla-get-Block Layout)
(if
(and
(= (vla-get-ObjectName i) "AcDbBlockReference")
(vlax-property-available-p i 'Path)
(setq tmpObj (vla-Item (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-Acad-Object))) (vla-get-Name i)))
(vl-catch-all-error-p
(vl-catch-all-apply 'vla-get-XrefDatabase (list tmpObj))
)
)
(vla-Detach tmpObj)
)
)
)
(princ)
)
This worked here, but you can't use it after a reload. I think that once you reload it keeps the reference to the XrefDatabase property. I don't see a way around it.
Looking back into this thread I saw this.
Michael, you can find unloaded xrefs only by looking for code 71. If present, the xref is unloaded. Otherwise it'll be missing no matter if it's unresolved or not.
But it isn't the case after you reload, at least is wasn't in my drawing.
Command: -xref
Enter an option [?/Bind/Detach/Path/Unload/Reload/Overlay/Attach] <Attach>: u
Enter xref name(s) to unload: NORT-003-E-RFPWR
Xref "NORT-003-E-RFPWR": NORT-003-E-RFPWR.DWG
"NORT-003-E-RFPWR" is unloaded.
Command: (TBLSEARCH "BLOCK" "NORT-003-E-RFPWR")
((0 . "BLOCK") (2 . "NORT-003-E-RFPWR") (70 . 12) (4 . "") (10 0.0 0.0 0.0) (1
. "NORT-003-E-RFPWR.DWG") (-2 . <Entity name: 7effc480>))
-
Tim, did you know that (tblsearch) does NOT return a complete elist?
Command: -xref
Enter an option [?/Bind/Detach/Path/Unload/Reload/Overlay/Attach] <Attach>: u
Enter xref name(s) to unload: test
Xref "test": C:\Base Maps\Jeffs Test Files\test.dwg
"test" is unloaded.
Xref "notch": C:\Base Maps\Jeffs Test Files\junk\notch.dwg
"notch" is orphaned.
Xref "sink": C:\Base Maps\Jeffs Test Files\junk\sink.dwg
"sink" is orphaned.
Command: (tblsearch "block" "test")
((0 . "BLOCK") (2 . "test") (70 . 4) (4 . "") (10 0.0 0.0 0.0) (1 . "C:\\Base
Maps\\Jeffs Test Files\\test.dwg") (-2 . <Entity name: 7e834258>))
Command: (entget (tblobjname "block" "test"))
((-1 . <Entity name: 7e834250>) (0 . "BLOCK") (330 . <Entity name: 7e834248>)
(5 . "10A") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbBlockBegin")
(70 . 4) (71 . 1) (10 0.0 0.0 0.0) (-2 . <Entity name: 7e834258>) (2 . "test")
(1 . "C:\\Base Maps\\Jeffs Test Files\\test.dwg"))
Using MP's code as a base, this has worked in my test drawings:
(defun c:YouNameIt (/ name data modList method)
(vlax-for block
(setq blocks (vlax-get-property
(vlax-get-property
(vlax-get-acad-object)
'ActiveDocument
)
'Blocks
)
)
(if
(and
(eq :vlax-true
(vlax-get-property
block
'IsXref
)
)
(assoc 71
(setq data
(entget
(tblobjname
"block"
(setq name
(vlax-get-property
block
'Name
)
)
)
)
)
)
)
(vla-detach block)
)
)
(princ)
)
-
Tim, did you know that (tblsearch) does NOT return a complete elist?
Nope. I didn't know that one Jeff. Thanks. I was thinking that I could us what Stig mentioned to see if it is unloaded, but didn't see it there. I wondered why MP did (tblobjname... instead of tblsearch.
(defun XrefDetach (/ tmpObj)
(vlax-for Layout (vla-get-Layouts (vla-get-activedocument (vlax-get-acad-object)))
(vlax-for i (vla-get-Block Layout)
(if
(and
(= (vla-get-ObjectName i) "AcDbBlockReference")
(vlax-property-available-p i 'Path)
(setq tmpObj (vla-Item (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-Acad-Object))) (vla-get-Name i)))
(assoc 71 (entget (tblobjname "block" (vla-get-Name i))))
)
(vla-Detach tmpObj)
)
)
)
(princ)
)
This code works as it should now thanks to Stig's post, and Jeff telling me what I was doing wrong.
-
thank you sir, that seems to work quite well. i have it defined and run when a drawing is closed.
-
Took a while to get there, and learned somethings new. Glad we got somthing that works the way you want it to.
-
Took a while to get there, and learned somethings new. Glad we got somthing that works the way you want it to.
again, thanks for your time.