Author Topic: Detach unloaded xrefs  (Read 14311 times)

0 Members and 1 Guest are viewing this topic.

CADwoman

  • Guest
Detach unloaded xrefs
« 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

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Detach unloaded xrefs
« Reply #1 on: February 18, 2005, 11:54:14 AM »
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. :)

Code: [Select]
(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.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CADwoman

  • Guest
Detach unloaded xrefs
« Reply #2 on: February 18, 2005, 05:58:39 PM »
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".


Quote from: MP
Written very quickly. Read "may require an edit or two".

Code: [Select]
(defun c:DetachUnloadedXrefs ...

   <snipperage>
   
)

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Detach unloaded xrefs
« Reply #3 on: February 18, 2005, 06:25:08 PM »
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:

Quote
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
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

SMadsen

  • Guest
Detach unloaded xrefs
« Reply #4 on: February 18, 2005, 10:02:24 PM »
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.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Detach unloaded xrefs
« Reply #5 on: February 18, 2005, 10:13:35 PM »
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).
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

SMadsen

  • Guest
Detach unloaded xrefs
« Reply #6 on: February 19, 2005, 07:28:49 AM »
It's undocumented in the DXF reference but documented in the ObjectARX docs (for AcDbBlockTableRecord::isUnloaded method).

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Detach unloaded xrefs
« Reply #7 on: February 19, 2005, 07:53:58 AM »
Thank you Stig, great info.

Function modified to reflect CADwoman's other wants.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Detach unloaded xrefs
« Reply #8 on: February 19, 2005, 08:58:22 AM »
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) ...

Code: [Select]
(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)

)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CADwoman

  • Guest
Detach unloaded xrefs
« Reply #9 on: February 22, 2005, 10:33:05 AM »
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.

Quote from: MP
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:

Quote
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

CADaver

  • Guest
Re: Detach unloaded xrefs
« Reply #10 on: December 14, 2005, 05:07:09 PM »
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

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Detach unloaded xrefs
« Reply #11 on: December 14, 2005, 05:36:24 PM »
You can see if this will work for you.
Code: [Select]
(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)
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CADaver

  • Guest
Re: Detach unloaded xrefs
« Reply #12 on: December 14, 2005, 06:14:03 PM »
i needed it to work in the current file so i took a swing at modifying the code thusly:

 
Code: [Select]
(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:
 
Quote
  Command: (XREFDETACH)
  ; error: Automation Error. Description was not provided.
 

so i've noodled something up somewhere   :cry:

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Detach unloaded xrefs
« Reply #13 on: December 14, 2005, 06:25:37 PM »
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.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CADaver

  • Guest
Re: Detach unloaded xrefs
« Reply #14 on: December 15, 2005, 08:43:27 AM »
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.

CADaver

  • Guest
Re: Detach unloaded xrefs
« Reply #15 on: December 15, 2005, 11:23:29 AM »
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?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Detach unloaded xrefs
« Reply #16 on: December 15, 2005, 12:00:53 PM »
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.
Code: [Select]
(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)
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CADaver

  • Guest
Re: Detach unloaded xrefs
« Reply #17 on: December 15, 2005, 01:27:55 PM »
hmmm... that one didn't work at all

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Detach unloaded xrefs
« Reply #18 on: December 15, 2005, 02:27:51 PM »
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.
Code: [Select]
(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.
Quote from: Autocad Command Line
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

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Jeff_M

  • King Gator
  • Posts: 4094
  • C3D user & customizer
Re: Detach unloaded xrefs
« Reply #19 on: December 15, 2005, 04:13:44 PM »
Tim, did you know that (tblsearch) does NOT return a complete elist?
Quote from: CommandLine
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:
Code: [Select]
(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)
)

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Detach unloaded xrefs
« Reply #20 on: December 15, 2005, 04:30:22 PM »
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.

Code: [Select]
(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.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CADaver

  • Guest
Re: Detach unloaded xrefs
« Reply #21 on: December 15, 2005, 04:56:19 PM »
thank you sir, that seems to work quite well.  i have it defined and run when a drawing is closed.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Detach unloaded xrefs
« Reply #22 on: December 15, 2005, 04:59:28 PM »
Took a while to get there, and learned somethings new.  Glad we got somthing that works the way you want it to.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CADaver

  • Guest
Re: Detach unloaded xrefs
« Reply #23 on: December 15, 2005, 05:52:30 PM »
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.