vla-add

Discussion in 'AutoCAD' started by Ursus Uziemblo, Jan 25, 2005.

  1. Hi,
    I try to add to blocks collection a new block
    (setq block_coll (vla-get-blocks (vla-active-decument)))
    (vla-add block_coll (vlax-3d-point 0 0) "abc") works OK, but
    (vla-add block_coll (vlax-3d-point 0 0) "d:/abc")
    returns error.
    How to add (insert) a drawing,
    next stage - how to update a new version of it
    Thanks for help
    Ursus Uziemblo
     
    Ursus Uziemblo, Jan 25, 2005
    #1
  2. Code:
    
    (vlax-invoke-method
    (vlax-get-property
    (vlax-get-property
    (vlax-get-acad-object)
    'ActiveDocument
    )
    'ModelSpace ;; or paperspace
    )
    'InsertBlock    ;; method to invoke
    InsertPoint    ;; variant (3 element array of doubles)
    BlockName      ;; valid block name or *path*
    XScale         ;; double (optional)
    YScale         ;; double (optional)
    ZScale         ;; double (optional)
    Rotation       ;; double (optional)
    )
    
    or
    
    (vla-InsertBlock
    (vla-get-ModelSpace ;; or paperspace
    (vla-get-ActiveDocument
    (vlax-get-acad-object)
    )
    )
    InsertPoint ;; variant (3 element array of doubles)
    BlockName   ;; valid block name or *path*
    XScale      ;; double (optional)
    YScale      ;; double (optional)
    ZScale      ;; double (optional)
    Rotation    ;; double (optional)
    )
    
    Examples:
    
    Assuming "c:\\ABC.dwg" is a fully valid drawing ...
    
    (vlax-invoke-method
    (vlax-get-property
    (vlax-get-property
    (vlax-get-acad-object)
    'ActiveDocument
    )
    'ModelSpace
    )
    'InsertBlock
    (vlax-3d-point 0 0 0) ;; insert point
    "c:\\ABC.dwg"         ;; valid path
    1.0                   ;; x-scale
    1.0                   ;; y scale
    1.0                   ;; z scale
    0.0                   ;; rotation
    )
    
    or
    
    (vla-InsertBlock
    (vla-get-ModelSpace
    (vla-get-ActiveDocument
    (vlax-get-acad-object)
    )
    )
    (vlax-3d-point 0 0 0) ;; insert point
    "c:\\ABC.dwg"         ;; valid path
    1.0                   ;; x-scale
    1.0                   ;; y scale
    1.0                   ;; z scale
    0.0                   ;; rotation
    )
    
    To redefine the block call the InsertBlock method
    again using the full path to the external drawing,
    otherwise subsequent calls can be made using the
    (pathless) name only and the internal block def will
    be used.
    
    
     
    Michael Puckett, Jan 25, 2005
    #2
  3. Note, it appears the scale and rotation arguments
    are optional in VB but not in Visual LISP.

    <snip>
     
    Michael Puckett, Jan 25, 2005
    #3
  4. Ursus Uziemblo

    Doug Broad Guest

    Ursus,
    For those who are working in the active document, the following
    accomplishes the same thing as Michael's nicely written functions:

    (command "_.insert" "blockname" nil)
     
    Doug Broad, Jan 25, 2005
    #4
  5. Thanks Michael
    I will try it
    ps
    why (vla-add...)
    works with name and rejects file name"
    Ursus Uziemblo
     
    Ursus Uziemblo, Jan 25, 2005
    #5
  6. Thanks Doug
    I try to update (reload) new version of block
    from (command "-insert"...) i have to delete a new block
    after insert - I wish to only reload bolck definition
    Ursus Uziemblo
     
    Ursus Uziemblo, Jan 25, 2005
    #6
  7. Ursus Uziemblo

    MP Guest

    look at the help for Add Method and also InsertBlock method.
    That will explain the difference

    Basically with the add method you're adding a block definition to the blocks
    collection inside the current dwg.
    With the insertblock method you're inserting a block reference of an already
    existing block definition. That existing block definition can either be a
    block definition in the blocks collection of the current dwg or it can be an
    external dwg file (sometimes referred to as a "wblock").
    The act of inserting an external file as a block will automatically add the
    definition to the blocks collection without you having to do that step.

    hth
    Mark
     
    MP, Jan 25, 2005
    #7
  8. Ursus Uziemblo

    Doug Broad Guest

    Ursus,
    To reload blocks an alternative is:
    (command "_.insert" "blockname=filename" nil)
     
    Doug Broad, Jan 25, 2005
    #8
  9. Thanks Mark
    It explain all -
    my goal is to redefine block definition without
    inserting it to drawings
    Looks like the best method is insert and delete it
    Ursus Uziemblo
     
    Ursus Uziemblo, Jan 25, 2005
    #9
  10. Ursus Uziemblo

    MP Guest

    see Doug's reply above
    :)
     
    MP, Jan 25, 2005
    #10
  11. Thanks Michael again
    changes I added
    (vla-delete (YourCode))
    works OK in 99%
    Now, how to fix this 1%
    New block I'm inserting has one attribute shifted down
    in updated block all geometry is updated OK except
    position of the attribute.
    Deleting old and inserting new instance of block
    ask for all attributes
    Any ideas?
    Ursus Uziemblo
     
    Ursus Uziemblo, Jan 25, 2005
    #11
  12. Thanks
    this is what I miss
    uu
     
    Ursus Uziemblo, Jan 25, 2005
    #12
  13. Calling the insert command w/a nil as Doug demonstrated
    is probably the best way to redefine a block, insomuch
    as no great coding effort is required.

    However it's not the only way (please note I wrote this
    quick and dirty, it may need some polish) ...

    <for fun>

    Code:
    
    ;;  [Re]define a block definition based on an external
    ;;  drawing using Visual LISP. Does not create an
    ;;  instance, rather, creates a temporary block
    ;;  definition to serve as a temporary host, then
    ;;  dumps said temporary def after the block we are
    ;;  interested is [re]defined.  Updates any existing
    ;;  instances of the block in question.
    ;;
    ;;  Written very quickly -- if you find errors please
    ;;  let the newsgroup know so I/we can fix it up.
    ;;
    ;;  Michael Puckett, 2005/01/25
    
    (defun RedefineBlock
    
    (   drawingPath
    /
    i
    prefix
    tempName
    tempBlock
    tempPoint
    ss
    )
    
    (cond
    
    (   (findfile drawingPath)
    
    ;;  create a unique temp block name
    
    (setq prefix "temp" i 0)
    (while
    (tblsearch "block"
    (setq tempName
    (strcat prefix
    (itoa (setq i (1+ i)))
    )
    )
    )
    )
    
    ;;  create a temporary block definition
    
    (setq tempBlock
    (vlax-invoke-method
    (setq blocks
    (vlax-get-property
    (vlax-get-property
    (vlax-get-acad-object)
    'ActiveDocument
    )
    'Blocks
    )
    )
    'Add
    (setq tempPoint (vlax-3d-point '(0 0 0)))
    tempName
    )
    )
    
    (cond
    
    (   ;;  insert the external drawing
    ;;  into the temporary block, this
    ;;  redefines the internal definition
    ;;  for drawingPath if it exists,
    ;;  otherwise it defines it. If the
    ;;  attempt to insert the drawing
    ;;  fails bail (incorrect version,
    ;;  corrupt, yada).
    
    (null
    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vlax-invoke-method
    (list
    tempBlock
    'InsertBlock
    tempPoint
    drawingPath
    1.0
    1.0
    1.0
    0.0
    )
    )
    )
    )
    
    ;;  now delete the temporary block
    ;;  def as we no longer need it
    
    (vlax-invoke-method
    tempBlock
    'Delete
    )
    
    ;;  if the current drawing has
    ;;  any instances update them
    
    (if
    (setq ss
    (ssget "x"
    (list
    '(0 . "insert")
    (cons 2
    (vl-filename-base drawingPath)
    )
    )
    )
    )
    (repeat (setq i (sslength ss))
    (vlax-invoke-method
    (vlax-ename->vla-object
    (ssname ss (setq i (1- i)))
    )
    'Update
    )
    )
    )
    
    ;;  tell the caller we did it (admittedly
    ;;  we did not ensure we were successful
    ;;  by testing each stage, I'll leave it
    ;;  up to you to make this function robust)
    
    t
    )
    
    (   t
    
    ;;  delete the temporary block
    ;;  def as we no longer need it
    ;;  (the insert attempt failed)
    ;;  return nil to the caller
    
    (vlax-invoke-method
    tempBlock
    'Delete
    )
    
    nil
    
    )
    )
    )
    )
    )
    
    Example of use:
    
    (RedefineBlock "c:\\abc.dwg")
    
    
     
    Michael Puckett, Jan 25, 2005
    #13
  14. I rewrote it, ditching tblsearch and ssget code, instead using
    activex methods. As such, it should work on any valid document,
    including an objectdbx document, tho the latter is theory as I
    haven't had time to test it.

    PLEASE note the calling signature has changed, it now requires
    a document to be passed as the first argument.

    Let me know of any problems or find that conceptually it's out
    to lunch.

    Code:
    
    ;;===========================================================================
    ;;
    ;;  Redefine.lsp | Copyright (c) 2005 Michael Puckett | All Rights Reserved
    ;;
    ;;===========================================================================
    ;;
    ;;  [Re]define a block definition based on an external drawing using Visual
    ;;  LISP. Does not create an  instance, rather, creates a temporary block
    ;;  definition to serve as a temporary host, then dumps said temporary
    ;;  definition after the block we are interested in is [re]defined.  Updates
    ;;  any existing instances of the block in question (in non objectdbx
    ;;  documents).
    ;;
    ;;  Written very quickly for the customization newsgroup -- if you find
    ;;  errors please let the newsgroup know so I / we can fix it up.
    ;;
    ;;===========================================================================
    ;;
    ;;  Example call:
    ;;
    ;;      (RedefineBlock
    ;;          (vlax-get-property
    ;;              (vlax-get-acad-object)
    ;;             'ActiveDocument
    ;;          )
    ;;          "c:\\abc.dwg"
    ;;      )
    ;;
    ;;===========================================================================
    
    (defun RedefineBlock
    
    (   document
    drawingPath
    /
    i
    ss
    blocks
    prefix
    tempName
    tempBlock
    tempPoint
    blockName
    )
    
    (cond
    
    (   (findfile drawingPath)
    
    ;;  create a unique temp block name
    
    (setq
    i      0
    blocks (vlax-get-property document 'Blocks)
    )
    
    (while
    (null
    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vlax-invoke-method
    (list
    blocks
    'Item
    (setq tempName
    (strcat "temp"
    (itoa (setq i (1+ i)))
    )
    )
    )
    )
    )
    )
    )
    
    ;;  create a temporary block definition
    
    (setq tempBlock
    (vlax-invoke-method
    blocks
    'Add
    (setq tempPoint (vlax-3d-point '(0 0 0)))
    tempName
    )
    )
    
    (cond
    
    (   ;;  insert the external drawing
    ;;  into the temporary block, this
    ;;  redefines the internal definition
    ;;  for drawingPath if it exists,
    ;;  otherwise it defines it. If the
    ;;  attempt to insert the drawing
    ;;  fails bail (incorrect version,
    ;;  corrupt, yada).
    
    (null
    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vlax-invoke-method
    (list
    tempBlock
    'InsertBlock
    tempPoint
    drawingPath
    1.0
    1.0
    1.0
    0.0
    )
    )
    )
    )
    
    ;;  now delete the temporary block
    ;;  def as we no longer need it
    
    (vlax-invoke-method
    tempBlock
    'Delete
    )
    
    ;;  if the current drawing has
    ;;  any instances update them
    
    (setq blockName
    (strcase
    (vl-filename-base drawingPath)
    )
    )
    
    (if ;;  there's no need to update
    ;;  objectdbx documents
    
    (vlax-property-available-p
    document
    'Active
    )
    (vlax-for block blocks
    (if
    (eq :vlax-true
    (vlax-get-property
    block
    'IsLayout
    )
    )
    (vlax-for object block
    (if
    (and
    (eq "AcDbBlockReference"
    (vlax-get-property
    object
    'ObjectName
    )
    )
    (eq blockName
    (strcase
    (vlax-get-property
    object
    'Name
    )
    )
    )
    )
    (vlax-invoke-method
    object
    'Update
    )
    )
    )
    )
    )
    )
    
    ;;  tell the caller we did it (admittedly
    ;;  we did not ensure we were successful
    ;;  by testing each stage, I'll leave it
    ;;  up to you to make this function robust)
    
    t
    )
    
    (   t   ;;  delete the temporary block
    ;;  def as we no longer need it
    ;;  (the insert attempt failed)
    
    (vlax-invoke-method
    tempBlock
    'Delete
    )
    
    nil
    
    )
    )
    )
    )
    )
    
    
    <snip>
     
    Michael Puckett, Jan 25, 2005
    #14
  15. Thanks Michael
    I love your code, works ok
    only one problem
    attribut shifted in new block DO NOT change position
    as needed.
    Only if you insert new block attribute is in correct place.
    Thaks very, very much
    Ursus Uziemblo

     
    Ursus Uziemblo, Jan 25, 2005
    #15
  16. Update: Modify code to remedy bug in ObjectDBX document
    implementation of InsertBlock method. See comment in code.

    Code:
    
    ;;===========================================================================
    ;;
    ;;  Redefine.lsp | Copyright (c) 2005 Michael Puckett | All Rights Reserved
    ;;
    ;;===========================================================================
    ;;
    ;;  [Re]define a block definition based on an external drawing using Visual
    ;;  LISP. Does not create an  instance, rather, creates a temporary block
    ;;  definition to serve as a temporary host, then dumps said temporary
    ;;  definition after the block we are interested in is [re]defined.  Updates
    ;;  any existing instances of the block in question (in non objectdbx
    ;;  documents).
    ;;
    ;;  Written very quickly for the customization newsgroup -- if you find
    ;;  errors please let the newsgroup know so I / we can fix it up.
    ;;
    ;;===========================================================================
    ;;
    ;;  Example call:
    ;;
    ;;      (RedefineBlock
    ;;          (vlax-get-property
    ;;              (vlax-get-acad-object)
    ;;             'ActiveDocument
    ;;          )
    ;;          "c:\\abc.dwg"
    ;;      )
    ;;
    ;;===========================================================================
    
    (defun RedefineBlock
    
    (   document
    drawingPath
    /
    i
    ss
    block
    blocks
    prefix
    tempName
    tempBlock
    tempPoint
    blockName
    )
    
    (cond
    
    (   (findfile drawingPath)
    
    ;;  create a unique temp block name
    
    (setq
    i      0
    blocks (vlax-get-property document 'Blocks)
    )
    
    (while
    (null
    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vlax-invoke-method
    (list
    blocks
    'Item
    (setq tempName
    (strcat "temp"
    (itoa (setq i (1+ i)))
    )
    )
    )
    )
    )
    )
    )
    
    ;;  create a temporary block definition
    
    (setq tempBlock
    (vlax-invoke-method
    blocks
    'Add
    (setq tempPoint (vlax-3d-point '(0 0 0)))
    tempName
    )
    )
    
    ;;  If the document is an objectdbx document
    ;;  and the block already exists blow away
    ;;  everything in the definition. There's a bug
    ;;  in the objectdbx model that manifests itself
    ;;  as "add new def to existing def" instead of
    ;;  "redefine def"
    
    (if
    (and
    (null
    (vlax-property-available-p
    document
    'Active
    )
    )
    (null
    (vl-catch-all-error-p
    (setq block
    (vl-catch-all-apply
    'vlax-invoke-method
    (list
    blocks
    'Item
    (vl-filename-base drawingPath)
    )
    )
    )
    )
    )
    )
    (   (lambda ( / lst )
    (vlax-for object block
    (setq lst
    (cons object lst)
    )
    )
    (foreach object lst
    (vlax-invoke-method
    object
    'Delete
    )
    )
    )
    )
    )
    
    (cond
    
    (   ;;  insert the external drawing
    ;;  into the temporary block, this
    ;;  redefines the internal definition
    ;;  for drawingPath if it exists,
    ;;  otherwise it defines it. If the
    ;;  attempt to insert the drawing
    ;;  fails bail (incorrect version,
    ;;  corrupt, yada).
    
    (null
    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vlax-invoke-method
    (list
    tempBlock
    'InsertBlock
    tempPoint
    drawingPath
    1.0
    1.0
    1.0
    0.0
    )
    )
    )
    )
    
    ;;  now delete the temporary block
    ;;  def as we no longer need it
    
    (vlax-invoke-method
    tempBlock
    'Delete
    )
    
    ;;  if the current drawing has
    ;;  any instances update them
    
    (setq blockName
    (strcase
    (vl-filename-base drawingPath)
    )
    )
    
    (if ;;  there's no need to update
    ;;  objectdbx documents
    
    (vlax-property-available-p
    document
    'Active
    )
    
    (vlax-for block blocks
    (if
    (eq :vlax-true
    (vlax-get-property
    block
    'IsLayout
    )
    )
    (vlax-for object block
    (if
    (and
    (eq "AcDbBlockReference"
    (vlax-get-property
    object
    'ObjectName
    )
    )
    (eq blockName
    (strcase
    (vlax-get-property
    object
    'Name
    )
    )
    )
    )
    (vlax-invoke-method
    object
    'Update
    )
    )
    )
    )
    )
    )
    
    ;;  tell the caller we did it (admittedly
    ;;  we did not ensure we were successful
    ;;  by testing each stage, I'll leave it
    ;;  up to you to make this function robust)
    
    t
    )
    
    (   t   ;;  delete the temporary block
    ;;  def as we no longer need it
    ;;  (the insert attempt failed)
    
    (vlax-invoke-method
    tempBlock
    'Delete
    )
    
    nil
    
    )
    )
    )
    )
    )
    
    
     
    Michael Puckett, Jan 25, 2005
    #16
  17. I could add that easy enough, but I'll have to pass
    on adding that detail at this time (other fish to fry).
    As a programmer you'll have to find all the instances
    of the block in question, and then for each attdef that
    exists in the definition AND the instance modify the
    position to reflect the definition, otherwise add any
    new attdefs (as attribs) to the instance(s). Basically
    mimicking what utilities like AttReDef do.

    Hope that's clear; cheers.
     
    Michael Puckett, Jan 25, 2005
    #17
  18. Code:
    ;;
    ;;  this code snip
    ;;
    
    (repeat (vlax-get-property block 'Count)
    (vlax-invoke-method
    (vlax-invoke-method
    block
    'Item
    0
    )
    )
    )
    ;;
    ;;  can replace this
    ;;
    (   (lambda ( / lst )
    (vlax-for object block
    (setq lst
    (cons object lst)
    )
    )
    (foreach object lst
    (vlax-invoke-method
    object
    'Delete
    )
    )
    )
    )
    
    My thinking was (right or wrong) probably not good
    to delete objects from a collection while one is
    iterating said collection. The alternate method poses
    no threat that I can see and should be quite speedy.

    <snip>
     
    Michael Puckett, Jan 25, 2005
    #18
  19. Doh, typo.

    (repeat (vlax-get-property block 'Count)
    (vlax-invoke-method
    (vlax-invoke-method
    block
    'Item
    0
    )
    'Delete
    )
    )
     
    Michael Puckett, Jan 25, 2005
    #19
  20. Thanks Michael,
    you spend a lot of time
    with out coding one more question:
    why 'InsertBlock to "tempname" container works OK
    but the same 'InsertBlock into existing container
    works correctly and exit with error?
    Ursus Uziemblo
     
    Ursus Uziemblo, Jan 26, 2005
    #20
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.