Author Topic: xref attribute work around  (Read 10645 times)

0 Members and 1 Guest are viewing this topic.

cadman6735

  • Guest
xref attribute work around
« on: March 23, 2011, 09:47:40 AM »
Hi all,

I understand that xrefs do not support attributes.  We use our border sheet as an xref (company standard) and I would like to be able to call the sheet name into the layout tab name, This is to match our Revit printing naming standard.  (Revit forces the sheet name to the print and this now company standard)  My first idea was to use attributes but learned that attributes are not supported with xrefs.  I don't really want to assign an attribute to each sheet file because that defeats the purpose of attributes.

My idea now is to just make a plot reactor that asks the user to select the text in the border sheet that holds the sheet name and as long as it has been selected once it will keep the handle and check for name change each time it is plotted or re-ask to select the name if text is deleted.

If someone has a better solution I am open to ideas.

Simple solution would be to just have the user put in the correct name in the correct CAPs on or not wait till the last minute to just forget add the name and hold up print production. But this is not an option.

Thanks

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #1 on: March 23, 2011, 10:03:54 AM »
My first suggestion would be to use an attributed block - but if this is really out of the question, you could perhaps attempt to grab the text from the block (xref) definition to avoid any user input and possible errors.

You can get all objects in a block using something like this:

Code: [Select]
(defun _getblockobjects ( name )
  (
    (lambda ( entity / result )
      (if entity
        (while (setq entity (entnext entity))
          (setq result (cons entity result))
        )
      )
    )
    (tblobjname "BLOCK" name)
  )
)

Code: [Select]
(_getblockobjects "YourBlockName")
The above could be easily modified to only return Text objects, from which you could grab your text.

Lee

T.Willey

  • Needs a day job
  • Posts: 5251
Re: xref attribute work around
« Reply #2 on: March 23, 2011, 10:23:59 AM »
You can use the code here to attach attributes to xrefs.

[ http://www.theswamp.org/index.php?topic=8037.msg371079#msg371079 ]
Tim

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

Please think about donating if this post helped you.

jbuzbee

  • Swamp Rat
  • Posts: 851
Re: xref attribute work around
« Reply #3 on: March 23, 2011, 11:48:40 AM »
Ok, I did this once, pretty easy too.  Let me see if I can find it (many years ago . . ..)
James Buzbee
Windows 8

cadman6735

  • Guest
Re: xref attribute work around
« Reply #4 on: March 23, 2011, 01:40:59 PM »
Willey

Does your code attach an attribute to an xref as I would think a block would work?  So if I so choose to do so, when ever g-bs is xrefed into a new sheet file I will get the attribute dialog box to fill out the title border information Sheet Name, Sheet Number?  Ether at insert (as if I was inserting a block) or if I just double clicked on the border itself.

I am not looking for anyone to wright code for me, I am just looking for ideas and direction.  But if I could manipulate your code to what I think I want it to do, this would give me a great head start.  I tried to run you code to see what it does but it says I am missing some arguments.  It take me a bit to read and understand code to figure out what I am missing, so I am just curiouse where I can take your code

Thanks

jbuzbee

  • Swamp Rat
  • Posts: 851
Re: xref attribute work around
« Reply #5 on: March 23, 2011, 01:58:45 PM »
OK, sorry, I don't have any of my really old stuff (only go back to 2007).

1. Xref the drawing WITH the attributes.
2. Change the name of the xref
3. Insert the drawing WITH the attributes.
4. Point the xref reference to the block.
5. Erase the original Xref entity

Can't remember how but it worked like a charm.

Let me see if I can remember any more . . ..
James Buzbee
Windows 8

cadman6735

  • Guest
Re: xref attribute work around
« Reply #6 on: March 23, 2011, 02:20:06 PM »
Buz

I almost see your logic, great trick

The only question I have is how do you point the xref to a block?

Following your logic
1. xrfed in my border sheet
2. changed the name
3. referenced in another bordersheet
4. bound the border sheet via insert
5. exploded the new inserted block to access the attribute
6. edit as a block
7. Block is no longer an xref...  (needs to remain xref)

I think I am missing some steps.  (not sure if I want to go this route but I do like the out of the box thinking.)
Please fill in the missing steps for me, I am super curiose.

Thanks

T.Willey

  • Needs a day job
  • Posts: 5251
Re: xref attribute work around
« Reply #7 on: March 23, 2011, 03:00:28 PM »
My code attaches an attribute to an insert.  The drawing would already have to be inserted into the drawing, and then you would run my code.  And xref is just a smart insert, so it works.
Tim

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

Please think about donating if this post helped you.

cadman6735

  • Guest
Re: xref attribute work around
« Reply #8 on: March 23, 2011, 04:00:54 PM »
Willey

Sorry man, I am still very green...  How do I run your code?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: xref attribute work around
« Reply #9 on: March 23, 2011, 04:38:14 PM »
I just tested it again in '09, and it seemed not to work.  When I get a minute I'll try it again and let you know.
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: xref attribute work around
« Reply #10 on: March 23, 2011, 04:50:30 PM »
Okay.  The new code worked in my latest test.
[ http://www.theswamp.org/index.php?topic=8037.msg426208#msg426208 ]

What you need to do is copy what is in the code block to a new file, save it, then load it into Acad.  Then type ' AddExtraAtt ' at the command line, and follow the prompts.  You have to hit ' T ' to type in the values to use though, but I just tied it, and it worked.
Tim

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

Please think about donating if this post helped you.

cadman6735

  • Guest
Re: xref attribute work around
« Reply #11 on: March 24, 2011, 09:52:43 AM »
wow, willey

This is a cool tool, thanks (it has given me an idea)

The only down side for what I am looking for is it seems that the att. will have to be added to each sheet, and for the users in my office this is way too many steps and just adding text to each sheet seems a simpler route.


The idea that I got from this is to setup a title border with attributs as you nomaly would in the title border file.  When the border is xrefed into the sheet file (I think it is called "deep cloning") deep clone the attributes into the sheet file and using your code somehow to attach the attributes to the xref block as your code does to become a true xref attribute.

So each time the border is referenced in I can attedit the title border xref block, sheet name and number.  Then when the plot is activeated a plot reactor will change the layout tab name to the attribute sheet number (A-101) and append the sheet name attribute to the Layout tab so when plotted I get (A-101 First Floor Plan)  or a command reactor that reacts on attedit and will rename the layout tab at that point.

Now this would be a trick.


I will post this code in a few years.  ^-^

cadman6735

  • Guest
Re: xref attribute work around
« Reply #12 on: March 24, 2011, 09:59:35 AM »
For right now I am trying to go the rought of just selecting text and storing the text in an object.

my code does not store the info once the file is closed, I know it is because I am losing my object after closing the file.  I am having a hard time figuring out how to select a text or mtext object with vlisp.

This is my first attemtp at this code:
Quote
  (defun c:get ( / ent entName entHandle)

  (vl-load-com)

    (setq
      ent      (entget (car (entsel)))
      entName      (cdr (car ent))
      entHandle      (cdr (assoc 5 (entget entName)))
    )

    (vlax-ename->vla-object entName)

    (vlax-ldata-put entName "Handle" entHandle)

    (princ)
)

;----------------------------------------------------------------------------------------------------------------------------------

  (defun c:put ( / )

  (vl-load-com)

  (print (vlax-ldata-get entName "Handle"))

    (princ)
)

can someone help me just select the text via vlisp.

thanks

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #13 on: March 24, 2011, 10:01:23 AM »
Use nentsel.

cadman6735

  • Guest
Re: xref attribute work around
« Reply #14 on: March 24, 2011, 10:14:34 AM »
Lee

the text is not nested it is live in the file

I think we are thinking of two different approches.

We use only one border for each project with 200+ sheet, we that referance that one border file.  The text that never changes is located in the border file.  The sheet name and number will change per sheet file.  So at this point the only solution we know how to do is to leave the Number and Name blank in the border and just add text to each sheet.  Which has worked well for us until we switch to Revit.  Revit forces the PDF to print Sheet number and name, which upper managment loves.  Now we have a hard time getting users to fill out or rename the PDF's to match our new company standard.  Anyway, not to get into a long story.

So nentsel will not work unless I am way off base and don't understand the direction you are going.


Why does USERS1 not hold it value after closing file?

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #15 on: March 24, 2011, 10:19:34 AM »
the text is not nested it is live in the file

Sorry, I thought the text was part of the XRef...

So you just want the user to select some text, and add this text to the Layout name? or am I still misunderstanding?

jbuzbee

  • Swamp Rat
  • Posts: 851
Re: xref attribute work around
« Reply #16 on: March 24, 2011, 10:20:59 AM »
Found it.  Told you it was easy.

Code: [Select]
(defun kb:swapblock  (ent newBlockName / new_blk)
  (setq new_blk (subst (cons 2 newBlockName) (assoc 2 ent) ent))
  (entmod new_blk)
  (princ "\nBlock swapped!"))

So you xref and insert the same file.  Rename the xref first, then insert, then use the code above to swap the block for the xref.  AutoCAD will now think the block is an xref so you have to call the attedit command to edit the attributes (double-clicking brings up the reference editor).

Then erase the original xref and move the block / xref hybrid into it's place.  When the xref is reloaded the attributes remain in tact.

Just tested on AutoCAD 2009.  I used to have a real slick routine that did all of the above automatically, but can't find it.

jb
James Buzbee
Windows 8

cadman6735

  • Guest
Re: xref attribute work around
« Reply #17 on: March 24, 2011, 10:35:36 AM »
lee

you hit the nail but...

It is not as simple (for me) as just taking the text string and adding it to the layout tab.  I could do that, yeah me.

I want the file to remember the name and check the name each time I plot or when the text is edited, does not matter as long as the tab updates when the name and number has changed.

Which if I could figure out how to select a text object via vlisp (which I am find very difficult at the momment) I would use (vlax-data) or if USERS1 would hold its value I would go this route.
« Last Edit: March 24, 2011, 10:47:41 AM by cadman6735 »

cadman6735

  • Guest
Re: xref attribute work around
« Reply #18 on: March 24, 2011, 10:46:30 AM »
buzz

I am sorry man, I am an idiot, I am having a hard time understanding how it works...  I am not too experianced with arguments and after running the app. I get "too few arguments"...

I hate the fact that I am the one that has to be lead by the nose to understand.

1.  I xrefed in the border
2.  I renamed the xref
3.  Then I inserted the re-named xref via bind-insert?
4.  Then I xrefed another border in so I can run your code on the block in step 3 with the xref I just xrefed in
5.  Then ran your code

(kb:swapblock)
*Cancel*
too few arguments

cadman6735

  • Guest
Re: xref attribute work around
« Reply #19 on: March 24, 2011, 04:53:05 PM »
It took me all day to figure out the visual lisp version of my other code posted...  And it still doesn't work...   :realmad:


I have no clue what I am missing.  How can I store an object handle so I can call it after the acad has closed and reopend?

Quote
  (defun c:get ( / entHandle)

  (vl-load-com)

  (setq
    acadObject         (vlax-get-acad-object)
    acadActiveDocument      (vla-get-ActiveDocument acadObject)
    acadUtility         (vla-get-Utility acadActiveDocument)
   
  )

    (vla-getentity acadUtility 'obj 'ip "\nPlease Select Sheet Name")

    (setq entHandle (vla-get-handle obj))

    (vlax-ldata-put obj "Handle" entHandle)

    (princ)
)

;----------------------------------------------------------------------------------------------------------------

  (defun c:put ( / )

  (vl-load-com)

  (print (vlax-ldata-get obj "Handle"))

  (princ)
)

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #20 on: March 24, 2011, 05:09:04 PM »
Why are you attempting to store an object's handle in the LData of that same object? The object handle is unchanged between drawing sessions.

cadman6735

  • Guest
Re: xref attribute work around
« Reply #21 on: March 24, 2011, 05:49:18 PM »
I don't know.

I just want to have a variable store the handle so I can access the object for future use once the program as been saved and closed and reopened.

I have tried USERS1

I have tried my first version of the code using ldata

I have tried my second version of the code using ldata

I am now trying xdata, going thru a tutorial by AfraLisp.

I want to use USERS1 seems the most simple but it does not hold the value and I don't know why.


cadman6735

  • Guest
Re: xref attribute work around
« Reply #22 on: March 24, 2011, 06:00:09 PM »
now you say
Quote
same object

xdata is not the way to go either, it is also sToring it in the same object, which does not help me unless I can access it via the handle.

I'm going to find something to break  :pissed:  and start again tomorrow.

stupid lisp...  just kidding

but I want to "AAAHAHHAAA"

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #23 on: March 24, 2011, 06:10:41 PM »
I thought this would be a good exercise in using reactors (I don't write too many reactor based programs - they are volatile...).

The following code uses an ObjectReactor monitoring a user-selected Text Object.

Start the program with 'SyncText', and select a text object (in Paperspace) to be synced with the Layout in which it resides. After selection, xData will be added to the text object so that the transcient reactors may be rebuilt when the drawing is next opened.

Notice that when the text is edited, the Layout name is automatically updated.

Save/Close the drawing.

When you next open the drawing, load my program to rebuild the reactors and the text and layout will once again be synced.

Type 'UnSyncText' to remove the link.

Code: [Select]
(defun c:SyncText ( / *error* ss object objreactor comreactor ) 
  ;; Example © Lee Mac 2011
 
  (defun *error* ( msg )
    (setvar 'NOMUTT 0)
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **")))
    (princ)
  )
 
  (if (= 1 (getvar 'CVPORT))
    (progn
      (setvar 'NOMUTT 1)
      (princ "\nSelect Text to Sync with Layout: ")
      (setq ss (ssget "_+.:S:E" (list (cons 0 "TEXT") (cons 410 (getvar 'CTAB)))))
      (setvar 'NOMUTT 0)
     
      (if ss
        (progn
          (SyncText:Remove (getvar 'CTAB))
          (setq object (vlax-ename->vla-object (ssname ss 0)))
         
          (if (not (tblsearch "APPID" "LMAC-SyncText"))
            (regapp "LMAC-SyncText")
          )
          (entmod
            (list (cons -1 (ssname ss 0))
              (list -3
                (list "LMAC-SyncText"
                 '(1002 . "{") (cons 1000 (getvar 'CTAB)) '(1002 . "}")
                )
              )
            )
          )
          (if (setq objreactor (car (SyncText:GetReactors "LayoutSyncReactor" '(:vlr-object-reactor))))
            (progn
              (if (not (vlr-added-p objreactor))
                (vlr-add objreactor)
              )
              (vlr-owner-add objreactor object)
            )
            (vlr-object-reactor (list object) "LayoutSyncReactor"
              (list
                (cons :vlr-modified 'SyncText:Modified)
                (cons :vlr-erased   'SyncText:Erased)
              )
            )
          )
          (if (setq comreactor (car (SyncText:GetReactors "LayoutSyncReactor" '(:vlr-command-reactor))))
            (if (not (vlr-added-p comreactor))
              (vlr-add comreactor)
            )
            (vlr-command-reactor "LayoutSyncReactor"
              (list
                (cons :vlr-commandwillstart 'SyncText:Command)
              )
            )
          )
          (SyncText:Modified object reactor params)
          (princ "\n--> Text Synced with Layout.")
        )
      )
    )
    (princ "\n--> Command Only Available in Paperspace.")
  )
  (princ)
)

(defun SyncText:Remove ( layout / reactors objreactor )
  (mapcar 'vlr-remove
    (setq reactors
      (append
        (SyncText:GetReactors "LayoutSyncReactor" '(:vlr-object-reactor))
        (SyncText:GetReactors "LayoutSyncReactor" '(:vlr-command-reactor))
      )
    )
  )
  (
    (lambda ( / ss i )
      (if (setq ss (ssget "_X" (list '(0 . "TEXT") '(-3 ("LMAC-SyncText")) (cons 410 layout))))
        (repeat (setq i (sslength ss))
          (entmod
            (list (cons -1 (ssname ss (setq i (1- i))))
             '(-3 ("LMAC-SyncText"))
            )
          )
          (vlr-owner-remove (car reactors) (vlax-ename->vla-object (ssname ss i)))
        )
      )
    )
  )
  (and reactors (or (null (vlr-owners (car reactors))) (mapcar 'vlr-add reactors)))
  (princ)
)

(defun c:UnSyncText nil
  (SyncText:Remove "*")
  (princ)
)

(defun SyncText:Modified ( object reactor params )
  (or *acdoc*
    (setq *acdoc*
      (vla-get-ActiveDocument (vlax-get-acad-object))
    )
  )
  (if
    (not
      (or *UndoCalled*
        (vlax-erased-p object)
      )
    )
    (vl-catch-all-apply 'vla-put-name
      (list
        (vla-get-layout
          (vla-objectidtoobject *acdoc* (vla-get-ownerid object))
        )
        (vla-get-TextString object)
      )
    )
  )
  (princ)
)

(defun SyncText:Erased ( object reactor params )
  (vlr-remove reactor)
  (princ)
)

(defun SyncText:Command ( reactor params )
  (setq *UndoCalled* (wcmatch (strcase (car params)) "*U*"))
  (princ)
)

(defun SyncText:GetReactors ( data types )
  (vl-remove-if-not
    (function
      (lambda ( reactor )
        (eq data (vlr-data reactor))
      )
    )
    (apply 'append
      (mapcar 'cdr (apply 'vlr-reactors types))
    )
  )
)

(vl-load-com)

(
  (lambda ( / ss )
    (if
      (and
        (not
          (vl-some
            (function
              (lambda ( reactor )
                (eq "LayoutSyncReactor" (vlr-data reactor))
              )
            )
            (apply 'append
              (mapcar 'cdr
                (vlr-reactors :vlr-object-reactor :vlr-command-reactor)
              )
            )
          )
        )
        (setq ss (ssget "_X" '((0 . "TEXT") (-3 ("LMAC-SyncText")))))
      )
      (progn
        (vlr-object-reactor
          (
            (lambda ( / l i )
              (repeat (setq i (sslength ss))
                (setq l (cons (vlax-ename->vla-object (ssname ss (setq i (1- i)))) l))
              )
            )
          )
          "LayoutSyncReactor"
          (list
            (cons :vlr-modified 'SyncText:Modified)
            (cons :vlr-erased   'SyncText:Erased)
          )
        )
        (vlr-command-reactor "LayoutSyncReactor"
          (list
            (cons :vlr-commandwillstart 'SyncText:Command)
          )
        )
      )
    )
  )
)

(princ)

Currently only for one text object Updated for multiple Layouts, but a lot of coding for little gain IMO though.

Lee
« Last Edit: March 24, 2011, 09:00:11 PM by Lee Mac »

cadman6735

  • Guest
Re: xref attribute work around
« Reply #24 on: March 25, 2011, 09:30:33 AM »
Lee
I am humbled by you.  I didn't want or ask you to write this code for me but now that you have I can't thank you enough.  I can see (by your code) the task that I am trying to undertake is way over my skill set.  I can only assume that you program for a living and with a tool like this, this is something you need to be paid for.  I am not sure what a fare price would be and I honestly can not afford to pay you for it but if we can work something out, I will happly reimburse your time.

This tool will save us a ton of time in down production when trying to get jobs out the door.  Our Print shop spend hours renaming PDF's when they could and should be doing more proactive tasks.  You think this is little gain, I disagree.

  -  If I can ask you for one more favor (you have already done way too much for me), to make this work with MText, so we can have multiple lines in our sheet title, a title very rarly is one line.

I hesitate to ask, but we can not use this tool unless it is Mtext.  If you don't want to or don't have the time to mess with it, I understand and will take what is given to me and just say THANK YOU.  The ease that you write this stuff  is what I strive for.  I am humbled.




Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #25 on: March 25, 2011, 10:38:47 AM »
I am humbled by you.  I didn't want or ask you to write this code for me but now that you have I can't thank you enough.  I can see (by your code) the task that I am trying to undertake is way over my skill set.  I can only assume that you program for a living and with a tool like this, this is something you need to be paid for.  I am not sure what a fare price would be and I honestly can not afford to pay you for it but if we can work something out, I will happly reimburse your time.

Many thanks for your kind words CADman - I appreciate it. Of course, I didn't write the code expecting reimbursement - initially, this was a good exercise for me in programming using reactors (I don't write too many reactor based programs), and I would furthermore state that the current code is by no means 'bulletproof' (I find it very difficult to make a program completely robust when invoking reactors since one must account for all possible scenarios [e.g. note the extra command reactor required to prevent a crash when Undo is called] - but perhaps this a lack of knowledge in this area on my part). That said, of course, if you do feel compelled to make a donation to either theSwamp or my site, both will be welcomed.

This tool will save us a ton of time in down production when trying to get jobs out the door.  Our Print shop spend hours renaming PDF's when they could and should be doing more proactive tasks.  You think this is little gain, I disagree.

I'm glad that it can save you time in your work - my earlier comment regarding the 'little gain' was more remarking upon how much code was required to merely link a text object to the Layout Name - if only Fields were permitted in Layout Names, this would be a walk in the park.

If I can ask you for one more favor (you have already done way too much for me), to make this work with MText, so we can have multiple lines in our sheet title, a title very rarly is one line.

The program could indeed be modified to accept MText, however I foresee problems where MText formatting is concerned (it could be removed of course), and also in that Layout Names may only consist of a single line with a limited number of characters (254?)

I hesitate to ask, but we can not use this tool unless it is Mtext.  If you don't want to or don't have the time to mess with it, I understand and will take what is given to me and just say THANK YOU.  The ease that you write this stuff  is what I strive for.  I am humbled.

To be honest, its mostly practice - many times I study the code others have posted and try to take ideas further, or code something in a different way.

Happy I could help,

Lee

cadman6735

  • Guest
Re: xref attribute work around
« Reply #26 on: March 25, 2011, 11:36:41 AM »
Quote
That said, of course, if you do feel compelled to make a donation to either theSwamp or my site, both will be welcomed.

Indeed, I will make a donation to both, your site and the swamp.  When I can afford to do so, the economy here in the states has me stagnent in sallery and only a single income family.  I wish I could donate today.  This kind gesture of yours will not be fogotten.

Quote
To be honest, its mostly practice - many times I study the code others have posted and try to take ideas further, or code something in a different way.

Then I am on the right path, I do nothing other than read and study forums and old posts and code, I am determined to learn.  Though I do find it frustraiting and overwhelming.

Life is good and people like you make it better.
Have great weekend.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #27 on: March 25, 2011, 11:55:21 AM »
Life is good and people like you make it better.
Have great weekend.

That's very kind of you CADMan, have a great weekend too  :-)

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #28 on: March 25, 2011, 02:23:59 PM »
This should hopefully work with MText:

Code: [Select]
(defun c:SyncText ( / *error* ss object ) 
  ;; Example © Lee Mac 2011
 
  (defun *error* ( msg )
    (setvar 'NOMUTT 0)
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **")))
    (princ)
  )
 
  (if (= 1 (getvar 'CVPORT))
    (progn
      (setvar 'NOMUTT 1)
      (princ "\nSelect Text to Sync with Layout: ")
      (setq ss (ssget "_+.:S:E" (list (cons 0 "TEXT,MTEXT") (cons 410 (getvar 'CTAB)))))
      (setvar 'NOMUTT 0)
     
      (if ss
        (progn
          (SyncText:Remove (getvar 'CTAB))
          (setq object (vlax-ename->vla-object (ssname ss 0)))
         
          (if (not (tblsearch "APPID" "LMAC-SyncText")) (regapp "LMAC-SyncText"))
          (entmod
            (append (entget (ssname ss 0))
              (list
                (list -3
                  (list "LMAC-SyncText"
                   '(1002 . "{") (cons 1000 (getvar 'CTAB)) '(1002 . "}")
                  )
                )
              )
            )
          )
          (if SyncText:ObjectReactor
            (progn
              (if (not (vlr-added-p SyncText:ObjectReactor)) (vlr-add SyncText:ObjectReactor))
              (vlr-owner-add SyncText:ObjectReactor object)
            )
            (setq SyncText:ObjectReactor
              (vlr-object-reactor (list object) "SyncTextObjectReactor"
                (list
                  (cons :vlr-modified 'SyncText:Modified)
                )
              )
            )
          )
          (if SyncText:CommandReactor
            (if (not (vlr-added-p SyncText:CommandReactor)) (vlr-add SyncText:CommandReactor))
            (setq SyncText:CommandReactor
              (vlr-command-reactor "SyncTextCommandReactor"
                (list
                  (cons :vlr-commandwillstart 'SyncText:Command)
                )
              )
            )
          )
          (SyncText:Modified object nil nil)
          (princ "\n--> Text Synced with Layout.")
        )
      )
    )
    (princ "\n--> Command Only Available in Paperspace.")
  )
  (princ)
)

(defun SyncText:Remove ( layout )
  (if
    (and SyncText:ObjectReactor SyncText:CommandReactor
      (mapcar 'vlr-remove (list SyncText:ObjectReactor SyncText:CommandReactor))
    )
    (
      (lambda ( / ss i )
        (if (setq ss (ssget "_X" (list '(0 . "TEXT,MTEXT") '(-3 ("LMAC-SyncText")) (cons 410 layout))))
          (repeat (setq i (sslength ss))
            (entmod
              (list (cons -1 (ssname ss (setq i (1- i)))) '(-3 ("LMAC-SyncText")))
            )
            (vlr-owner-remove SyncText:ObjectReactor (vlax-ename->vla-object (ssname ss i)))
          )
        )
        (if (vlr-owners SyncText:ObjectReactor)
          (mapcar 'vlr-add (list SyncText:ObjectReactor SyncText:CommandReactor))
        )
      )
    )
  ) 
  (princ)
)

(defun c:UnSyncText nil
  (SyncText:Remove "*")
  (princ)
)

(defun SyncText:Modified ( object reactor params / dstring mstring )
  (or *acdoc*
    (setq *acdoc* (vla-get-ActiveDocument (vlax-get-acad-object)))
  )
  (if (and SyncText:RegExp (not *UndoCalled*))
    (if (vlax-erased-p object)
      (progn
        (vlr-owner-remove SyncText:ObjectReactor object)
        (if (null (vlr-owners SyncText:ObjectReactor))
          (mapcar 'vlr-remove (list SyncText:ObjectReactor SyncText:CommandReactor))
        )
      )
      (if
        (vl-catch-all-error-p
          (setq err
            (vl-catch-all-apply 'vla-put-name
              (list
                (vla-get-layout
                  (vla-objectidtoobject *acdoc* (vla-get-ownerid object))
                )
                (progn
                  (LM:GetTrueContent SyncText:RegExp (vlax-vla-object->ename object) 'dstring 'mstring)
                  dstring
                )
              )
            )
          )
        )
        (princ (strcat "\n--> Error: " (vl-catch-all-error-message err)))
      )
    )
  )
  (princ)
)

(defun SyncText:Command ( reactor params )
  (setq *UndoCalled* (wcmatch (strcase (car params)) "*U*"))
  (princ)
)

(vl-load-com)

(
  (lambda ( / ss )
    (if
      (and
        (not (and SyncText:ObjectReactor SyncText:CommandReactor))
        (setq ss (ssget "_X" '((0 . "TEXT") (-3 ("LMAC-SyncText")))))
      )
      (progn
        (if (not SyncText:ObjectReactor)
          (setq SyncText:ObjectReactor
            (vlr-object-reactor
              (
                (lambda ( / l i )
                  (repeat (setq i (sslength ss))
                    (setq l (cons (vlax-ename->vla-object (ssname ss (setq i (1- i)))) l))
                  )
                )
              )
              "SyncTextObjectReactor" (list (cons :vlr-modified 'SyncText:Modified))
            )
          )
        )
        (if (not SyncText:CommandReactor)
          (setq SyncText:CommandReactor
            (vlr-command-reactor "SyncTextCommandReactor"
              (list
                (cons :vlr-commandwillstart 'SyncText:Command)
              )
            )
          )
        )
      )
    )
    (if (not SyncText:RegExp)
      (setq SyncText:RegExp (vlax-create-object "VBScript.RegExp"))
    )
    (setq *acdoc* (vla-get-ActiveDocument (vlax-get-acad-object)))
  )
)


;;------------------=={ Get True Content }==------------------;;
;;                                                            ;;
;;  Returns the unformatted string associated with the        ;;
;;  supplied entity, in formats compatible with Text & MText  ;;
;;  objects.                                                  ;;
;;                                                            ;;
;;  The arguments *dtextstring & *mtextstring should be       ;;
;;  supplied with quoted symbols (other than those symbols    ;;
;;  used by the arguments themselves). The unformatted        ;;
;;  strings suitable for Text & MText objects will henceforth ;;
;;  be bound to the supplied symbol arguments respectively.   ;;
;;                                                            ;;
;;  Note that it is the caller's responsibility to create and ;;
;;  release the RegularExpressions (RegExp) object. This      ;;
;;  object may be created using the                           ;;
;;  Programmatic Identifier: "VBScript.RegExp".               ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2010 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  RegExp       - RegularExpressions (RegExp) Object         ;;
;;  entity       - Ename whose text content is to be returned ;;
;;  *dtextstring - (output) Unformatted string compatible     ;;
;;                 with Text entities                         ;;
;;  *mtextstring - (output) Unformatted string compatible     ;;
;;                 with MText entities                        ;;
;;------------------------------------------------------------;;
;;  Returns:    This function always returns nil              ;;
;;------------------------------------------------------------;;

(defun LM:GetTrueContent ( RegExp entity *dtextstring *mtextstring / _Replace _AllowsFormatting _GetTextString )

  (defun _Replace ( new old string )
    (vlax-put-property RegExp 'pattern old) (vlax-invoke RegExp 'replace string new)
  )

  (defun _AllowsFormatting ( entity / object )   
    (or (wcmatch (cdr (assoc 0 (entget entity))) "MTEXT,MULTILEADER")     
      (and
        (eq "ATTRIB" (cdr (assoc 0 (entget entity))))
        (vlax-property-available-p (setq object (vlax-ename->vla-object entity)) 'MTextAttribute)
        (eq :vlax-true (vla-get-MTextAttribute object))
      )
    )
  )

  (defun _GetTextString ( entity )
    (
      (lambda ( entity / _type elist )
        (cond
          ( (wcmatch (setq _type (cdr (assoc 0 (setq elist (entget entity))))) "TEXT,*DIMENSION")
           
            (cdr (assoc 1 (reverse elist)))
          )
          ( (eq "MULTILEADER" _type)

            (cdr (assoc 304 elist))
          )
          ( (wcmatch _type "ATTRIB,MTEXT")

            (
              (lambda ( string )
                (mapcar
                  (function
                    (lambda ( pair )
                      (if (member (car pair) '(1 3))
                        (setq string (strcat string (cdr pair)))
                      )
                    )
                  )
                  elist
                )
                string
              )
              ""
            )
          )
        )
      )
      (if (eq 'VLA-OBJECT (type entity))
        (vlax-vla-object->ename entity)
        entity
      )
    )
  )

  (
    (lambda ( string )
      (if string
        (progn
          (mapcar
            (function
              (lambda ( x ) (vlax-put-property RegExp (car x) (cdr x)))
            )
            (list (cons 'global actrue) (cons 'ignorecase acfalse) (cons 'multiline actrue))
          )
          (if (_AllowsFormatting entity)
            (mapcar
              (function
                (lambda ( x ) (setq string (_Replace (car x) (cdr x) string)))
              )
             '(
                ("Π"       . "\\\\\\\\")
                (" "       . "\\\\P|\\n|\\t")
                ("$1"      . "\\\\(\\\\[ACcFfHLlOopQTW])|\\\\[ACcFfHLlOopQTW][^\\\\;]*;|\\\\[ACcFfHLlOopQTW]")
                ("$1$2/$3" . "([^\\\\])\\\\S([^;]*)[/#\\^]([^;]*);")
                ("$1$2"    . "\\\\(\\\\S)|[\\\\](})|}")
                ("$1"      . "[\\\\]({)|{")
              )
            )
            (setq string (_Replace "" "%%[OoUu]" (_Replace "Π" "\\\\" string)))
          )
          (set *mtextstring (_Replace "\\\\" "Π" (_Replace "\\$1$2$3" "(\\\\[ACcFfHLlOoPpQSTW])|({)|(})" string)))
          (set *dtextstring (_Replace "\\"   "Π" string))
        )
      )
    )
    (_GetTextString entity)
  )
  nil
)

(princ)

It uses my GetTrueContent sub from here to remove any formatting codes present in the MText string.

I have also changed my method of manipulating the reactor objects to use global variables as this results in slightly less code.  :-)

cadman6735

  • Guest
Re: xref attribute work around
« Reply #29 on: March 28, 2011, 10:07:25 AM »
All I can say is thank you.

Thank you.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #30 on: March 28, 2011, 10:35:46 AM »
All I can say is thank you.

Thank you.

You're very welcome CADMan :-)

cadman6735

  • Guest
Re: xref attribute work around
« Reply #31 on: March 29, 2011, 04:59:28 PM »
I am starting to notice code like the code in red in other code:

Code: [Select]
(setq ss (ssget [color=red]"_+.:S:E"[/color] (list (cons 0 "TEXT,MTEXT") (cons 410 (getvar 'CTAB)))))

Another example

Quote
(if (setq ss (ssget "_:L" '((0 . "MTEXT") (1 . "*\\P*"))))

What is it?



alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: xref attribute work around
« Reply #32 on: March 29, 2011, 05:03:19 PM »
Code: [Select]
SSGET

the underscore (_) is needed with W, F, WP, :S but not with X, A, C, CP, I, L, P, :E ...

(ssget '(2 2))
Create a selection set of the object passing through (2,2):
                                                                                               
+.  The undocumented “+.” mode forces (ssget) to remain in “point” mode, similar to
    setting PickAuto to 0.... the "+." puts (ssget) into "point" mode. It helps the ":S"
    single-mode act just like (entsel) by avoiding implied selection windows.

A  All like "X" but filters frozen out
   Selects all objects on thawed layers.

B  Box
   Selects all objects inside or crossing a rectangle specified by two points. If
   the rectangle's points are specified from right to left, Box is equivalent to
   Crossing. Otherwise, Box is equivalent to Window.

C  Crossing  Simular to Window selection
   Selects objects within and crossing an area defined by two points. A crossing
   selection is displayed as dashed or otherwise highlighted to differentiate it
   from window selection. Specifying the corners from right to left creates a
   crossing selection. *** (Specifying the corners from left to right creates a window
   selection.)  (ssget "_C" '(0 0) '(1 1))
   Caution: the area must be on the screen for this to work properly - CAB
   
CP Crossing Polygon
   Selects objects within and crossing a polygon defined by specifying points. The
   polygon can be any shape but cannot cross or touch itself. AutoCAD draws the
   last segment of the polygon so that it is closed at all times. CPolygon is not
   affected by the PICKADD system variable.
   (ssget "_CP" '((1 1)(3 1)(5 2)(2 4)))
   Example with filters (ssget "_CP" '(Point list) '(Filter List))
   (setq ss (ssget "_CP" '((0 0)(10 0)(10 10)(0 10)) '((0 . "INSERT") (66 . 1))  ))
   Caution: the area must be on the screen for this to work properly - CAB
   (vl-cmdf "._zoom" "_E") ; Extents
   
:D Duplicates OK, else duplicates are ignored

:E Everything in aperture
   Everything within the cursor's object selection pickbox.

F Fence
  Selects all objects crossing a selection fence. The Fence method is similar to
  CPolygon except that AutoCAD does not close the fence, and a fence can cross
  itself. Fence is not affected by the PICKADD system variable.

G Groups
  Selects all objects within a specified group.

I Implied
  Implied selection (objects selected while PICKFIRST is in effect).

L Last
  Last visible object added to the database
 
:L Rejects locked layers

M  Multiple
   Specifies multiple points without highlighting the objects, thus speeding up
   the selection process for complex objects. The Multiple method also selects two
   intersecting objects if the intersection point is specified twice.
 
:N Nested
   Call ssnamex for additional information on container blocks and transformation
   matrices for any entities selected during the ssget operation. This additional
   information is available only for entities selected via graphical selection
   methods such as Window, Crossing, and point picks.
   
   Unlike the other object selection methods, :N may return multiple entities with
   the same entity name in the selection set. For example, if the user selects a
   subentity of a complex entity such as a BlockReference, PolygonMesh, or old
   style polyline, ssget looks at the subentity that is selected when determining
   if it has already been selected. However,  ssget actually adds the main entity
   (BlockReference, PolygonMesh, etc.) to the selection set. The result could be
   multiple entries with the same entity name in the selection set (each will have
   different subentity information for ssnamex to report).

P  Previous
   Selects the most recent selection set. The Previous selection set is cleared by
   operations that delete objects from the drawing. AutoCAD keeps track of whether
   each selection set was specified in model space or paper space. The Previous
   selection set is ignored if you switch spaces.

:P Rejects Viewport

:R Allows entities in a long transaction to be selected.

:S Force single object selection only

:U Enables subentity selection - 2006+
Cannot be combined with the  duplicate (":D") or nested (":N")  selection modes.
In this  mode, top-level  entities are  selected by  default, but  the user  can
attempt  to  select  subentities  by pressing  the  CTRL  key  while making  the
selection. This option  is supported only  with interactive selections,  such as
window, crossing, and polygon. It is  not supported for all, filtered, or  group
selections.

:V Forces subentity selection - 2006+
Treats all interactive,  graphic selections performed  by the user  as subentity
selections. The returned  selection set contains  subentities only. This  option
cannot be combined with the  duplicate (":D") or nested (":N")  selection modes.
This option is  supported only with  interactive selections, such  as window and
crossing. It is not supported for all, filtered, or group selections.

W  Window
   Selects all objects completely inside a rectangle defined by two points.
   Specifying the corners from left to right creates a window selection.
   (Specifying the corners from right to left creates a crossing selection.)

WP Window Polygon
   Selects objects completely inside a polygon defined by points. The polygon can
   be any shape but cannot cross or touch itself. AutoCAD draws the last segment of
   the polygon so that it is closed at all times. WPolygon is not affected by the
   PICKADD system variable.

X  Extended search (search whole database)
   Entire database. If you specify the X selection method and do not provide a
   filter-list, ssget selects all entities in the database, including entities on
   layers that are off, frozen, and out of the visible screen.
   
   Also at the command prompt "Select objects:" you can enter
   Add, Remove, Undo,

:U Enables subentity selection. Cannot be combined with the duplicate (":D") or
   nested (":N") selection modes. In this mode, top-level entities are selected by
   default, but the user can attempt to select subentities by pressing the CTRL key
   while making the selection. This option is supported only with interactive
   selections, such as window, crossing, and polygon. It is not supported for all,
   filtered, or group selections.

:V Forces subentity selection. Treats all interactive, graphic selections
   performed by the user as subentity selections. The returned selection set
   contains subentities only. This option cannot be combined with the duplicate
   (":D") or nested (":N") selection modes. This option is supported only with
   interactive selections, such as window and crossing. It is not supported for
   all, filtered, or group selections.

Systen Var
  PICKADD controls whether subsequent selections replace the current selection set or add to it.
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

cadman6735

  • Guest
Re: xref attribute work around
« Reply #33 on: March 29, 2011, 05:08:00 PM »
whow, that was quick

Thanks Alan

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: xref attribute work around
« Reply #34 on: March 29, 2011, 06:11:29 PM »
whow, that was quick

Thanks Alan

Alan's a quick typist  :evil:

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: xref attribute work around
« Reply #35 on: March 29, 2011, 06:24:21 PM »
whow, that was quick

Thanks Alan

Alan's a quick typist  :evil:
"Ctrl+C" and "Ctrl+V"  :lol:
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox