Logistics working with Object DBX / OpenDocuments

Discussion in 'AutoCAD' started by David Kozina, Jan 4, 2005.

  1. David Kozina

    David Kozina Guest

    Just trying to clean up some code, as well as avoid evil code duplication
    where I can, and was wondering if I'm on the right track. I'm sure someone
    here will let me know ;)

    When I first started using ObjectDBX methods, I found some code posted by
    Jeff Mishler that I found very useful, and did much to get me on my way.
    The logic of it was basically to check through the open documents collection
    and, if the file was not open, return a DBX object which could then be
    manipulated. If the file WAS open, a prompt would be displayed telling the
    user to close the file, then try again. If the file didn't exist, a prompt
    would inform the user of that case, too.

    Later on, in response to another question of mine, (UCS importing), Joe
    Burke kindly posted some similar code, with the difference that if the
    document in question WAS open, IT would be returned OR, otherwise, a DBX
    object. (IOW, no need to close the file first.)

    Now as I look back over the routines I have since created (not many, yet)
    (currently based on JM's logic structure), I see in some of them that, at
    times, it would actually be useful to work over an open doc object, rather
    than forcing the user to close the document and re-running the routine (as
    in JB's logic structure). At other times, it probably doesn't matter too
    much. But what is more worrisome to me is that much of the code of the
    routines themselves is being repeated, as I copy one routine and transform
    it to another one. Kind of hard to explain, but the point is, I know this
    sort of code duplication is not a healthy practice, either.

    So... I'm trying to bust the routines up into smaller subfunctional chunks
    (as shown below), based a little more on JB's logic structure. I am
    assuming that whenever these functions will be called, it will most likely
    be in an Object DBX situtation (since the affected code at this point is ALL
    relating to modifications of DBX objects). But I'm wanting to at least make
    provisions now for the modifications of documents that may be open.

    The trick (I think) - and thus my question - is that later on, I'll probably
    need to be able to know what I 'snagged': Nothing, a DBX object, or an Open
    Document object - no? This is what I'm wondering about. Thus my use of the
    Dotted pair return in the djkGetDocObjAtPath function. My question is if
    this is a good way to handle the situation or if there is a more elegant way
    to do so. Hope this at least sort of makes sense.

    This is what I've got so far:

    ; Returns Open Document Object if found, or nil
    ; Based on code by Joe Burke 2004
    (defun djkGetOpenDocObjAtPath
    (FullPath_str ; Full Path String to Document
    /
    *djkAcadObject* ; Application Object
    *djkDocuments* ; Documents Collection Object
    SourceDoc_obj ; Source Document
    ; /
    ; vl:T
    )
    ; begin
    (setq *djkAcadObject* (vlax-get-acad-object))
    (setq *djkDocuments* (vlax-get-property *djkAcadObject* 'Documents))
    ; Iterate through the open documents collection
    (vlax-for OpenDoc_obj *djkDocuments*
    ; begin loop
    (if (= FullPath_str (vlax-get-property OpenDoc_obj 'FullName))
    ; then - found it
    (setq SourceDoc_obj OpenDoc_obj)
    ; else - keep looking
    ;
    );_end if
    ; end loop
    );_end vlax-for
    ; return what was found - or nil if nothing
    SourceDoc_obj
    ; end
    );_end defun


    ;|
    Based on code by Joe Burke & Jeff Mishler - 2004
    Modified 2005 by David Kozina
    Returns Open Document Object or ODBX Document Object
    dotted pair or nil: (# . <_obj>), #: 0 = DBX obj, 1 = Open Doc
    |;
    (defun djkGetDocObjAtPath
    (FullPath_str ; Full Path String to Document
    /
    SourceDoc_obj ; Source Document
    ; /
    ; (djkGetOpenDocObjAtPath
    ; (djkGetDBXObject
    )
    ; begin
    (cond
    ; case source file is open...
    ; return Open Doc Object dotted pair
    ((setq SourceDoc_obj
    (djkGetOpenDocObjAtPath FullPath_str)
    );_end setq
    (cons 1 SourceDoc_obj)
    ); end case
    ; case - file not open but DOES exist...
    ; return DBX object dotted pair
    ((findfile FullPath_str)
    (cons 0 (djkGetDBXObject)) ;<- Note: DBX subfunction not posted
    ); end case
    ; default case - file doesn't exist...
    ; return nil...
    (T
    nil
    ); end case
    );_end cond
    ; end
    );_end defun


    ; Save DBX Object - Call as Needed
    ; based on code by Jeff Mishler - 2004
    (defun djkDBXObjectSaveAs
    (DBX_obj ; DBX Object
    /
    ; /
    ; vl:T
    )
    ; begin
    ; Save changes to file - Must use SaveAs, Save not implemented
    (vlax-invoke-method
    DBX_obj
    'Saveas
    (vlax-get-property DBX_obj 'Name)
    )
    ; end
    );_end defun


    Using the above subfunctions, I am envisioning the overall routine logic to
    go something like this:

    ;...
    (setq SourceDoc_dp
    (djkGetDocObjAtPath FullPath_str)
    );_end setq

    (cond
    ; case - DBX route
    ((zerop (car SourceDoc_dp))
    ; "open" source for our use...
    (vlax-invoke-method
    (cdr SourceDoc_dp)
    'Open
    FullPath_str
    )

    ; do stuff here...

    ; use following line where needed...
    ; (djkDBXObjectSaveAs (cdr SourceDoc_dp))

    ; we're done with it
    (vlax-release-object (cdr SourceDoc_dp))
    ); end case

    ; case - OpenDoc route
    ((SourceDoc_dp)

    ; do stuff here...

    ); end case

    ; default case - no file existed
    (T
    (alert "File does not exist")
    ); end case
    );_end cond
    ;...

    The second half of my question relates to the routine logic of the last bit,
    itself.
    Typically, the general cond statement logic will be duplicated in the DBX
    routines themselves.
    (The parts that will change would be the "do stuff here..." sections.)
    Is there any way to break this down any more, or is this about as good as it
    gets?

    Any guidance or suggestions regarding the above would be appreciated.

    Best regards,
    David Kozina
     
    David Kozina, Jan 4, 2005
    #1
  2. David Kozina

    Joe Burke Guest

    Hi David,

    On topic:

    I think everyone would agree, there's two basic reasons for using this stuff. Either
    to get data from the source file, which in turn is used somehow in the active file.
    Or to modify the source file in some manner and save those changes.

    As I read your code, it seems to assume the second case. IOW, if all you want is data
    from source file, whether it comes from an open or DBX doc is of no concern. In that
    case, it seems returning a dotted pair from djkGetDocObjAtPath passes information to
    the calling function which is of no use. Do you agree, or maybe I misread your code?

    I should mention, the majority of functions I have which use this stuff are intended
    to get data from source, rather than put data and save. That's not to say I don't do
    the other thing. But in my situation, usually a stand-alone user, whether I've
    modified a DBX or open doc typically isn't a concern either way. Things may be
    different if your code is intended to be used by others who don't understand what's
    going on under-the-hood.

    Off topic:

    I noticed this (T nil) at the end of the cond statement in djkGetDocObjAtPath. I'm
    taking this opportunity to ask why in terms of the example code in developer help
    which mentions this method and presents the following code as an example.

    (cond
    ((= s "Y") 1)
    ((= s "y") 1)
    ((= s "N") 0)
    ((= s "n") 0)
    (t nil)
    )

    Assuming (setq s "A") the following also returns nil.

    (cond
    ((= s "Y") 1)
    ((= s "y") 1)
    ((= s "N") 0)
    ((= s "n") 0)
    )

    If none of the conditions return T, cond returns nil by default. Or am I missing
    something here?

    Joe Burke
     
    Joe Burke, Jan 5, 2005
    #2
  3. Joe,

    The only reason to use the explicit condition to return nil would be for
    clarity of intent or code maintenance. Neither of which, IMHO, is strong
    enough of a case to add the statement.

    --
    R. Robert Bell


    ....
    Off topic:

    I noticed this (T nil) at the end of the cond statement in
    djkGetDocObjAtPath. I'm
    taking this opportunity to ask why in terms of the example code in developer
    help
    which mentions this method and presents the following code as an example.

    (cond
    ((= s "Y") 1)
    ((= s "y") 1)
    ((= s "N") 0)
    ((= s "n") 0)
    (t nil)
    )

    Assuming (setq s "A") the following also returns nil.

    (cond
    ((= s "Y") 1)
    ((= s "y") 1)
    ((= s "N") 0)
    ((= s "n") 0)
    )

    If none of the conditions return T, cond returns nil by default. Or am I
    missing
    something here?
     
    R. Robert Bell, Jan 5, 2005
    #3
  4. David Kozina

    Joe Burke Guest

    Robert,

    Thanks for the confirmation.

    Joe Burke
     
    Joe Burke, Jan 5, 2005
    #4
  5. David Kozina

    David Kozina Guest

    <heh> You haven't tried maintaining *my* code...

    (Correct in your assessment of the reasons, btw)

    I know it doesn't need to be there, just am trying to be as consistent as
    possible in my coding style (always providing a default case, etc), which in
    turn seems to have lead to fewer 'show time' errors as of late. Perhaps I
    should ;remark those lines - would THAT be acceptable? ;)

    Thanks for the comments, fellas.

    Best regards,
    David Kozina
     
    David Kozina, Jan 5, 2005
    #5
  6. David Kozina

    David Kozina Guest

    Joe,

    Thanks for the comments.

    Right now, the routines that use this stuff usually ARE modifying the DBX
    object, rather than just gleaning information from it. For instance, one
    routine copies a detail drawing from one folder to another, renames it, then
    modifies the Titleblock Bubble ID Number accordingly. I know how to do this
    via Object DBX, but I believe the logic (and code) for modifying an open
    drawing in this case would have to be different (two problems arising
    relating to attribute text justification and thumbnail images in the DBX
    object, for instance - whereas I haven't yet worked out the logic for an
    open drawing condition, but I am assuming it won't have to deal with those
    two particular problems), thus I am thinking I need to be able to discern
    what I'm working with - a DBX object or an open document object. So I
    thought a dotted pair would serve to do the job for this. Does this make
    any sense?

    One of my main questions is if there is a decent way to 'modularize' that
    'outermost' final code segment any further. Perhaps using as arguments a
    FullPath string, an ObjDBXFunctionCall, and an OpenDocFunctionCall?
    Then I could basically create a function out of that COND statement, true?
    I am just trying to get rid of the repetition that I see starting to develop
    in my code in this case. Does this make any sense?

    Best regards,
    David Kozina

    PS I noted after my first post that the (zerop test case call will crash if
    SourceDoc_dp is nil - it's fixable, but perhaps there is a more elegant
    solution?
     
    David Kozina, Jan 5, 2005
    #6
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.