First attempt at Object DBX

Discussion in 'AutoCAD' started by T.Willey, Nov 9, 2004.

  1. T.Willey

    LUCAS Guest

    Just rename the BlockOldref name to BlockNew name.



    definition with another, but I couldn't get it to work. I was trying to use
    the 'CopyObject method, but it only seems to work with an acad document or
    an acad database, which a block table definition doesn't seem to be either
    one.
    does is delete the objects form the old block.
     
    LUCAS, Nov 17, 2004
    #21
  2. T.Willey

    Joe Burke Guest

    Hi Tim,

    Here's a code snip from my block replace program. See the last comment. I think
    that's where your example hiccups.

    blocks - copy to blocks collection
    srcdoc - copy from document
    srcblocks - copy from blocks collection
    nm - block name is the same in both documents

    (setq oldblk (vla-item blocks nm)) ;block def to modify
    (setq newblk (vla-item srcblocks nm)) ;source block def

    (vlax-for item newblk
    (setq itemlst (cons item itemlst))) ;list of objects to copy

    (vlax-for item oldblk
    (vla-delete item)) ;delete objects from block to modify

    ;source is the copy from document
    (vlax-invoke srcdoc 'CopyObjects (reverse itemlst) oldblk)

    Or this, though catching an error in this case may not be a good idea.

    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vlax-invoke
    (list srcdoc 'CopyObjects (reverse itemlst) oldblk)
    )
    )

    Joe Burke
     
    Joe Burke, Nov 17, 2004
    #22
  3. T.Willey

    Joe Burke Guest

    Lucas,

    The method suggested is designed to avoid renaming.

    Joe Burke
     
    Joe Burke, Nov 17, 2004
    #23
  4. T.Willey

    LUCAS Guest

    ;;just for test
    ;;(TT OLDBLKNAME NEWBLKNAME)
    ;;(TT "123" "123")
    ;;make sure you have blkname in both documents
    (defun TT (NM NM1 / DWGNAME SRCDOC BLOCKS SRCBLOCKS NM NM1 ENT ENTT)
    (if (setq DWGNAME (getfiled "Select Drawing File" "" "dwg" 4))
    (progn
    (if (> (atoi (getvar "AcadVer")) 15)
    (setq SRCDOC (vla-getinterfaceobject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument.16"
    )
    )
    (progn
    (if (not (vl-registry-read
    "HKEY_CLASSES_ROOT\\ObjectDBX.AxDbDocument\\CLSID"
    )
    )
    (startapp "regsvr32.exe"
    (strcat "/s \"" (findfile "axdb15.dll") "\"")
    )
    )
    (setq SRCDOC (vla-getinterfaceobject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument"
    )
    )
    )
    )
    (setq BLOCKS (vla-get-blocks
    (vla-get-activedocument (vlax-get-acad-object))
    )
    )
    (vla-open SRCDOC DWGNAME)
    (setq SRCBLOCKS (vla-get-blocks SRCDOC))

    ;; blocks - copy to blocks collection
    ;; srcdoc - copy from document
    ;; srcblocks - copy from blocks collection
    ;; nm - block name is the same in both documents

    ;;rename blkname
    (if (equal NM NM1)
    (vla-put-name
    (vla-item BLOCKS NM1)
    (setq NM1 (strcat "tmp" NM))
    )
    )

    ;;copy blk def
    (vla-copyobjects
    SRCDOC
    (vlax-safearray-fill
    (vlax-make-safearray vlax-vbobject '(0 . 0))
    (list (vla-item SRCBLOCKS NM))
    )
    BLOCKS
    )

    ;;rename blkname
    (vlax-for ENT BLOCKS
    (vlax-for ENTT ENT
    (if (and (= (vla-get-objectname ENTT) "AcDbBlockReference")
    (= (vla-get-name ENTT) NM1)
    )
    (vla-put-name ENTT NM)
    )
    )
    )

    ;;delete oldblk def
    (vla-delete (vla-item BLOCKS NM1))
    (vlax-release-object BLOCKS)
    (vlax-release-object SRCBLOCKS)
    (vlax-release-object SRCDOC)
    )
    )
    (princ)
    )

    ;;(TTT BLKNAME)
    ;;(TTT "123")
    ;;make sure you have blkname in both documents
    (defun TTT (NM / DWGNAME SRCDOC BLOCKS SRCBLOCKS NM OLDBLK NEWBLK
    ITEMLST ITEM)
    (if (setq DWGNAME (getfiled "Select Drawing File" "" "dwg" 4))
    (progn
    (if (> (atoi (getvar "AcadVer")) 15)
    (setq SRCDOC (vla-getinterfaceobject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument.16"
    )
    )
    (progn
    (if (not (vl-registry-read
    "HKEY_CLASSES_ROOT\\ObjectDBX.AxDbDocument\\CLSID"
    )
    )
    (startapp "regsvr32.exe"
    (strcat "/s \"" (findfile "axdb15.dll") "\"")
    )
    )
    (setq SRCDOC (vla-getinterfaceobject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument"
    )
    )
    )
    )
    (setq BLOCKS (vla-get-blocks
    (vla-get-activedocument (vlax-get-acad-object))
    )
    )
    (vla-open SRCDOC DWGNAME)

    (setq SRCBLOCKS (vla-get-blocks SRCDOC))

    (setq OLDBLK (vla-item BLOCKS NM)) ;block def to modify
    (setq NEWBLK (vla-item SRCBLOCKS NM)) ;source block def

    (vlax-for ITEM NEWBLK
    (setq ITEMLST (cons ITEM ITEMLST))
    ) ;list of objects to copy

    (vlax-for ITEM OLDBLK
    (vla-delete ITEM)
    ) ;delete objects from block to modify
    ;;source is the copy from document
    (vlax-invoke SRCDOC 'COPYOBJECTS (reverse ITEMLST) OLDBLK)

    (vlax-release-object BLOCKS)
    (vlax-release-object SRCBLOCKS)
    (vlax-release-object SRCDOC)
    (command "_.regen")
    )
    )
    (princ)
    )
     
    LUCAS, Nov 17, 2004
    #24
  5. T.Willey

    Joe Burke Guest

    Lucas,

    Your code is a good example of why I don't do it that way. ;-)

    The method I'm suggesting involves considerably less code. Plus it doesn't have to
    deal with block references contained in target drawing at all. Because nothing is
    renamed, references to any block in question are updated simply by modifying its
    block definition.

    I have an old version of my block replace thing which uses the method you suggest. It
    was more complicated codewise, and less reliable, than the method I suggested to Tim.

    Thanks for your thoughts on this. I just think there's an easier alternative...

    BTW, if you or Tim prefer a more complete programming example, search for CloneBlock
    by John Uhden posted January 2004. It's basically the same idea using one document,
    rather than copy from source doc to target doc.

    Regards
    Joe Burke
     
    Joe Burke, Nov 17, 2004
    #25
  6. T.Willey

    T.Willey Guest

    Lucas,

    The problem with that is if I'm bringing in a block from another file that has the same name, but I want to update the block information. That is why I was trying to find a way to replace the objects within it by using code.

    Tim
     
    T.Willey, Nov 17, 2004
    #26
  7. T.Willey

    T.Willey Guest

    Joe and Lucas,

    All the ways I have found to do this have not yielded the results that I want. Most importantly are the attributes not being updated with the blocks already inserted into the document. I remember seeing a post about attributes here a little while ago, so I will do some more research.

    Thanks for your help on this part.
    Tim
     
    T.Willey, Nov 17, 2004
    #27
  8. Attributes on already-inserted blocks are sub-entities of the insertion.
    They will *not* magically update just because the block definition changed.
    You will need to iterate thru the block insertions modifying the attributes
    to match the new block definition.

    --
    R. Robert Bell


    Joe and Lucas,

    All the ways I have found to do this have not yielded the results that I
    want. Most importantly are the attributes not being updated with the blocks
    already inserted into the document. I remember seeing a post about
    attributes here a little while ago, so I will do some more research.

    Thanks for your help on this part.
    Tim
     
    R. Robert Bell, Nov 17, 2004
    #28
  9. T.Willey

    T.Willey Guest

    Robert,

    What would be the best way? After reading some post, The way I was planning on doing it was:
    Get the value for all attributes within blocks already inserted in the drawing
    Running the command "Attsync"
    Then putting back all the values (as many as can be, if new block as less amount)

    I couldn't think of any other way. Any direction is appreciated.
    Thanks
    Tim
     
    T.Willey, Nov 17, 2004
    #29
  10. Jason Piercey, Nov 17, 2004
    #30
  11. T.Willey

    T.Willey Guest

    Jason,

    I was talking about keeping attribute values when changing the blocks definition. The line "Any direction is appreciated." meant that any point in the right direction for a solution is appreciated. But I will check out the link to see if there is anything there that I could use.

    Thanks.
    Tim
     
    T.Willey, Nov 17, 2004
    #31
  12. How are you going to run a command via ObjectDBX?

    --
    R. Robert Bell


    Robert,

    What would be the best way? After reading some post, The way I was
    planning on doing it was:
    Get the value for all attributes within blocks already inserted in the
    drawing
    Running the command "Attsync"
    Then putting back all the values (as many as can be, if new block as less
    amount)

    I couldn't think of any other way. Any direction is appreciated.
    Thanks
    Tim
     
    R. Robert Bell, Nov 17, 2004
    #32
  13. T.Willey

    T.Willey Guest

    I would like to run it anyway, but the way I explained it, it would have to be run within the active document because I was planning on using ssget. Now that I write this I guess it doesn't have to be written that way because I could cycle through the model space (paper) blocks to find all occurances.

    This seems to work in the tests that I have done, but if there is a better way, I'm open. Run the first one, then run "attsync" on said block, the run the second one.
    Thanks.
    Tim
    ps. This is how I did it first, forgot about the ability to cycle through the space blocks.

    (defun GetAttNValue (BlockName / ss temp1 temp2 EndList)

    (if (setq ss (ssget "x" (list (cons 0 "INSERT") (cons 2 BlockName) (cons 66 1))))
    (while (setq temp1 (ssname ss 0))
    (setq temp2 (cons temp1 temp2))
    (while (/= (value 0 (entget (setq temp1 (entnext temp1)))) "SEQEND")
    (if (= (value 0 (entget temp1)) "ATTRIB")
    (setq temp2 (cons (value 1 (entget temp1)) temp2))
    )
    )
    (setq EndList (cons (reverse temp2) EndList))
    (setq temp2 nil)
    (ssdel (ssname ss 0) ss)
    )
    )
    Endlist
    )

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

    (defun PutAttValueBack (AttList / temp1)

    (foreach item AttList
    (setq cnt1 1)
    (setq temp1 (car item))
    (while
    (and
    (/= (value 0 (entget (setq temp1 (entnext temp1)))) "SEQEND")
    (nth cnt1 item)
    )
    (if (= (value 0 (entget temp1)) "ATTRIB")
    (progn
    (vla-put-TextString (MakeX temp1) (nth cnt1 item))
    (setq cnt1 (1+ cnt1))
    )
    )
    )
    )
    )
     
    T.Willey, Nov 17, 2004
    #33
  14. T.Willey

    T.Willey Guest

    On a side note. How would one get the active space with the ability to add it into the InsertBlock method?
    Example.
    (setq temp1
    (vla-InsertBlock
    (vla-get-PaperSpace ActDoc) <--- don't want to have to hard code the space.
    (vlax-3d-point '(5000 5000 0))
    (vla-get-Name BlockNew)
    1 1 1 0
    )
    )

    Tim
     
    T.Willey, Nov 17, 2004
    #34
  15. T.Willey

    T.Willey Guest

    Nevermind. I was just making it harder on myself. Thinking that it need to know the number of the paperspace block, but it doesn't, so I got it this way.

    (if (= (vla-get-ActiveSpace ActDoc) 1)
    (setq ActSpace (vla-get-ModelSpace ActDoc))
    (setq ActSpace (vla-get-PaperSpace ActDoc))
    )

    Tim

    Duh!!...
     
    T.Willey, Nov 17, 2004
    #35
  16. T.Willey

    T.Willey Guest

    Here is the way I did it without using ssget.

    Tim

    (defun GetAttNValue (BlockName DocBlock / temp1 temp2 cnt1 EndList BlkColl SpaceList)

    (if (not DocBlcock)
    (setq DocBlock (vla-get-ActiveDocument (vlax-get-ACAD-Object)))
    )
    (setq BlkColl (vla-get-Blocks DocBlock))
    (vlax-for item BlkColl
    (if
    (or
    (vl-string-search "*MODEL_SPACE" (strcase (vla-get-Name item)))
    (vl-string-search "*PAPER_SPACE" (strcase (vla-get-Name item)))
    )
    (setq SpaceList (cons item SpaceList))
    )
    )
    (foreach item SpaceList
    (setq cnt1 0)
    (while (/= cnt1 (vla-get-Count item))
    (setq temp2 (vla-Item item cnt1))
    (if
    (and
    (vlax-property-available-p temp2 'Name)
    (= (vla-get-Name temp2) BlockName)
    )
    (progn
    (setq temp1 (cons (vlax-vla-object->ename temp2) temp1))
    (foreach item3 (safearray-value (vlax-variant-value (vla-GetAttributes temp2)))
    (setq temp1 (cons (vla-get-TextString item3) temp1))
    )
    (setq EndList (cons (reverse temp1) EndList))
    )
    )
    (setq cnt1 (1+ cnt1))
    )
    )
    Endlist
    )
     
    T.Willey, Nov 18, 2004
    #36
  17. T.Willey

    MP Guest

    Hi T. Willey!
    May I offer a possible alternate way to get your model and paperspace
    blocks?

    ;since this way you have to go through all blocks just to get at the ms/ps
    ones...
    ;maybe this is more efficient...though I'm sure it's unmeasurable by humans
    :)
    (defun adcfList-Spaces(oDoc / spacelist)
    (vlax-for oPs(vla-get-layouts oDoc)
    (setq spacelist(cons ops spaceList)))
    spacelist
    )
    (defun adcfList-SpaceBlocks(oDoc / spacelist)
    (vlax-for oPs(vla-get-layouts oDoc)
    (setq spacelist(cons (vla-get-block ops) spaceList)))
    spacelist
    )
    (defun Test( / o)
    (princ"\nList of spaces: ")
    (foreach o
    (adcfList-Spaces (adcfGet-ActiveDoc))
    (print(vla-get-name o))
    )
    (princ"\nList of space blocks: ")
    (foreach o
    (adcfList-SpaceBlocks (adcfGet-ActiveDoc))
    (print(vla-get-name o))
    )
    (princ"\nEnd list")
    )

    of course substitute your wording for the activedoc func
    I included getting the blocks of the layouts cause depending on what you
    want to do, sometimes you need those instead of just the layout object.
    ;then I'd suggest moving the count out of the loop cause you only really
    need to do it once
    ;instead of...
    ;maybe consider..
    (setq cnt2(vla-get-Count item))
    ;and for some reason I'd replace /= with <
    (while (< cnt1cnt2)
    ;just to make sure some errant code doesnt' bump it more than cnt2 and put
    you in an endless loop(very theoretical....just a thought)
    ;i guess it's really just that it looks more like whats' really going on...
    ;curious if you're using vla funcs why store the ename rather than the
    object?
    ;obviously it depends on how your're using endlist after this sub runs
    have fun dbxin'
    :)
    Mark
     
    MP, Nov 18, 2004
    #37
  18. T.Willey

    Joe Burke Guest

    Tim,

    I'm not sure whether you solved the basic issue, replacing one block with another. My
    sense is you did. Then the attributes issue came up, and the thread turned to that
    discussion. Assuming all that is true, which replace block method did you use? What I
    suggested, or Lucas' method? I'm just curious.

    BTW, my replace block program doesn't attempt to deal with attributed blocks. I guess
    it should, but I don't use it to replace those types of blocks.

    Joe Burke
     
    Joe Burke, Nov 18, 2004
    #38
  19. T.Willey

    T.Willey Guest

    Joe,

    First I did it your way, then I noticed that the attributes didn't work right, so then I tried it another way, I think kind of like the way Lucas was describing.

    I will both post methods, incase the is some better way of doing it. I'm not sure which way is better yet. Once uses a couple of commands, so I'm thinking that I couldn't use that if I wanted it to be used as an Object DBX method, but other then that it both work.
    Thanks.
    Tim

    (defun ReplaceBlock (BlockOld BlockNew NewBlockDoc / OldName ActDoc BlkColl ActSpace test1 temp1 temp2 temp3)

    (setq OldName (vla-get-Name BlockOld))
    (vla-put-Name BlockOld (strcat "tmw_temp-" OldName))
    (setq ActDoc (vla-get-ActiveDocument (vlax-get-ACAD-Object)))
    (setq BlkColl (vla-get-Blocks ActDoc))
    (if (not NewBlockDoc)
    (setq NewBlockDoc ActDoc)
    )
    (if (= (vla-get-ActiveSpace ActDoc) 1)
    (setq ActSpace (vla-get-ModelSpace ActDoc))
    (setq ActSpace (vla-get-PaperSpace ActDoc))
    )
    (setq test1 (vl-catch-all-apply 'vla-Item (list BlkColl (vla-get-Name BlockNew))))
    (if (= (type test1) 'vl-catch-all-apply-error)
    (vla-CopyObjects
    NewBlockDoc
    (vlax-SafeArray-Fill (vlax-Make-SafeArray vlax-vbObject '(0 . 0)) (list BlockNew))
    BlkColl
    )
    )
    (setq temp1
    (vla-InsertBlock
    ActSpace
    (vlax-3d-point '(5000 5000 0))
    (vla-get-Name BlockNew)
    1 1 1 0
    )
    )
    (setq temp2 (safearray-value (vlax-variant-value (vla-Explode temp1))))
    (vla-Delete temp1)
    (foreach item temp2
    (setq temp3 (cons (vlax-vla-object->ename item) temp3))
    )
    (command "_.purge" "_b" (vla-get-Name BlockNew) "_n")
    (vla-put-Name BlockOld OldName)
    (command "_.-block" OldName "_y" (list 5000 5000 0))
    (apply 'command temp3)
    (command "")
    )

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

    (defun ReplaceBlock-2 (BlockOld BlockNew NewBlockDoc / OldName ActDoc BlkColl test1 temp1 temp2 temp3)

    (setq ActDoc (vla-get-ActiveDocument (vlax-get-ACAD-Object)))
    (if (not NewBlockDoc)
    (setq NewBlockDoc ActDoc)
    )
    (if
    (and
    (= (vla-get-ObjectName BlockOld) "AcDbBlockTableRecord")
    (= (vla-get-ObjectName BlockNew) "AcDbBlockTableRecord")
    )
    (progn
    (vlax-for item BlockOld
    (vlax-invoke-method item 'Delete)
    )
    (setq cnt1 0)
    (while (/= cnt1 (vla-get-Count BlockNew))
    (setq temp1 (vla-Item BlockNew cnt1))
    (vla-CopyObjects
    NewBlockDoc
    (vlax-SafeArray-Fill (vlax-Make-SafeArray vlax-vbObject '(0 . 0)) (list temp1))
    BlockOld
    )
    (setq cnt1 (1+ cnt1))
    )
    )
    )
    )
     
    T.Willey, Nov 18, 2004
    #39
  20. T.Willey

    T.Willey Guest

    Hey Mark,

    I like the two little routines you used, I still new at vl*- things, so it's always nice to see other ways of doing things.

    The count is in the foreach loop because it needs to reset to 0 foreach item. It is how the program knows which item to check, by it's number.

    Good point about changing the /=, but I would have to say to use >=, I think it will work better.

    I stored the enames because I couldn't figure out how to modify something by a vl*- thing. I didn't really see and index type function. I was looking at getting either the handle or the object index, but I couldn't figure out how to use that information to find it again by that name. If you have any pointers for that that would be cool. I use the return list to put back the attribute values in another routine (posted above).

    Thanks for the tips and pointers.
    Tim
     
    T.Willey, Nov 18, 2004
    #40
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.