Author Topic: Simulate Microstation's Exchange command?  (Read 3486 times)

0 Members and 1 Guest are viewing this topic.

Guitar_Jones

  • Guest
Simulate Microstation's Exchange command?
« on: June 04, 2009, 12:43:38 AM »
Does anyone know if there's an existing program for AutoCAD that functions like Exchange in Microstation?
XrefEdit is similar but comes with more trouble than its worth. i was looking for something that would
close the active drawing and open the selected reference file in the same location you were at in the active file
(whether in paper or model space).

Matt__W

  • Seagull
  • Posts: 12955
  • I like my water diluted.
Re: Simulate Microstation's Exchange command?
« Reply #1 on: June 04, 2009, 08:19:01 AM »
I think I remember seeing some sort of VBA app that would open the selected xref to the same location (not sure if it worked with both MS and PS) as in the host drawing.  I'll poke around and see if I can find it.
Autodesk Expert Elite
Revit Subject Matter Expert (SME)
Owner/FAA sUAS Pilot @ http://skyviz.io

Matt__W

  • Seagull
  • Posts: 12955
  • I like my water diluted.
Re: Simulate Microstation's Exchange command?
« Reply #2 on: June 04, 2009, 08:25:19 AM »
Autodesk Expert Elite
Revit Subject Matter Expert (SME)
Owner/FAA sUAS Pilot @ http://skyviz.io

Guitar_Jones

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #3 on: June 04, 2009, 08:40:58 AM »
I can definitely work with that. Thanks Matt

Guitar_Jones

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #4 on: June 09, 2009, 05:46:00 AM »
Code: [Select]
Decided to try it in lisp and here's what i got so far. Still needs "clean up".
If in the model layout, it will close the active drawing and open the selected reference file with the same orientation/screen coords.
If in another layout, it will add the choice of switching to the model layout with the same orientation/screen coords.
Must be in model space (whether it's the model layout tab or an active viewport.)
Currently writes dcl and scr files to c:\temp. Suggestions are welcome.

Type XC to run.

[code;; NOTES:
;; The intent is similar to that of refedit
;; "xc" or "exchange" allows user to pick an xref to open and display the view/orientation of the current drawing.
;; If executed in a layout tab,  option to exchange with Model Space is available

;; "sv" or "saveview" will capture view/orientation of current drawing
;; "gv" or "getview"  will match view/orientation saved by "saveview" or "exchange" (only functions in modelspace)

;; Xref path found by using several functions by Joe Burke
;; Coordinates acquired by using VPCords by MP

(defun c:saveview()
(if (/= (getvar 'ctab) "Model")(vla-put-mspace (vla-get-ActiveDocument (vlax-get-Acad-Object)) :vlax-true))
(vl-cmdf "ucs" "v")
(setq *VLISP-NEW-FULL-INIT* (vpcords))
(if xlist
(setq *VLISP-NEW-FULL-INIT* (append *VLISP-NEW-FULL-INIT* xlist))
(setq *VLISP-NEW-FULL-INIT* (append *VLISP-NEW-FULL-INIT* (list (getvar 'ucsxdir))))
);
);defun
(defun c:sv()(c:saveview))

(defun c:getview()
(vl-cmdf "ucs" "w")
(vl-cmdf "ucs" "0,0")
(vl-cmdf (nth 2 *VLISP-NEW-FULL-INIT*) "")
(vl-cmdf "plan" "c")
(vl-cmdf "zoom" "window")
(vl-cmdf (nth 0 *VLISP-NEW-FULL-INIT*))
(vl-cmdf (nth 1 *VLISP-NEW-FULL-INIT*))
(vl-cmdf "ucs" "w")
);defun
(defun c:gv()(c:getview))

(defun VPCords (/ viewctr vphps vphms vpscale psvpctr difference psviewctr halfHeight aspectRatio offset)
(if (= (getvar 'ctab) "Model")
(progn
    (   (lambda (offset)
            (   (lambda (viewctr)
                    (list
                        (mapcar '- viewctr offset)
                        (mapcar '+ viewctr offset)
                    )
                )
                (getvar "viewctr") ;VPCords by MP
            )
        )
        (   (lambda (halfHeight aspectRatio)
                (list
                    (* halfHeight aspectRatio)
                    halfHeight
                )
            )
                (* 0.5 (getvar "viewsize"))
                (apply '/ (getvar "screensize"))
        )
    )
);progn

(progn ;Acquired through VPCords-this version used to get model space coords while in a viewport
  (setq viewctr (getvar "viewctr");Viewport Center in drawing units
  vphps (cdr (assoc 41 (entget (acet-currentviewport-ename) '("ACAD"))))
  vphms (getvar "viewsize")
  vpscale (/ vphms vphps)
  psvpctr (cdr (assoc 10 (entget (acet-currentviewport-ename) '("ACAD"))))
  difference (mapcar (function (lambda (x y)(- y (* vpscale x)))) psvpctr viewctr)
xlist (list (getvar 'ucsxdir))
 );setq
  (vla-put-mspace (vla-get-ActiveDocument (vlax-get-Acad-Object)) :vlax-false)
  (vl-cmdf "ucs" "w")
  (setq psviewctr (mapcar (function (lambda (x y) (+ y (* vpscale x)))) (getvar "viewctr") difference)
halfHeight (* (* 0.5 (getvar "viewsize")) vpscale)
aspectRatio (apply '/ (getvar "screensize"))
offset (list (* halfHeight aspectRatio) halfheight)
    )
(list (mapcar '- psviewctr offset)
            (mapcar '+ psviewctr offset)
)

)
)
)

(defun c:switch (/ )
(if (and (= (getvar 'sdi) 1)(not Model))
(vl-cmdf
                    "_.vbastmt"
                  (strcat "AcadApplication.Documents.Open \"" xrefpath "\"")
);vl
)
);defun

(defun Is_ReadOnly (path / dwlfile x )
  (setq dwlfile (vl-string-subst ".dwl" ".dwg" path))
  (if (setq x (open dwlfile "r"))(progn (alert (strcat "The selected Xref is occupied by " (read-line x) ". Try again later."))(close x)(exit)))
);

(defun c:xc ()(c:exchange))
(defun c:exchange (/ blocks datalst cnt nestcnt doc xpathlst openscrfile file dwgpre dwglist *error* xrefpathlist
userclick xreflist BlkCol xrefinfo xrefselection xrefname xlist Model what)
(vl-load-com)
(defun *error* ( msg )
(cond
      ((not msg))
      ((wcmatch (strcase msg) "*QUIT*,*CANCEL*"))
      (T (princ (strcat "\nError: " msg)))
    )
    (setvar "cmdecho" 1)
        (princ)
);defun *error*

(if (and (/= (getvar 'ctab) "Model")(= (vla-get-mspace (vla-get-ActiveDocument (vlax-get-Acad-Object))) :vlax-false))(progn (alert "\nViewport must be active! Exiting XC.lsp... ")(exit)))

  ;; Argument: path string
  ;; Returns the path portion as a list of strings in reverse order.
  ;; (setq s "..\\..\\Common ABC\\XRefs ABC\\Plan Unit 3BR KLSC.dwg")
  ;; ("\\XRefs ABC" "\\Common ABC" "\\.." "\\..")
  ;; The file name is not included.
  (defun PathList (str / idx pat pos lst)
    (setq idx 0 pat "\\")
    (while (setq pos (vl-string-search pat str idx))
      (setq lst (cons (strcat pat (substr str (1+ idx) (- pos idx))) lst)
            idx (1+ pos)
      )
    )
    lst
  ) ;end

  ;; Returns a list of lists: (fullname fn blockname expath)
  (defun XrefsData ( / blkname expath fullname fn xlst NestedXref)

    ;; Argument: block definition vla-object.
    ;; Returns a count number if the xref is nested, otherwise nil.
    ;; Based on code by Stephan Koster in a program named XrefTree.
    ;; Function renamed from nested_p.
    ;; The nestcnt variable is local to the primary routine.
    ;; There is a known flaw in the function which Jason pointed out.
    ;; If an xref is both nested and referenced as a parent, the
    ;; function does not flag it as nested. The fallout from that situation,
    ;; if it occurs, is handled near the end of the primary routine.
    (defun NestedXref (blkdef / elst)
      (setq elst (entget (vlax-vla-object->ename blkdef)))
      (if
        (or
          (not (vl-position '(102 . "{BLKREFS") elst))
          (and
            (vl-position '(102 . "{BLKREFS") elst)
            (not (cdr (assoc 331 elst)))
          )
        )
        (setq nestcnt (1+ nestcnt))
        ;; Else return nil to the parent function.
      )
    ) ;end

    (vlax-for x blocks
      (if
        (and
          (= -1 (vlax-get x 'IsXref))
          (setq blkname (vlax-get x 'Name))
          ;; Filter out nested xrefs.
          (not (NestedXref x))
          (setq expath (cdr (assoc 1 (tblsearch "block" blkname))))
          (setq fn (strcat (vl-filename-base expath) ".dwg"))
        )
        (progn
          (cond
            ;; Xref found at full or relative path.
            ((setq fullname (findfile expath)))
            ;; Xref found in the same folder as the active file
            ;; and it the xref has not been renamed.
            ((setq fullname (findfile fn)))
            ;; Xref not found so far. Substitute the path for full name.
            (T (setq fullname expath))
          )
          (setq xlst (cons (list fullname fn blkname expath) xlst))
        )
      )
    )
    xlst
  ) ;end

  (defun XrefSearch (strlst path dot / xpath)
    (if (and strlst path dot)
      (progn
        (setq path (strcat "\\" path))
        (while
          (and
            strlst
            (not (findfile (setq xpath (strcat dot
              (substr (setq path (strcat (car strlst) path)) 2))))
            )
          )
          (setq strlst (cdr strlst))
          (setq dot (strcat dot dot))
        )
        (if (and xpath (findfile xpath))
          xpath
        )
      )
    )
  ) ;end
  ;;;; END SUB-FUNCTIONS ;;;;
  ;;;; START PRIMARY FUNCTION ;;;
  (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))

  (setvar "cmdecho" 0)

  (setq blocks (vla-get-blocks doc)
        cnt 0
        nestcnt 0
        datalst (XrefsData)
  )

(foreach x datalst
(setq XrefList (append XrefList (list (caddr x))))
(setq xpathlst (append xpathlst (list (car x))))
)

(if XrefList (setq XrefList (acad_strlsort xreflist)))

(if (/= (getvar 'ctab) "Model")
(progn (initget "Reference Mspace")(setq what (getkword "\nExchange with [ Reference / Mspace] ?:<R> ")));progn
);if

(if (or (= what "Reference")(= what nil))
(progn
(if (/= (getvar 'ctab) "Model")(vla-put-mspace doc :vlax-true))
(setq xrefinfo (entget (car (entsel "\nSelect Xref to exchange with..."))))
(setq xrefselection (cdr (assoc 2 xrefinfo)))
(if (null xrefselection)(progn (alert "Selected object is not an xref.Try again.")(exit)))
(if Xpathlst (setq Xpathlst (acad_strlsort xpathlst)))
(foreach x xpathlst
(if (/= (vl-string-search xrefselection x) nil)(setq xrefpathlist (append xrefpathlist (list x))))
);
(setq xrefpath (nth 0 xrefpathlist))
(Is_Readonly xrefpath)
)
);if

(vl-cmdf "ucs" "v")
(setq *VLISP-NEW-FULL-INIT* (vpcords))
(if xlist
(setq *VLISP-NEW-FULL-INIT* (append *VLISP-NEW-FULL-INIT* xlist))
(setq *VLISP-NEW-FULL-INIT* (append *VLISP-NEW-FULL-INIT* (list (getvar 'ucsxdir))))
);

       (if (= what "Mspace")(progn (setvar 'ctab "Model")(setq Model 1)(setq xrefpath 1)))
     (progn (setq openscrfile (open (setq file (strcat "c:\\temp\\temp.scr")) "w")) ;derived from post by Ronjonp
           (progn (foreach f (list xrefpath)
                    (if (and (= (getvar 'sdi) 0)(not Model))(write-line (strcat "_.open \"" f "\"") openscrfile))
          (write-line "switch" openscrfile)
            (if (and (= (getvar 'sdi) 1)(not Model))(write-line "Y" openscrfile))
                    (write-line "ucs w" openscrfile) ;
                    (write-line "ucs 0,0 (nth 2 *VLISP-NEW-FULL-INIT*) " openscrfile) ;
                    (write-line "plan c" openscrfile) ;
                    (write-line "zoom window" openscrfile) ;
    (write-line "(nth 0 *VLISP-NEW-FULL-INIT*) (nth 1 *VLISP-NEW-FULL-INIT*)" openscrfile);
          (write-line "ucs w" openscrfile)
                  )
                  (close openscrfile)
                  (command ".script" file)
           )
           (vl-file-delete file)
    )

);defun



replaced code
« Last Edit: September 21, 2010, 02:39:17 PM by Guitar_Jones »

Joe Burke

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #5 on: June 09, 2009, 06:59:28 AM »
After copy code on-screen, paste to new file and save as Exchange.lsp and load...

Command: exchange
; error: bad argument type: stringp nil

Maybe post the code as a file?

Guitar_Jones

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #6 on: June 09, 2009, 07:06:18 AM »
you have to type xc to run..sorry, just added to the previous post

Joe Burke

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #7 on: June 09, 2009, 07:48:47 AM »
Just my opinion, I think you need a workaround for SDI must be 1.

Guitar_Jones

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #8 on: June 09, 2009, 08:19:02 AM »
Just my opinion, I think you need a workaround for SDI must be 1.

Yea..I just started storing info in *VLISP-NEW-FULL-INIT* and I should've started with setenv from the beginning. I agree that it should not be limited to the SDI setting and that should be an easy fix. Thanks for the input Joe.
« Last Edit: June 10, 2009, 11:54:00 AM by Guitar_Jones »

Joe Burke

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #9 on: June 09, 2009, 08:26:54 AM »
You're welcome. Looking forward to your next version.

Guitar_Jones

  • Guest
Re: Simulate Microstation's Exchange command?
« Reply #10 on: June 10, 2009, 11:50:38 AM »
Haven't had much time to play, but here's a working version with the SDI workaround.
I was mistaken about the sdi setting affecting *VLISP-NEW-FULL-INIT*.
Command is now 'exchange' or 'xc'.

*EDIT*-removed code
« Last Edit: June 16, 2009, 09:38:49 AM by Guitar_Jones »