Author Topic: Apologies and some ObjectDBX code ...  (Read 3260 times)

0 Members and 1 Guest are viewing this topic.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Apologies and some ObjectDBX code ...
« on: November 29, 2006, 04:06:26 PM »
Have been so busy at the new job / life haven't been able to participate here at all <insert crying icon here>. All I can say is "I sincerely wish you all well" and "here is some code / food for thought" in a <lame> attempt to make up for lost time. No time to explain how to use, the in-line comments will have to suffice.

Provided as is, complete with warts, pimples and errors -- no warranties stated or impied. In other words, use at your own risk!

:)

Code: [Select]
(defun _OdbxReport ( filelist reportname overwrite foo / handle document result )

    ;;==================================================================
    ;;
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  In short this function is a convenience wrapper. For a given
    ;;  filelist, reportname, overwrite toggle and arbitrary function
    ;;  'Foo' it will, if possible, cycle through all of the drawings in
    ;;  filelist and apply function 'Foo to said drawings.
    ;;
    ;;  Arguments:
    ;;
    ;;      filelist   : A list of path qualified files.
    ;;
    ;;      reportname : A path qualified file which will be opened for
    ;;                   output, writing over any original contents if
    ;;                   overwrite argument is non nil, otherwise
    ;;                   appending new data to existing.
    ;;
    ;;      overwrite  : As noted, indicates whther the report is
    ;;                   overwritten or appended.
    ;;
    ;;      foo        : Arbitrary function which must have this
    ;;                   signature:
    ;;
    ;;                   (defun foo ( docname document handle ) ... )
    ;;
    ;;                    Where:
    ;;
    ;;                        docname :  A string, the name of the
    ;;                                   document.
    ;;
    ;;                        document : An objectdbx document.
    ;;
    ;;                        handle   : A file handle opened for
    ;;                                   output.
    ;;
    ;;  For example, 'Foo' might be as simple as:
    ;;
    ;;      (lambda ( docname document handle )
    ;;          (princ
    ;;              (strcat
    ;;                  docname
    ;;                  " has "
    ;;                  (itoa
    ;;                      (vlax-get
    ;;                          (vlax-get
    ;;                              document
    ;;                             'RegisteredApplications
    ;;                          )
    ;;                         'Count
    ;;                      )
    ;;                  )
    ;;                  " appid(s).\n"
    ;;              )
    ;;              handle
    ;;          )
    ;;      )
    ;;
    ;;  What 'Foo' actually does with the objectdbx document or the
    ;;  handle this function cares not, its sole responsibility is to:
    ;;
    ;;      1.  Open the report file for output, either overwrite or
    ;;          append.
    ;;
    ;;      2.  Cycle through all files:
    ;;
    ;;          2.1 Open the file via objectdbx.
    ;;
    ;;          2.2 Pass document etc. to function 'Foo'.
    ;;
    ;;          2.3 Close the objectdbx file.
    ;;
    ;;      3. Close the report file.
    ;;
    ;;  reporting any errors thrown trying to open the report file,
    ;;  opening files via objectdbx, or unhandled errors thrown by
    ;;  function 'Foo'. Typically 'Foo' will interogate the objectdbx
    ;;  document and write data to the handle.
    ;;
    ;;  "But" you say, "it seems redundant, passing the document name
    ;;  when one could just use (vla-get-name document)".
    ;;
    ;;  Ahhhh, but if a temporary copy of the document is created by
    ;;  the (_OdbxOpen ...) function the name reported will be wrong. In
    ;;  other words, if 'Foo' needs to report the original document name
    ;;  it should use the docname argument rather than querying the
    ;;  document for its name, ergo the docname requirement. If the
    ;;  actual document name is desired you can use the afore mentioned
    ;;  vla-get-name function. If necessary you can use the supplied
    ;;  function _OdbxIsTempCopy function to determine if the document
    ;;  is not the original.
    ;;
    ;;  What's the point of all this again?
    ;;
    ;;  Typically function 'Foo' will interogate the document and write
    ;;  information to the data file represented by the handle. Could be
    ;;  block attribute data, could be some other rivoting data like
    ;;  AutoPlant component IDs, who knows. This function provides easy
    ;;  access to previous authored functions, like the _OdbxOpen and
    ;;  _OdbxClose functions to make easy the frequent exercise of using
    ;;  ObjectDBX to interogate multiple files. No point in penning the
    ;;  same scafolding again and again.
    ;;
    ;;==================================================================

    (cond
        (   (setq handle (open reportname (if overwrite "w" "a")))

            (foreach docname filelist

                (cond

                    (   (setq document (_OdbxOpen docname t))

                        (if
                            (vl-catch-all-error-p
                                (setq result
                                    (vl-catch-all-apply
                                       '(lambda ( )
                                            (foo
                                                docname
                                                document
                                                handle
                                            )
                                        )
                                    )
                                )
                            )

                            (princ
                                (strcat
                                    "(Foo docname document handle)"
                                    " threw this error: <"
                                    (vl-catch-all-error-message result)
                                    ">\n"
                                )
                            )

                        )

                        (_OdbxClose document)
                    )

                    (   (princ
                            (strcat
                                "Could not open <"
                                docname
                                "> with ObjectDBX.\n"
                            )
                        )
                    )
                )
            )

            (close handle)

        )

        (   (princ
                (strcat
                    "Could not open <"
                    reportname
                    "> for output.\n"
                )
            )
        )
    )
)

Code: [Select]
(defun c:Example ( )

    (_OdbxReport

        ;;  filelist

       '(
            "x:\\SomePath\\SomeName1.dwg"
            "x:\\SomePath\\SomeName2.dwg"
            "x:\\SomePath\\SomeName3.dwg"
        )

        ;;  reportname

        "c:\\MyReportName.txt"

        ;;  overwrite

        t

        ;;  foo

        (lambda ( docname document handle )
            (princ
                (strcat
                    docname
                    " has "
                    (itoa
                        (vlax-get
                            (vlax-get
                                document
                               'RegisteredApplications
                            )
                           'Count
                        )
                    )
                    " appid(s).\n"
                )
                handle
            )
        )
    )

    (princ)

)

And the supporting cast ...

Code: [Select]
(defun _OdbxOpen ( drawingname tempflag / foo exists odbxdoc tempfile result )

    ;;==================================================================
    ;;   
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  Open the document via ObjectDBX if possible (trap any errors).
    ;;
    ;;  If the file cannot be opened directly AND the tempflag is non
    ;;  nil try to open a temporary copy (flagging it as a copy).
    ;;
    ;;==================================================================

    (cond

        (   (and

                (defun foo ( odbxdoc drawingname )
                    (null
                        (vl-catch-all-error-p
                            (vl-catch-all-apply
                               '(lambda ( )
                                    (vla-open
                                        odbxdoc
                                        drawingname
                                    )
                                )
                            )
                        )
                    )
                )

                (setq exists (_Exists drawingname))

                (setq odbxdoc (_OdbxGetInterface))

                (foo odbxdoc drawingname)

            )

            ;;  File opened no problem.

            (setq result odbxdoc)

        )

        (
            (and

                exists

                odbxdoc

                ;;  Assumption: File exists in a read-only directory,
                ;;  (can't make associated dwl file) try make and use
                ;;  a temporary copy.

                (setq tempfile (_MakeTempFileCopy drawingname))

                (foo odbxdoc tempfile)

            )

            ;;  Flag the file as being a temp by adding a main dict
            ;;  entry named "OdbxTempCopy".
            ;;
            ;;  See companion functions --
            ;;
            ;;      _OdbxIsTempCopy
            ;;
            ;;      _OdbxDeleteIfTempCopy

            (vl-catch-all-apply
               '(lambda ( )
                    (vla-add
                        (vla-get-dictionaries odbxdoc)
                        "OdbxTempCopy"
                    )
                )
            )

            (setq result odbxdoc)

        )

        (   odbxdoc

            (vlax-release-object odbxdoc)

        )

    )

    result

)

Code: [Select]
(defun _OdbxClose ( document / filename )

    ;;==================================================================
    ;;   
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  Close the objectdbx document. If it was a temporary copy made by
    ;;  _OdbxOpen try to delete it.
    ;;
    ;;  See companion functions --
    ;;
    ;;      _OdbxOpen
    ;;
    ;;      _OdbxIsTempCopy
    ;;
    ;;==================================================================
   
    (if (_OdbxIsTempCopy document)
        (setq filename (vla-get-name document))
    )

    (vl-catch-all-apply
       '(lambda ( )
            (vlax-release-object document)
        )
    )

    (if filename
        (vl-catch-all-apply
           '(lambda ( )
                (vl-file-delete filename)
            )
        )
    )

    (princ)

)

Code: [Select]
(defun _OdbxGetInterface ( / version )

    ;;==================================================================
    ;;   
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  If possible create an instance of the ObjectDBX interface.
    ;;
    ;;  If I recall correctly Luis Esquivel helped me refine this way
    ;;  back in the day on the Autodesk forums. Others too have
    ;;  contributed to the collective objectdbx knowledge, folks like
    ;;  Tony Tanzillo, who was the first to publically share any info
    ;;  about said topic and who we are all indebted to.
    ;;
    ;;==================================================================

    (if (_OdbxGetCLSID)
        (vla-getinterfaceobject
            (vlax-get-acad-object)
            (apply 'strcat
                (cons "ObjectDBX.AxDbDocument"
                    (if (/= 15 (setq version (atoi (getvar "acadver"))))
                        (list "." (itoa version))
                    )
                )
            )
        )
    )
)

Code: [Select]
(defun _OdbxGetCLSID ( / key version dll )

    ;;==================================================================
    ;;   
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  Get the ObjectDBX CLSID so callers may attemp to create an
    ;;  objectdbx interface. If necessary register the dll (was required
    ;;  for early versions of AutoCAD, like 2000 IIRC.
    ;;
    ;;  If I recall correctly Luis Esquivel helped me refine this way
    ;;  back in the day on the Autodesk forums. Others too have
    ;;  contributed to the collective objectdbx knowledge, folks like
    ;;  Tony Tanzillo, who was the first to publically share any info
    ;;  about said topic and who we are all indebted to.
    ;;
    ;;==================================================================

    (cond
        (   (vl-registry-read
                (setq key
                    (strcat "HKEY_CLASSES_ROOT\\ObjectDBX.AxDbDocument"
                        (if (eq 15 (setq version (atoi (getvar "acadver"))))
                            "\\CLSID"
                            (strcat "." (itoa version) "\\CLSID")
                        )
                    )
                )
            )
        )
        (   (and
                (setq dll
                    (findfile
                        (strcat
                            "AxDb"
                            (itoa version)
                            ".dll"
                        )
                    )
                )
                (_RegSvr32 dll)
            )
            (vl-registry-read key)
        )
    )
)

Code: [Select]
(defun _OdbxIsTempCopy ( document / result )

    ;;==================================================================
    ;;   
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  Determine if the document is a temporary copy that had been made
    ;;  via the _OdbxOpen function.
    ;;
    ;;  See companion functions --
    ;;
    ;;      _OdbxOpen
    ;;
    ;;      _OdbxClose
    ;;
    ;;==================================================================

    (vl-catch-all-apply
        '(lambda ( )
            (setq result
                (not
                    (null
                        (vla-item
                            (vla-get-dictionaries document)
                            "OdbxTempCopy"
                        )
                    )
                )
            )
        )
    )

    result

)

Code: [Select]
(defun _RegSvr32 ( dll / cmd path match )

    ;;==================================================================
    ;;   
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  If possible register the specified dll.
    ;;
    ;;  If I recall correctly Luis Esquivel helped me refine this way
    ;;  back in the day on the Autodesk forums.
    ;;
    ;;==================================================================

    (vl-some
       '(lambda (x) (startapp x (strcat "\"" dll "\" /s")))
        (list
            (setq cmd "regsvr32.exe")
            (strcat
                (setq path (getenv "WinDir"))
                "\\System\\"
                cmd
            )
            (strcat path "\\System32\\" cmd)
        )
    )

    (setq match
        (strcat
            (strcase (vl-filename-base dll))
            "`.*"
        )
    )

    (vl-some
       '(lambda (x) (wcmatch (strcase x) match))
        (vl-registry-descendents "HKEY_CLASSES_ROOT")
    )

)

Code: [Select]
(defun _MakeTempFileCopy ( filename / result )

    ;;==================================================================
    ;;
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  If possible make a copy of the specified file in the temp
    ;;  folder.
    ;;
    ;;==================================================================

    (if
        (and
            (findfile filename)
            (vl-file-copy
                filename
                (setq result
                    (vl-filename-mktemp
                        nil
                        nil
                        (vl-filename-base filename)
                    )
                )
                nil
            )
        )
        result
    )
)

Code: [Select]
(defun _Exists ( filename / handle )

    ;;==================================================================
    ;;
    ;;  Written by Michael Puckett
    ;;
    ;;------------------------------------------------------------------
    ;;
    ;;  Return t if the file exists. Note that this differs from
    ;;  findfile function which will search the AutoCAD support path.
    ;;  This function merely reports whether a file exists as expressed.
    ;;
    ;;==================================================================

    (and
        (setq handle (open filename "r"))
        (null (close handle))
    )
)

Kind regards all!

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

GDF

  • Water Moccasin
  • Posts: 2081
Re: Apologies and some ObjectDBX code ...
« Reply #1 on: November 29, 2006, 04:13:35 PM »
Thanks

I take it....this no longer applies "Needs a day job"?

Gary
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

Fatty

  • Guest
Re: Apologies and some ObjectDBX code ...
« Reply #2 on: November 29, 2006, 06:04:48 PM »
Thank you

It is very tasty, my saliva drips till now :)

Have a happy work on new place,

Regards

~J'~

Arizona

  • Guest
Re: Apologies and some ObjectDBX code ...
« Reply #3 on: November 29, 2006, 06:24:17 PM »
Have been so busy at the new job / life haven't been able to participate here at all <insert crying icon here>. All I can say is "I sincerely wish you all well" and "here is some code / food for thought" in a <lame> attempt to make up for lost time. No time to explain how to use, the in-line comments will have to suffice.

Cool read Michael!

We missed you :-)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Apologies and some ObjectDBX code ...
« Reply #4 on: November 29, 2006, 07:31:36 PM »
Good to see you got a chance to raise your head for a moment Michael.

Interesting and topical topic.

be well
kwb

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

LE

  • Guest
Re: Apologies and some ObjectDBX code ...
« Reply #5 on: November 29, 2006, 07:35:30 PM »
Se te extraña Michael.

But first things first!

Cheers.

Slim©

  • Needs a day job
  • Posts: 6566
  • The Dude Abides...
Re: Apologies and some ObjectDBX code ...
« Reply #6 on: November 29, 2006, 10:44:57 PM »
Many thanks, MP. Gotta keep the MAN happy!
Thanks for the code, I'll figure it out as we go....
Don't work too hard,get some sleep & time with the wife... :-)
I drink beer and I know things....