Author Topic: Seperating Xrefs from blocks  (Read 10262 times)

0 Members and 1 Guest are viewing this topic.

Krushert

  • Seagull
  • Posts: 13679
  • FREE BEER Tomorrow!!
Re: Seperating Xrefs from blocks
« Reply #15 on: August 22, 2006, 12:41:21 PM »
Just watching and learning.

<long story don't ask)
I + XI = X is true ...  ... if you change your perspective.

I no longer CAD or Model, I just hang out here picking up the empties beer cans

Hangman

  • Swamp Rat
  • Posts: 566
Re: Seperating Xrefs from blocks
« Reply #16 on: August 22, 2006, 01:45:47 PM »
I wish I could get away with not using nested xrefs, but unfortunately, when an architects drafter or some other discipline sends us drawings, nine times out of ten, there are xrefs within xrefs within xrefs.  Most of the time I mearly use these to overlay my drawing and take the time to sketch what they have so I don't have to fight their drawings.  but then, my fellow drafters use their drawings for "simplicity & time" in putting our drawings together.  It's the changes & re-editing that's the killer.
So, the most we have in our drawings is an xref'ed title block and gridlines (depending on the project size).  We BIND our drawings when sending them to the architect or other discipline, which brought me to this topic.  Not very often, but on occasion we have a nested xref & unreferenced image(s) which crashes the LiSP.

Ooops, (what a monolog   :oops: )
Anyway, ok, I understand the referenced vs unreferenced with blocks & xrefs.  And Images for that matter.  I'm just not understanding the correlation of the connection.  I know the image isn't a raster so it has to be connected differently than a block, but how it's connected is a mystery.
Quote
To see if an xref/image is 'referenced' you will need to search the database (layouts) and see if those objects have been inserted anywhere.  If you are checking in the current drawing, then you can use (ssget "x" .... ) to see, if you want to use ObjectDBX to check this stuff out, then you will have to search through the definition of the layouts (their block definition).
Ok, so I want to check the current drawing as you mentioned, (I'm assuming that by checking the current drawing, it will also check the layout tabs ??) for both a nested xref and an unreferenced image.  As I mentioned in my monolog, there are xrefs that we use, but there are others from other disciplines caught in the drawing as well.  Therefore, I can't search for it by name, but I have to at least be alerted to the fact that I have a nested xref in the drawing, referenced or unreferenced.  If I list ALL the xrefs, then that defeats the purpose of the BIND, so I need to list only those xrefs that are nested or tier two or deeper.  So I'm not sure that I need to ObjectDBX to check them out, I just want to know that they are there .??
With the Images, it's appearing that the only way to automatically detach them is to know their name ??  I don't care about the images, if they are there, great, they get bound with the drawing when running the BIND command.  But if they are unreferenced, then the BIND crashes.  I want to simply detach them, I don't care what their name is or where they came from, just detach if they are unreferenced.

Ok, I think you lost me there, I'm sort of understanding your explanation, but I'm not seeing what's right under my nose.    :-(

I thank you for your patience though, and anyone who can help knock this into my thick skull, please bring in your expertise as well, I could use a swift kick in the head.   ^-^
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Seperating Xrefs from blocks
« Reply #17 on: August 22, 2006, 02:25:34 PM »
Here is one for looking for nested xrefs.  This will print to the screen in a tree format the nesting levels.
Code: [Select]
(defun ListXrefs (Doc / XrefNameList)

(defun FindInList (LstItem Lst)

(if (assoc LstItem Lst)
 (assoc LstItem Lst)
 (while
  (or
   Lst
   (not (assoc LstItem Lst))
  )
  (setq Lst
   (vl-remove-if
    'null
    (mapcar
     'cadr
     Lst
    )
   )
  )
 )
)
)
;--------------------------------------------------
(defun PrintResults (Lst StrSpace)
(foreach Item Lst
 (if (equal (type Item) 'LIST)
  (PrintResults Item (strcat "  " StrSpace))
  (prompt (strcat "\n" StrSpace "|-> Nested Xref = " Item))
 )
)
)
;-----------------------------------------------------
(setq BlkCol (vla-get-Blocks Doc))
(vlax-for Blk BlkCol
 (if (= (vla-get-IsXref Blk) :vlax-true)
  (setq XrefNameList (cons (list (vla-get-Name Blk)) XrefNameList))
 )
)
(foreach XrefName XrefNameList
 (vlax-for Obj (vla-Item BlkCol (car Xrefname))
  (if
   (and
    (= (vla-get-ObjectName Obj) "AcDbBlockReference")
    (vlax-property-available-p Obj 'Path)
   )
   (setq XrefNameList
    (subst
     (cons (car XrefName) (cons (FindInList (vla-get-name Obj) XrefNameList) (cdr (assoc (car XrefName) XrefNameList))))
     (assoc (car XrefName) XrefnameList)
     (vl-remove-if '(lambda (x) (= (car x) (vla-get-Name Obj))) XrefNameList)
    )
   )
  )
 )
)
;(print XrefNameList)
(foreach i XrefNameList
 (prompt (strcat "\n Main Xref = " (car i)))
 (PrintResults (cdr i) "  ")
)
(princ)
)
I might have posted this before, I'm not sure right now.
Call this like
(ListXrefs (vla-get-ActiveDocument (vlax-get-Acad-Object)))
Here are the results
Quote
Command: (ListXrefs (vla-get-ActiveDocument (vlax-get-Acad-Object)))

 Main Xref = XrefMain
    |-> Nested Xref = Xref2
      |-> Nested Xref = Cube
    |-> Nested Xref = Xref1
 Main Xref = XREF

As for images, you will have to see if the dictionary exist, if it does, then there are images attached to the drawing, and you can search for each one, then if it exist, then don't erase it, but if it doesn't then delete the entry in the dictionary.

Code: [Select]
(not
  (vl-catch-all-error-p
   (setq ImDict
    (vl-catch-all-apply
     '(lambda ()
      (vla-Item
       (vla-get-Dictionaries
        (vla-get-ActiveDocument
         (vlax-get-Acad-Object)
        )
       )
       "ACAD_IMAGE_DICT"
      )
     )
    )
   )
  )
 )

This will return true if the dictionary exist, and nil if not.  I will have to do a little more research on images, as I don't see an easy way to get the info you want.

Hope this helps so far though.

FYI... another reason why xref/images are unreferenced (I think) is that they can't find the file they are pathed to.
Tim

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

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Seperating Xrefs from blocks
« Reply #18 on: August 22, 2006, 02:39:36 PM »
Can you post the portion of code that deals with the binding?  Maybe we can error proof that.
Tim

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

Please think about donating if this post helped you.

Hangman

  • Swamp Rat
  • Posts: 566
Re: Seperating Xrefs from blocks
« Reply #19 on: August 23, 2006, 12:26:16 PM »
Uuummmm, ...  Well ...  Yessir I can post it.  It's quite simple really.
Code: [Select]
  (command "purge" "A" "" "N")
  (command "purge" "A" "" "N")
  (command "purge" "A" "" "N")
  (command "qsave")
  (command "-xref" "R" "*")
  (command "-xref" "B" "*")
  (command "qsave")

It's a ... kind of embarrasing to post this, it's so simple.  But it does the trick until you have a nested xref, then it goes awry.
The program searches for the bind path & verifies it's there.  If not, it creates it, if so, saves the drawing as it is to the bind path.
It then changes to paperspace, zoom extents and sets the current layer to zero.
It then runs the code above and then closes.
I need to place the xref search and Image search between the purging and the -xref reload and bind.

I guess this is where the code would get so much more technical.
I couldn't find a way to do this with LiSP, and I don't know VLA nor am I successful in learning it.  So this is where I need your help.
And thank you again for your help.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hangman

  • Swamp Rat
  • Posts: 566
Re: Seperating Xrefs from blocks
« Reply #20 on: August 23, 2006, 12:55:51 PM »
Ok, when I run your most recently posted code, I get the following return

Command: AP
APPLOAD TST-XRefList3.lsp successfully loaded.

Command:
Command:
Command: (ListXrefs (vla-get-ActiveDocument (vlax-get-Acad-Object)))

Code: [Select]
Main Xref = 4
 Main Xref = 3
 Main Xref = 2
 Main Xref = 1
 Main Xref = TESTdwg_ARW-TTL
My drawing (TESTdwg_0-75.dwg) consists of (5) xref dwgs.  These drawings are 1,2,3,4, & TESTdwg_ARW-TTL
The drawing '3' was renamed, so it is 'unreferenced' or 'can't be found' in the 0-75.dwg.
The last dwg, ARW-TTL has two xrefs in it; S2-8-11 & S2-8-12.  The S2-8-12 is 'unreferenced' or 'can't be found' in the ARW-TTL dwg.
So the code is listing the xrefs "assigned" (if you will) to the drawing 0-75.dwg, but it is not listing the xrefs within the xref ARW-TTL, the nested xrefs.

I hope this bit helps, ...  I don't know how to help you trouble shoot this thing.

<Message Updated>

This is what I get when running the code Jeff posted earlier.

Command: ap
APPLOAD TST-XRefList4_JM-swamp.lsp successfully loaded.

Command:
Command:
Command: (xreftree)
Code: [Select]
((0 . "4") (0 . "3") (0 . "2") (0 . "1") (0 . "TESTdwg_ARW-TTL"))
Basically the same listing.  It doesn't tell you that one xref is not found nor does it tell you there are nested xrefs and one of those are not found.
« Last Edit: August 23, 2006, 01:09:33 PM by Hangman »
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Seperating Xrefs from blocks
« Reply #21 on: August 23, 2006, 01:24:36 PM »
If you want a routine to reload and bind xrefs, maybe this will work for you.
Code: [Select]
(defun ReloadBindXrefs (Doc / XrefList LstLen)

(vlax-for Blk (vla-get-Blocks Doc)
 (if (= (vla-get-IsXref Blk) :vlax-true)
  (progn
   (vla-Reload Blk)
   (vla-Bind Blk :vlax-true)
   (if
    (and
     (= (vla-get-IsXref Blk) :vlax-true)
     (not (vl-position (vla-get-Name Blk) XrefList))
    )
    (setq XrefList (cons Blk XrefList))
   )
  )
 )
)
(setq LstLen (length XrefList))
(while
 (and
  (> LstLen 0)
  (>= LstLen (setq LstLen (length XrefList)))
 )
 (foreach Blk XrefList
  (if
   (or
    (= (vla-get-IsXref Blk) :vlax-false)
    (and
     (vla-Bind Blk :vlax-true)
     (= (vla-get-IsXref Blk) :vlax-true)
    )
   )
   (setq XrefList (vl-remove Blk XrefList))
  )
 )
)
(foreach Blk XrefList
 (prompt (strcat "\n Unable to bind xref:" (vla-get-Name Blk)))
)
(princ)
)
To be called like (for current drawing)
(ReloadBindXrefs (vla-get-ActiveDocument (vlax-get-Acad-Object)))


In respones to your last post.  Try this routine and see if it works for you.  It will prompt which drawings it could not bind if any.
Tim

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

Please think about donating if this post helped you.

Hangman

  • Swamp Rat
  • Posts: 566
Re: Seperating Xrefs from blocks
« Reply #22 on: August 23, 2006, 01:55:16 PM »
I'll have to play with this a bit.
This is what I get at the moment when I run it.

Command: ap
APPLOAD TST-XRefList5.lsp successfully loaded.

Command:
Command:
Command: ReloadBindXrefs
Unknown command "RELOADBINDXREFS".  Press F1 for help.

Command: (ReloadBindXrefs (vla-get-ActiveDocument (vlax-get-Acad-Object)))
Code: [Select]
; error: Automation Error. File access error

This is going to be trick (at least for me), but I have a bit I can go study and learn why they work the way they do.

Thanks Tim for your help.  I appreciate it.  I know you've learned a think or two but you've put a lot of time in to find a solution for me.  Thank you.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Seperating Xrefs from blocks
« Reply #23 on: August 23, 2006, 01:59:47 PM »
Can you post a zip that has the drawings you are testing these routines on?  I would like to see what I can come up with.  I'll only be here or about another hour and a half today.
Tim

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

Please think about donating if this post helped you.

Hangman

  • Swamp Rat
  • Posts: 566
Re: Seperating Xrefs from blocks
« Reply #24 on: August 24, 2006, 11:09:59 AM »
Tim,
Yeah, I'll do that.

It finally dawned on me what you were asking earlier about posting the code and try to work out the errors.
So, here's another angle to this dilemma until we can find this fix.

When I run the program, and I have a nested xref or an xref that is not found, I get the following error:
Code: [Select]
Command: -xref
Enter an option [?/Bind/Detach/Path/Unload/Reload/Overlay/Attach] <Attach>: R
Enter xref name(s) to reload: *
Reload Xref "ARW-TTL": D:\temp\Tests\Xref\ARW-TTL.dwg
D:\temp\Tests\Xref\ARW-TTL.dwg has not changed.

Reload Xref "1": D:\temp\Tests\Xref\1.dwg
D:\temp\Tests\Xref\1.dwg has not changed.

Reload Xref "2": D:\temp\Tests\Xref\2.dwg
D:\temp\Tests\Xref\2.dwg has not changed.

Reload Xref "3": D:\temp\Tests\Xref\3.dwg
"3.dwg" cannot be found.
*Invalid*
Error: Function cancelled

How can I catch that error so if it occurs, an ALERT will pop up telling the user there are problems ??

As the program is right now, when the error crashes, it leaves the drawing open in the BIND directory.  If the user is not paying real close attention, they will not notice the error and run the program again which then creates the drawing in the BIND\BIND directory.  I have had a user who was zipping through his drawings and finally realized he had been binding the same drawing over and over because of the crash.  So his directory structure was something like:
D:\Drawings 2005\05132\BIND\BIND\BIND\BIND\BIND\BIND\BIND\BIND\BIND\BIND\BIND\BIND\BIND\BIND\05132_S3-2.dwg

So if an error occurs, I want to throw up an ALERT so the user will not continue blissfully down the wrong path.
Any ideas on how to reference an error ??
Code: [Select]
  (setq $error$ $error) ;;; ??
  (if (/= $error$ nil) ;;;  I don't know how I would work this line here
    (ALERT "an error has occured, please check your drawing before continuing."))

<message updated>

I do have this up in the beginning of my program
Code: [Select]
(defun $error (msg /)
    (if (or (= msg "Function cancelled")
            (/= msg "quit / exit abort")
        )
        (princ (strcat "Error: " msg))
    )
    (command ".undo" "e" "undo" "")
    (command ".redraw")
    (setvar "cmdecho" echoprv)
    (setvar "expert" xprtorg)
    (setq *error* old_err)
    (setq echoprv nil)
    (princ)
  );end error
« Last Edit: August 24, 2006, 11:15:50 AM by Hangman »
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Seperating Xrefs from blocks
« Reply #25 on: August 24, 2006, 11:31:07 AM »
Here you go.  I didn't know it would error if it couldn't relaod an xref.  This version will print to the command line which drawings could not be bound.
Code: [Select]
(defun ReloadBindXrefs (Doc / XrefList LstLen TroubleList)

(vlax-for Blk (vla-get-Blocks Doc)
 (if (= (vla-get-IsXref Blk) :vlax-true)
  (progn
   (if
    (vl-catch-all-error-p
     (vl-catch-all-apply 'vla-Reload (list Blk))
    )
    (setq TroubleList (cons Blk TroubleList))
    (progn
     (vla-Bind Blk :vlax-true)
     (if
      (and
       (= (vla-get-IsXref Blk) :vlax-true)
       (not (vl-position (vla-get-Name Blk) XrefList))
      )
      (setq XrefList (cons Blk XrefList))
     )
    )
   )
  )
 )
)
(setq LstLen (length XrefList))
(while
 (and
  (> LstLen 0)
  (> LstLen (setq LstLen (length XrefList)))
 )
 (foreach Blk XrefList
  (if
   (or
    (= (vla-get-IsXref Blk) :vlax-false)
    (and
     (vla-Bind Blk :vlax-true)
     (= (vla-get-IsXref Blk) :vlax-true)
    )
   )
   (setq XrefList (vl-remove Blk XrefList))
  )
 )
)
(foreach Blk (append XrefList TroubleList)
 (prompt (strcat "\n Unable to bind xref: " (vla-get-Name Blk)))
)
(princ)
)
Quote from:  Acad command line
Command: (ReloadBindXrefs (vla-get-ActiveDocument (vlax-get-Acad-Object)))

 Unable to bind xref: Xref1
 Unable to bind xref: Xref2
 Unable to bind xref: XrefMain
 Unable to bind xref: Cube
« Last Edit: August 24, 2006, 11:32:30 AM by T.Willey »
Tim

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

Please think about donating if this post helped you.

Hangman

  • Swamp Rat
  • Posts: 566
Re: Seperating Xrefs from blocks
« Reply #26 on: August 24, 2006, 11:40:24 AM »
Cool Tim,
I'll go play with it.

I've figured out a way to display my error message by adding to my error control code.
Code: [Select]
(defun $error (msg /)
    (if (or (= msg "Function cancelled")
            (/= msg "quit / exit abort")
        )
        (princ (strcat "Error: " msg))
    )
    (command ".undo" "e" "undo" "")
    (command ".redraw")
    (setvar "cmdecho" echoprv)
    (setvar "expert" xprtorg)
    (ALERT "ERROR !!! There are nested xref's and / or unreferenced images found in your drawing.") ;;; <<<<<
    (setq *error* old_err)
    (setq echoprv nil)
    (princ)
    (command "close" "Y") ;;; <<<<<
  );end error

It's not very pretty, but it does the trick until I can find a way to automatically detach the unreferenced stuff.   Thanks Tim.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Seperating Xrefs from blocks
« Reply #27 on: August 24, 2006, 11:55:44 AM »
If you want to detach the ones that can't be found, then we only need to change one part of the code I just posted.
Code: [Select]
(vlax-for Blk (vla-get-Blocks Doc)
 (if (= (vla-get-IsXref Blk) :vlax-true)
  (progn
   (if
    (vl-catch-all-error-p
     (vl-catch-all-apply 'vla-Reload (list Blk))
    )
    (setq TroubleList (cons Blk TroubleList))
    (progn
     (vla-Bind Blk :vlax-true)
     (if
      (and
       (= (vla-get-IsXref Blk) :vlax-true)
       (not (vl-position (vla-get-Name Blk) XrefList))
      )
      (setq XrefList (cons Blk XrefList))
     )
    )
   )
  )
 )
)
to
Code: [Select]
(vlax-for Blk (vla-get-Blocks Doc)
 (if (= (vla-get-IsXref Blk) :vlax-true)
  (progn
   (if
    (vl-catch-all-error-p
     (vl-catch-all-apply 'vla-Reload (list Blk))
    )
    (if
     (vl-catch-all-error-p
      (vl-catch-all-apply 'vla-Detach (list Blk))
     )
     (setq TroubleList (cons Blk TroubleList))
     (prompt (strcat "\n Detached xref: " (vla-get-Name Blk)))
    )
    (progn
     (vla-Bind Blk :vlax-true)
     (if
      (and
       (= (vla-get-IsXref Blk) :vlax-true)
       (not (vl-position (vla-get-Name Blk) XrefList))
      )
      (setq XrefList (cons Blk XrefList))
     )
    )
   )
  )
 )
)

The new part will try and detach it, if it can it will tell you it detached it, if not it will add it to the list of xref's it wasn't able to do anything with.  Hope that helps.
Tim

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

Please think about donating if this post helped you.

GDF

  • Water Moccasin
  • Posts: 2081
Re: Seperating Xrefs from blocks
« Reply #28 on: August 24, 2006, 04:41:13 PM »
Tim

I just caught this thread and tried your revised routine.
Works great, I can sure use this one. Thanks.

Gary
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Seperating Xrefs from blocks
« Reply #29 on: August 24, 2006, 04:52:45 PM »
Tim

I just caught this thread and tried your revised routine.
Works great, I can sure use this one. Thanks.

Gary
Cool! 8-)
Thanks for testing Gary.

Edit: Gary/all the way it's coded, it should work with drawings opened with ObjectDBX.  It will print to the current drawing opened.
« Last Edit: August 24, 2006, 04:54:00 PM by T.Willey »
Tim

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

Please think about donating if this post helped you.