First attempt at Object DBX

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

  1. T.Willey

    T.Willey Guest

    This code seems to work, but I got some examples from here, and I'm not sure if I used them right. I was just wondering if people with more experience with Object DBX could take a glance and give me some pointers.

    What it does is import blocks from a drawing.

    Thanks.
    Tim

    ps. I attached the ".dcl" file, just rename the extension from ".txt" to ".dcl".

    (defun ImportBlockDia (BlockList / blist diaload ipblist bilist)

    (if BlockList
    (progn
    (setq blist (vl-sort BlockList '(lambda (x y) (< (vla-get-Name x) (vla-get-Name y)))))
    (setq diaload (load_dialog "CloseDwg.dcl"))
    (if (not (new_dialog "Cdrawings" diaload))
    (exit)
    )
    (start_list "tx2" 3); clear the list
    (mapcar '(lambda (x) (add_list (vla-get-Name x))) blist)
    (end_list)
    (action_tile "accept"
    "(progn
    (setq ipblist (get_tile \"tx2\"))
    (done_dialog 1)
    )"
    )
    (action_tile "cancel"
    "(progn
    (setq ipblist nil)
    (done_dialog 1)
    )"
    )
    (start_dialog)
    (if ipblist
    (progn
    (setq ipblist (read (strcat "(" ipblist ")")))
    (foreach item ipblist
    (setq bilist (cons (nth item blist) bilist))
    )
    )
    )
    )
    )
    bilist
    )

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

    (defun c:CopyBlocks (/ dbxDoc rslt con *blocks cblist blist)

    (if (setq rslt (tmw:OpenDBX))
    (progn
    (setq cblist (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-ACAD-Object))))
    (setq *blocks (vla-get-Blocks (car rslt)))
    (vlax-for item *blocks
    (if
    (and
    (/= (vla-get-IsXRef item) :vlax-True)
    (not (vl-string-search "|" (vla-get-Name item)))
    (not (vl-string-search "*" (vla-get-Name item)))
    )
    (setq con (cons item con))
    )
    )
    (if (setq blist (ImportBlockDia con))
    (foreach item blist
    (vla-CopyObjects
    (car rslt)
    (vlax-SafeArray-Fill (vlax-Make-SafeArray vlax-vbObject '(0 . 0)) (list item))
    cblist
    )
    )
    )
    (VL-CATCH-ALL-APPLY 'vlax-release-object (list dbxDoc con *blocks cblist blist))
    (tmw:CloseDBX rslt)
    )
    )
    (princ)
    )

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

    (defun tmw:OpenDBX (/ FileName NewFileName TestIf dbxDoc)

    (if (setq FileName (getfiled "Select file:" (getvar "dwgprefix") "dwg" 4))
    (progn
    (if (setq TestIf (open FileName "a"))
    (close TestIf)
    (progn
    (setq NewFileName (strcat (vl-filename-directory FileName) "\\" (strcat "CopyOf-" (vl-filename-base FileName) ".dwg")))
    (vl-file-copy FileName NewFileName)
    (setq FileName NewFileName)
    )
    )
    (setq dbxDoc (vla-GetInterfaceObject (vlax-get-ACAD-Object) "ObjectDBX.AxDbDocument.16"))
    (vla-Open dbxDoc FileName)
    (list dbxDoc FileName)
    )
    )
    )

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

    (defun tmw:CloseDBX (Results / FileName)

    (setq FileName (cadr Results))
    (vl-Catch-All-Apply '(lambda () (vla-Close (car Resutls))))
    (vlax-Release-Object (car Results))
    (if (vl-string-search "CopyOf-" (vl-filename-base FileName))
    (vl-file-delete FileName)
    )
    )
     
    T.Willey, Nov 9, 2004
    #1
  2. T.Willey

    Rudy Tovar Guest

    Well I can't say I read the code....but it should be just copying the object
    then inserting it into your drawing...

    You could open the drawing and filter only its blocks, then copy and insert
    into your drawing...

    Just remember to filter out xrefs from regular blocks... I used this to
    differ from what an xref is and a block...

    (vl-load-com)
    (defun c:dbxblock (/ dbxDoc dwgname la cn lp it con)

    (setq dwgname (getfiled "Select Drawing File" "" "dwg" 4))

    (if dwgname
    (progn

    (setq dbxDoc
    (vla-GetInterfaceObject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument"
    )
    )

    (vla-open dbxDoc DwgName)

    (setq la (vla-get-block dbxdoc)
    cn (vla-get-count la)
    lp 0
    )

    (repeat cn
    (setq it (vla-item la lp)
    )
    (setq con (vla-get-isxref it))
    (princ con)

    (setq lp (1+ lp))

    )

    (vl-catch-all-apply
    '(lambda () (vla-close DBXDOC ':VLAX-TRUE 'ITEM))
    )

    (VL-CATCH-ALL-APPLY
    'vlax-release-object

    (list dbxDoc dwgname la cn lp it con)

    )
    (vlax-release-object dbxDoc)

    (setq dbxDoc nil)
    )
    )
    (princ)
    )


    --
    MASi
    Copyright 2004 by Cadentity
    www.Cadentity.com
    Autodesk
    Authorized Developer
     
    Rudy Tovar, Nov 9, 2004
    #2
  3. T.Willey

    T.Willey Guest

    Rudy,

    I saw you post this before, that is one of the reason why I tried to make my own routine. I didn't quite understand some of the functions you used, and even after reading the help files I still only could grasp a little. The two parts are:

    (vl-catch-all-apply
    '(lambda () (vla-close DBXDOC ':VLAX-TRUE 'ITEM))
    )
    and
    (VL-CATCH-ALL-APPLY
    'vlax-release-object
    (list dbxDoc dwgname la cn lp it con)
    )

    The first one looks as if you are closing the document that you opened in Object DBX, but I don't understand what the ':vlax-true or the 'item do.

    The second one you are release all the variable names that you use, but when does it and what, has to be released?

    Any pointers is greatly appreciated.
    Thanks.
    Tim
     
    T.Willey, Nov 9, 2004
    #3
  4. T.Willey

    Rudy Tovar Guest

    After several conversations with other developers and friend...any object
    that you use within the dbx function must be released or variable as
    illustrated...or else the drawing will not close and remain open...of which
    effects mean leaving a lock on the file and the drawing open. This
    mentioned...affects what you could use to update the file or edit it...even
    simply reading it. The only way you'll be able to gain access to the file
    again you'll have to shut down autocad or else the file will say it's open
    by guess who..? YOU.

    As you'v noticed..the first part opens and assigns the object file...then
    second simply uses the vla methods of acquiring objects or properties...then
    changing all things to given object... and finally releasing the object then
    cancel out each variable regardless of were how you used it within the
    illustrated list...

    Again there must be a LIST of all Variable that you used within the final
    list for the file to be released...

    --
    MASi
    Copyright 2004 by Cadentity
    www.Cadentity.com
    Autodesk
    Authorized Developer
     
    Rudy Tovar, Nov 9, 2004
    #4
  5. T.Willey

    T.Willey Guest

    Rudy,

    Thanks for clearing up the issue I had.

    Tim
     
    T.Willey, Nov 9, 2004
    #5
  6. T.Willey

    LUCAS Guest

    ;;For ref
    (defun IMPORTBLOCKDIA (BLOCKLIST / BLIST DIALOAD IPBLIST BILIST)
    (if BLOCKLIST
    (progn
    (setq BLIST (acad_strlsort BLOCKLIST))
    (setq DIALOAD (load_dialog "CloseDwg.dcl"))
    (if (not (new_dialog "Cdrawings" DIALOAD))
    (exit)
    )
    (start_list "tx2")
    (mapcar 'add_list BLIST)
    (end_list)
    (action_tile
    "accept"
    "(setq ipblist (get_tile \"tx2\"))
    (done_dialog 1)"
    )
    (action_tile
    "cancel"
    "(done_dialog 0)"
    )
    (start_dialog)
    (if IPBLIST
    (progn
    (setq IPBLIST (read (strcat "(" IPBLIST ")")))
    (foreach ITEM IPBLIST
    (setq BILIST (cons (nth ITEM BLIST) BILIST))
    )
    )
    )
    )
    )
    BILIST
    )

    ;;---------------------------------------------------------------------
    (defun C:COPYBLOCKS (/ DBXDOC CON *BLOCKS CBLIST BLIST)

    (if (setq
    FILENAME (getfiled "Select file:" (getvar "dwgprefix") "dwg" 4)
    )
    (progn
    (setq DBXDOC (vla-getinterfaceobject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument.16"
    )
    )
    (vla-open DBXDOC FILENAME)
    (setq CBLIST (vla-get-blocks
    (vla-get-activedocument (vlax-get-acad-object))
    )
    )
    (setq *BLOCKS (vla-get-blocks DBXDOC))
    (vlax-for ITEM *BLOCKS
    (if
    (and
    (/= (vla-get-isxref ITEM) :vlax-true)
    (not (vl-string-search "|" (vla-get-name ITEM)))
    (not (vl-string-search "*" (vla-get-name ITEM)))
    )
    (setq CON (cons (vla-get-name ITEM) CON))
    )
    )

    (if
    (setq BLIST (IMPORTBLOCKDIA CON))
    (foreach ITEM BLIST
    (vla-copyobjects
    DBXDOC
    (vlax-safearray-fill
    (vlax-make-safearray vlax-vbobject '(0 . 0))
    (list (vla-item *BLOCKS ITEM))
    )
    CBLIST
    )
    )
    )

    (vl-catch-all-apply
    'vlax-release-object
    (list DBXDOC *BLOCKS CBLIST)
    )
    )
    )
    ;;Add some code for insert into your drawing...
    (princ)
    )
     
    LUCAS, Nov 10, 2004
    #6
  7. Who told you that?

    The only object that you have to explicitly release, is the
    AxDbDocument. All others are destroyed regardless of any
    references or not.
     
    Tony Tanzillo, Nov 10, 2004
    #7
  8. Don't feel bad, Rudy doesn't seem to understand them either.


    I don't know where Rudy got the idea that you can
    close an AxDbDocument like that, but you can't. The
    AxDbDocument object has no Close method, but of
    course, since Rudy wraps the call in a vl-catch-all-apply,
    he never sees the error.

    To 'close' an AxDbDocument, just use (vlax-release-object)
    on the variable containing the document, and that'll do it.
     
    Tony Tanzillo, Nov 10, 2004
    #8
  9. T.Willey

    Rudy Tovar Guest

    Thanks for enlightening me...

    I'd have to go back a few weeks and rewind me thoughts...just in case you
    didn't follow the original thread, you may want to comment on it there...but
    of coarse you're probably too busy to look...

    We should hear from you more often, instead of you just degrading us...
     
    Rudy Tovar, Nov 10, 2004
    #9
  10. T.Willey

    Rudy Tovar Guest

    In part Autodesk programmer.

    Bug... so I was lead to believe....are you ADN?
     
    Rudy Tovar, Nov 10, 2004
    #10
  11. T.Willey

    Joe Burke Guest

    Hi Tim,

    Looking at the code you posted, and what Lucas posted (the two seem related), I don't
    see checking for duplicate block names from source file to target file. Or maybe I'm
    missing something? I haven't tried to run either program.

    What I'd expect to see is a filtered list of block names contained in target file.
    Then while copying blocks from source file, a check to ensure source file block name
    doesn't exist in target file. Without such a check, I think a duplicate record error
    would occur sooner or later.

    And may I suggest, if you want folks to critique your code, you should post it in
    form that's easy to understand. For instance, attaching a dcl file will turn most
    people off. It's not relevant to your primary question about ODBX. I often rewrite
    code when I want to post a question here. Just so the question is clear.

    Related, a line like this will also trurn off the folks you are most interested in
    talking to.

    (setq cblist (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-ACAD-Object))))

    The expression returns the blocks collection vla-object of the active file. That's
    not a list, so the var name is misleading. In turn, that makes the rest of your code
    hard to understand at first glance.

    Joe Burke
     
    Joe Burke, Nov 10, 2004
    #11
  12. T.Willey

    T.Willey Guest

    Tony,

    Thanks for pointing this stuff out.

    Tim
     
    T.Willey, Nov 10, 2004
    #12
  13. T.Willey

    T.Willey Guest

    Joe,

    Thanks for the comments, as I am still learning.

    The reason why I posted the dcl file was incase someone tried to run it, just wanted them to be able to without comeing back and asking for the dcl file.

    When I tested it with blocks that were the same name, I didn't have a problem, but now that you said something, and made me think. I wonder if the new blocks being imported is over writting the one that already exist? I will have to check that out.

    About my variable names, I understand what you are talking about. On the fly while writting, I name how I reference them in my own mind. The collection is still like a list in my mind, even though when I stop and think about it, it really isn't.

    Tim
     
    T.Willey, Nov 10, 2004
    #13
  14. T.Willey

    T.Willey Guest

    Lucas,

    I will have to read your code to see where it differs from mine. Thanks for it.

    Tim
     
    T.Willey, Nov 10, 2004
    #14
  15. This is directed to Tony Tanzillo but anyone can chime in...
    Tony,
    I have found that when dealing with Land Desktop activex objects, such as PVI's from PVI collection, I have to release
    the PVI object after I use it or I get rather random but persistent crashes.
    I use a vlax-for loop like this: (this one deletes all but one special PVI...)

    (VLAX-FOR PVI PVIS
    (IF (/= (VLAX-GET-PROPERTY PVI 'STATION) 1234567.89)
    (VL-CATCH-ALL-APPLY 'VLAX-INVOKE-METHOD (LIST PVIS "DELETE" (VLAX-GET-PROPERTY PVI 'STATION)))
    )
    (VL-CATCH-ALL-APPLY 'vlax-release-object (list PVI))
    )

    Note the release object at the end of each loop.
    This seems to solve the problem of the crashes.

    Now I see no reason why this should be necessary but experience shows it is.
    I really need to understand what is going on with the PVI object, is there a reason I would get a problem with an object
    in a foreach loop?

    I think it has to do with a bug in the handling of the garbage cleanup of the com objects...any advice appereciated
    though.

    "T.Willey" <>
    |>This code seems to work, but I got some examples from here, and I'm not sure if I used them right. I was just wondering if people with more experience with Object DBX could take a glance and give me some pointers.
    |>
    |>What it does is import blocks from a drawing.
    |>
    |>Thanks.
    |>Tim
    |>
    |>ps. I attached the ".dcl" file, just rename the extension from ".txt" to ".dcl".
    |>
    |>(defun ImportBlockDia (BlockList / blist diaload ipblist bilist)
    |>
    |>(if BlockList
    |> (progn
    |> (setq blist (vl-sort BlockList '(lambda (x y) (< (vla-get-Name x) (vla-get-Name y)))))
    |> (setq diaload (load_dialog "CloseDwg.dcl"))
    |> (if (not (new_dialog "Cdrawings" diaload))
    |> (exit)
    |> )
    |> (start_list "tx2" 3); clear the list
    |> (mapcar '(lambda (x) (add_list (vla-get-Name x))) blist)
    |> (end_list)
    |> (action_tile "accept"
    |> "(progn
    |> (setq ipblist (get_tile \"tx2\"))
    |> (done_dialog 1)
    |> )"
    |> )
    |> (action_tile "cancel"
    |> "(progn
    |> (setq ipblist nil)
    |> (done_dialog 1)
    |> )"
    |> )
    |> (start_dialog)
    |> (if ipblist
    |> (progn
    |> (setq ipblist (read (strcat "(" ipblist ")")))
    |> (foreach item ipblist
    |> (setq bilist (cons (nth item blist) bilist))
    |> )
    |> )
    |> )
    |> )
    |>)
    |>bilist
    |>)
    |>
    |>;---------------------------------------------------------------------
    |>
    |>(defun c:CopyBlocks (/ dbxDoc rslt con *blocks cblist blist)
    |>
    |>(if (setq rslt (tmw:OpenDBX))
    |> (progn
    |> (setq cblist (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-ACAD-Object))))
    |> (setq *blocks (vla-get-Blocks (car rslt)))
    |> (vlax-for item *blocks
    |> (if
    |> (and
    |> (/= (vla-get-IsXRef item) :vlax-True)
    |> (not (vl-string-search "|" (vla-get-Name item)))
    |> (not (vl-string-search "*" (vla-get-Name item)))
    |> )
    |> (setq con (cons item con))
    |> )
    |> )
    |> (if (setq blist (ImportBlockDia con))
    |> (foreach item blist
    |> (vla-CopyObjects
    |> (car rslt)
    |> (vlax-SafeArray-Fill (vlax-Make-SafeArray vlax-vbObject '(0 . 0)) (list item))
    |> cblist
    |> )
    |> )
    |> )
    |> (VL-CATCH-ALL-APPLY 'vlax-release-object (list dbxDoc con *blocks cblist blist))
    |> (tmw:CloseDBX rslt)
    |> )
    |>)
    |>(princ)
    |>)
    |>
    |>;-----------------------------------------------------------------
    |>
    |>(defun tmw:OpenDBX (/ FileName NewFileName TestIf dbxDoc)
    |>
    |>(if (setq FileName (getfiled "Select file:" (getvar "dwgprefix") "dwg" 4))
    |> (progn
    |> (if (setq TestIf (open FileName "a"))
    |> (close TestIf)
    |> (progn
    |> (setq NewFileName (strcat (vl-filename-directory FileName) "\\" (strcat "CopyOf-" (vl-filename-base FileName) ".dwg")))
    |> (vl-file-copy FileName NewFileName)
    |> (setq FileName NewFileName)
    |> )
    |> )
    |> (setq dbxDoc (vla-GetInterfaceObject (vlax-get-ACAD-Object) "ObjectDBX.AxDbDocument.16"))
    |> (vla-Open dbxDoc FileName)
    |> (list dbxDoc FileName)
    |> )
    |>)
    |>)
    |>
    |>;----------------------------------------------------------------------
    |>
    |>(defun tmw:CloseDBX (Results / FileName)
    |>
    |>(setq FileName (cadr Results))
    |>(vl-Catch-All-Apply '(lambda () (vla-Close (car Resutls))))
    |>(vlax-Release-Object (car Results))
    |>(if (vl-string-search "CopyOf-" (vl-filename-base FileName))
    |> (vl-file-delete FileName)
    |>)
    |>)

    James Maeding
    jmaeding at hunsaker dot com
    Civil Engineer/Programmer
     
    James Maeding, Nov 10, 2004
    #15
  16. T.Willey

    LUCAS Guest

    HI all,

    If your [Chinese lang] is good enough ,

    you can visit

    http://www.mjtd.com/bbs/dispbbs.asp?boardID=27&ID=8884&page=1



    just wanted them to be able to without comeing back and asking for the dcl
    file.
    problem, but now that you said something, and made me think. I wonder if
    the new blocks being imported is over writting the one that already exist?
    I will have to check that out.
    fly while writting, I name how I reference them in my own mind. The
    collection is still like a list in my mind, even though when I stop and
    think about it, it really isn't.
     
    LUCAS, Nov 11, 2004
    #16
  17. T.Willey

    Joe Burke Guest

    Hi Tim,

    I ran your code. Nice work, BTW. It's simply skipping blocks with the same name in
    target file. You're right, the check I suggested isn't needed. Though still, you
    might want to know which ones were copied or skipped.

    If you want it to replace blocks of the same name you could do something like this.
    Check to see if source block name exists in target block collection. If so, use
    vlax-for to delete all objects in the target block definition. Then use CopyObjects
    to copy the objects from source block into the now empty target block definition. Of
    course this is getting into some dangerous territory, so be careful.

    I have something I wrote for myself which replaces same name blocks from one drawing
    to another using the above method. It uses dos_checklist (DOSLib) for the block
    selection dialog. Kinda nice since it provides a check box for each block name.

    Joe Burke
     
    Joe Burke, Nov 11, 2004
    #17
  18. T.Willey

    T.Willey Guest

    Joe,

    Thanks for testing it, and thanks for the compliment. Glad you pointed out what it was doing with blocks of the same name. I will look into your idea when I have some time. If I run into problems with the new part of the code, I will be back here posting. Work came up and have deadlines, ya know.

    Tim
     
    T.Willey, Nov 11, 2004
    #18
  19. T.Willey

    T.Willey Guest

    Final version (for now). Last update: will let you know what blocks will not be inserted.

    Tim

    ps Change the txt extension to lsp to work.
     
    T.Willey, Nov 16, 2004
    #19
  20. T.Willey

    T.Willey Guest

    Joe,

    I was trying to work on something that would replace one block 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.

    How were you able to do this?
    or if anyone else knows, could you please advise?

    Thanks.
    Tim

    ps. Here is what I had so far, but it doesn't work. The only thing it does is delete the objects form the old block.

    (defun ReplaceBlock (BlockOld BlockNew / cnt1 temp1)

    (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
    BlockNew
    (vlax-SafeArray-Fill (vlax-Make-SafeArray vlax-vbObject '(0 . 0)) (list temp1))
    BlockOld
    )
    (setq cnt1 (1+ cnt1))
    )
    )
    )
    )
     
    T.Willey, Nov 16, 2004
    #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.