Author Topic: Change All Xrefs Path type - Found  (Read 1292 times)

0 Members and 1 Guest are viewing this topic.

MSTG007

  • Gator
  • Posts: 2598
  • I can't remeber what I already asked! I need help!
Change All Xrefs Path type - Found
« on: June 29, 2016, 05:49:16 PM »
I stumbled on this Routine. I thought I would give it a try and I get an error: malformed list on input.

This originally came from herer:
https://lispbox.wordpress.com/2015/02/10/change-all-xrefs-path-type-fullrelative-vice-versa/

Maybe I could have copied it wrong?

( I did remove a lot of the explaination code that in here to make the topic be able to post; because of the 2,000 characters warning.)


Code: [Select]


(vl-load-com)

(defun c:FRX ( / *error* fullrel actdoc *acad* files path fullpath
 fn docslst filelst temppath reuse temp pathlst
 cnt nestcnt datalst masterlst oklst notfoundlst
 multiplelst blkname blkobj expath time multans
 returnlst msg version formatlst targdoc newerdoclst
 documents processpathlst prmpt init rpwhat formatans
 lenlst curformat paths
 RPX:DocAtPath RPX:Repath RPX:GetDate
 RPX:CurrentFileFormat RPX:CheckDOSLib RPX:XrefsData)
 ;; globals: *projpath* *OKDOSLib*

(defun *error* (msg)
 (cond
 ((not msg))
 ((wcmatch (strcase msg) "*QUIT*,*CANCEL*"))
 (T (princ (strcat "\nError: " msg)))
 )
 (if
 (and
 targdoc
 (not (vlax-object-released-p targdoc))
 )
 (vlax-release-object targdoc)
 )
 (setvar "cmdecho" 1)
 (vla-EndUndoMark actdoc)
 (if (eq (type dos_waitcursor) 'EXRXSUBR)
 (dos_waitcursor)
 )

(princ)
 ) ;end error

;;;; START SUB-FUNCTIONS ;;;;

;; Argument: document vla-object.
 (defun RPX:XrefsData (doc / blocks blkname fn xreflst expath
 NestedXref GetPath)

;; Argument: xref block definition vla-object.
 (defun GetPath (blkdef / elst)
 (setq elst (entget (vlax-vla-object->ename blkdef)))
 (cdr (assoc 1 (entget (cdr (assoc 360 elst)))))
 )

;; Argument: block definition vla-object.
 (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)))
 )
 )
 (if nestcnt (setq nestcnt (1+ nestcnt)))
 ;; Else return nil to the parent function.
 )
 ) ;end

(setq blocks (vla-get-blocks doc))

(vlax-for x blocks
 (if
 (and
 (= -1 (vlax-get x 'IsXref))
 ;; Filter out nested xrefs.
 (not (NestedXref x))
 (setq blkname (vlax-get x 'Name))
 ;; Existing path
 (if (vlax-property-available-p x 'Path)
 (setq expath (vlax-get x 'Path))
 (setq expath (GetPath x))
 )
 (setq fn (strcat (vl-filename-base expath) ".dwg"))
 )
 (setq xreflst (cons (list fn blkname expath x) xreflst))
 )
 )
 xreflst
 ) ;end RPX:XrefsData

;; Argument: full path.
 (defun RPX:GetDate (path / date year mo day hr mn sec)
 (setq date (cdr (car (dos_filedate path)))
 date (rtos date 2 6)
 year (substr date 1 4)
 mo (substr date 5 2)
 day (substr date 7 2)
 hr (substr date 10 2)
 mn (substr date 12 2)
 sec (substr date 14 2)
 )
 (strcat year "/" mo "/" day " " hr ":" mn ":" sec)
 )

;; Used with dos_dwgver to determine if an ODBX doc
 (defun RPX:CurrentFileFormat ( / v)
 (setq v (atoi (getvar "acadver")))
 (cond
 ((= 15 v) 2000)
 ((= 16 v) 2004)
 ((= 17 v) 2007)
 ((= 18 v) 2010)
 (T 2013)
 )
 )

;; Added 2/20/2008.
 (defun RPX:CheckDOSLib ()
 (if
 (and
 (eq (type dos_waitcursor) 'EXRXSUBR)
 (eq (type dos_relativepath) 'EXRXSUBR)
 (eq (type dos_getdir) 'EXRXSUBR)
 (eq (type dos_ispathsameroot) 'EXRXSUBR)
 (eq (type dos_find) 'EXRXSUBR)
 (eq (type dos_getfilem) 'EXRXSUBR)
 (eq (type dos_msgbox) 'EXRXSUBR)
 (eq (type dos_dwgver) 'EXRXSUBR)
 (eq (type dos_filedate) 'EXRXSUBR)
 ;; Used to check if file is read only
 ;; in the RPX:DocAtPath function.
 (eq (type dos_file) 'EXRXSUBR)
 )
 (setq *OKDOSLib* T)
 (progn
 (princ "\nDOSLib from Robert McNeel & Associates is required. ")
 (princ "\nIt's available for free at http://www.mcneel.com. ")
 (princ "\nExiting... ")
 (exit)
 )
 )
 ) ;end

;; Argument: full path.
 (defun RPX:DocAtPath (path / version file srcdoc)
 ;check the documents collection
 (vlax-for x (vla-get-documents *acad*)
 (if
 (and
 (eq (strcase path) (strcase (vlax-get x 'FullName)))
 (or
 (and
 (>= (atoi (getvar "acadver")) 17)
 (/= 1 (logand 1 (last (dos_file path))))
 )
 ;; For DOSLib prior to version 7.0.
 (and
 (= (atoi (getvar "acadver")) 17)
 (/= 1 (logand 1 (last (dos_file path))))
 )
 (and
 ( (setq version (atoi (getvar "AcadVer"))) 15)
 (setq srcdoc
 (vla-GetInterfaceObject *acad*
 (strcat "ObjectDBX.AxDbDocument." (itoa version))))
 ;; Catch the error if file format is later than the version
 ;; in use. Return nil.
 (if (vl-catch-all-error-p
 (vl-catch-all-apply
 '(lambda ()
 (vla-open srcdoc path)))
 )
 (setq srcdoc nil)
 )
 )
 ;prior to 2004
 (T
 (if
 (and
 (vl-catch-all-error-p
 (vl-catch-all-apply
 'vla-GetInterfaceObject
 (list *acad* "ObjectDBX.AxDbDocument")))
 (setq file (findfile "AxDb15.dll"))
 )
 (startapp "regsvr32.exe" (strcat "/s \"" file "\""))
 )
 (setq srcdoc (vla-GetInterfaceObject *acad* "ObjectDBX.AxDbDocument"))
 (if (vl-catch-all-error-p
 (vl-catch-all-apply
 '(lambda ()
 (vla-open srcdoc path)))
 )
 (setq srcdoc nil)
 )
 )
 )
 )
 srcdoc
 ) ;end

;; Arguments: document and a list of lists.
 (defun RPX:Repath (doc lst / xname expath blk fullpath docname docpath
 name newpath reportlst)

(foreach x lst
 ;; Xref block name
 (setq xname (cadar x))
 ;; Existing path
 (setq expath (caddar x))
 ;; xref block vla-object
 (setq blk (last (car x)))
 (setq fullpath (cadr x))
 (if (vl-position doc docslst)
 (setq docname (vlax-get doc 'Name)
 docpath (vlax-get doc 'Path)
 )
 (setq name (vlax-get doc 'Name)
 docname (strcat (vl-filename-base name) ".dwg")
 docpath (vl-filename-directory name)
 )
 )

(if (eq "Relative" fullrel)
 (progn
 (setq newpath
 (dos_relativepath
 ;; Path to the document passed.
 docpath
 ;; Full path to xref.
 fullpath
 )
 )
 (if (not (vl-string-search "\\" (substr newpath 3)))
 (setq newpath (substr newpath 3))
 )
 )
 ;; Else fullrel is "Full" path.
 (setq newpath fullpath)
 )

;; Check the path found is not the same as the original path.
 ;; Repath if not.
 (if (not (eq (strcase expath) (strcase newpath)))
 (progn
 (if (equal doc actdoc)
 (command "._xref" "path" xname newpath)
 (vlax-put blk 'Path newpath)
 )

(setq cnt (1+ cnt))
 (setq reportlst (cons (list xname newpath) reportlst))
 )
 )

;; Double check each xref which should have been repathed actually was.
 (if (equal doc actdoc)
 (foreach x reportlst
 (if (not (eq (cadr x) (cdr (assoc 1 (tblsearch "block" xname)))))
 (command "._xref" "path" (car x) (cadr x))
 )
 )
 )

) ;foreach

(if reportlst (list docname reportlst))

) ;end RPX:Repath
 ;; ----------------------

;;;; END SUB-FUNCTIONS ;;;;

;;;; START MAIN FUNCTION ;;;;

(if (not *OKDOSLib*)
 (RPX:CheckDOSLib)
 )

(setq *acad* (vlax-get-acad-object)
 actdoc (vla-get-ActiveDocument *acad*)
 documents (vla-get-Documents *acad*)
 )

(vla-StartUndoMark actdoc)

(setq cnt 0)
 (setvar "cmdecho" 0)

(initget "Full Relative")
 (setq fullrel (getkword "\nPath type [Full/Relative] : "))
 (if (not fullrel) (setq fullrel "Relative"))

;; If 2004 or earlier only the Current option is allowed because
 (if (< (atof (getvar "acadver")) 16.1)
 (setq rpwhat "Current")
 (progn
 (if (< 1 (vlax-get documents 'Count))
 (setq prmpt (strcat "\nRepath current drawing, all opened drawings, "
 "or browse? [Browse/Current/Opened] : ")
 init "Browse Current Opened"
 )
 (setq prmpt "\nRepath current drawing or browse? [Browse/Current] : "
 init "Browse Current"
 )
 )
 (initget init)
 (setq rpwhat (getkword prmpt))
 (if (not rpwhat) (setq rpwhat "Browse"))
 )
 )

;; Option to reuse of the last project folder selected.
 (if *projpath*
 (progn
 (setq temppath *projpath*)
 (princ (strcat "\nCurrent folder: " *projpath*))
 (initget "Yes No")
 (setq reuse (getkword "\n Use current Project folder? [Yes/No] : "))
 (if (eq reuse "No")
 (setq *projpath* (dos_getdir "Select Project Folder" (getvar "dwgprefix")))
 )
 (if
 (and
 (eq reuse "No")
 (not *projpath*)
 )
 (progn
 (setq *projpath* temppath)
 (exit)
 )
 )
 )
 ;else
 (if
 (not
 (setq *projpath* (dos_getdir "Select Project Folder" (getvar "dwgprefix")))
 )
 (exit)
 )
 )

;; List of open files.
 (vlax-for x documents
 (setq docslst (cons x docslst))
 )

;; Browse/Current/Opened
 (cond
 ;; Process selected files.
 ((eq "Browse" rpwhat)
 (if
 (not (setq files
 (dos_getfilem "Select files" *projpath*
 "Drawing files (*.dwg)|*.dwg||")))
 (exit)
 (progn
 (setq path (car files))
 (foreach fn (cdr files)
 (setq processpathlst (cons (strcat path fn) processpathlst))
 )
 )
 )
 )
 ;; Process the documents collection.
 ((eq "Opened" rpwhat)
 (vlax-for x documents
 (setq processpathlst (cons (vlax-get x 'FullName) processpathlst))
 )
 (setq processpathlst (reverse processpathlst))
 )
 ;; Process the active file.
 ((eq "Current" rpwhat)
 (setq processpathlst (list (vlax-get actdoc 'FullName)))
 )
 ) ;cond

(if
 (and
 (eq "Relative" fullrel)
 (or
 (eq "Opened" rpwhat)
 (eq "Current" rpwhat)
 )
 (not
 (vl-every
 '(lambda (x) (dos_ispathsameroot *projpath* x)) processpathlst
 )
 )
 )
 (progn
 (alert
 (strcat "The project folder and all open files must be\n"
 "on the same drive when using relative paths.\n"
 "Please try again. Exiting..."
 )
 )
 (exit)
 )
 )

(if
 (and
 (eq "Relative" fullrel)
 (eq "Browse" rpwhat)
 (not (dos_ispathsameroot *projpath* (car files)))
 )
 (progn
 (alert
 (strcat "The project folder and the selected files must\n"
 "be on the same drive when using relative paths.\n"
 "Please try again. Exiting..."
 )
 )
 (exit)
 )
 )

;; List of full paths.
 (setq filelst (dos_find (strcat *projpath* "*.dwg") 4))


;; Get the current file format.
 (setq curformat (RPX:CurrentFileFormat))

(foreach x processpathlst
 (if (setq targdoc (RPX:DocAtPath x))
 ;; List of lists: (xreffilename blockname existingpath blockobj)
 (setq datalst (RPX:XrefsData targdoc))
 (setq newerdoclst (cons x newerdoclst))
 )

;; Make a list of full paths which would change file format if saved.
 (if (not (vl-position targdoc docslst))
 (progn
 (setq version (dos_dwgver x))
 (if (not (eq "Unknown" version))
 (progn
 (setq version (atoi (substr version 9)))
 (if
 (and
 (< version curformat)
 (not (vl-position x formatlst))
 )
 (setq formatlst (cons x formatlst))
 )
 )
 )
 )
 )

(if
 (and
 targdoc
 (not (vlax-object-released-p targdoc))
 )
 (vlax-release-object targdoc)
 )

;; Datalst is a list of lists.
 ;; (xreffilename blockname existingpath blockobj)
 (foreach x datalst
 (setq temp nil
 fn (car x)
 temp (cons fn temp)
 )
 (foreach str filelst
 (if (eq (strcase fn) (strcase (strcat (vl-filename-base str) ".dwg")))
 (setq temp (cons str temp))
 )
 )
 (setq temp (reverse temp))
 (if (not (vl-position temp masterlst))
 (setq masterlst (cons temp masterlst))
 )
 )
 ) ;foreach path in processpathlst

;; Each item in masterlst is (xreffilename path [path]). It's a list of
 ;; lists containing all non-nested xrefs in all selected files.

;; List xrefs which have multiple paths.
 (foreach x masterlst
 (if (< 1 (length (cdr x)))
 (setq multiplelst (cons x multiplelst))
 )
 )

;; Each list in multiplelst is like this (xreffilename path [path]).
 (if multiplelst
 (progn
 ;; Temp turn off the wait cursor.
 (dos_waitcursor)
 (textscr)

(princ "\nDuplicate xrefs found sorted by latest date first. ")

(foreach x multiplelst
 (princ "\n\n -------------- ")
 (princ (strcat "\n " (car x)))
 (foreach p (cdr x)
 (princ (strcat "\n\n" p "\n"))
 ; 2008/02/08 23:34:18
 (princ (strcat " " (RPX:GetDate p)))
 )
 (princ "\n -------------- ")
 )

;; Ask the question.
 (initget "Yes No")
 (setq multans (getkword "\n\nRepath using the latest date file? [Yes/No] : "))
 (if (not multans) (setq multans "Yes"))

;; Turn the wait cursor back on.
 (dos_waitcursor T)
 )
 )

(if formatlst
 (progn
 ;; Temp turn off the wait cursor.
 (dos_waitcursor)
 (textscr)

(princ "\nSome selected files will change file format. \n")

(foreach x formatlst
 (princ (strcat "\n " x))
 )

(princ "\n")

;; Ask the question.
 (initget "Yes No")
 (setq formatans (getkword "\nAllow files to change format? [Yes/No] : "))
 (if (not formatans) (setq formatans "Yes"))

;; Turn the wait cursor back on.
 (dos_waitcursor T)
 )
 )

(if (eq formatans "No")
 (foreach x formatlst
 (setq processpathlst (vl-remove x processpathlst))
 )
 )

(setq nestcnt 0)

;; Confirm proceed.
 ;; Temp turn off the wait cursor.
 (dos_waitcursor)

(cond
 ((eq "Current" rpwhat)
 (setq msg
 (dos_msgbox "Proceed with repathing the current file?"
 "Confirm" 2 4
 )
 )
 )
 ((eq "Opened" rpwhat)
 (setq msg
 (dos_msgbox "Proceed with repathing opened files?"
 "Confirm" 2 4
 )
 )
 )
 ((eq "Browse" rpwhat)
 (setq lenlst (length processpathlst))
 (cond
 ((= 1 lenlst)
 (setq msg
 (dos_msgbox
 (strcat "Proceed with repathing " (itoa lenlst) " file?")
 "Confirm" 2 4
 )
 )
 )
 ((< 1 lenlst)
 (setq msg
 (dos_msgbox
 (strcat "Proceed with repathing " (itoa lenlst) " files?")
 "Confirm" 2 4
 )
 )
 )
 ((= 0 lenlst)
 (setq msg
 (dos_msgbox
 "No files found which need repathing."
 "Confirm" 2 4
 )
 )
 )
 ) ; end cond
 )
 ) ; end cond

;; With options in-hand, step through the files again and repath.

(if (= 4 msg)
 (progn
 (dos_waitcursor T)
 (setq temp nil)

(foreach x processpathlst
 (setq targdoc nil)
 (if (setq targdoc (RPX:DocAtPath x))
 ;; List of lists: (xreffilename blockname existingpath blockobj)
 (setq datalst (RPX:XrefsData targdoc)
 pathlst nil
 )
 )

;; datalst is a list of lists
 ;; (xreffilename blockname existingpath blockobj)
 (foreach x datalst
 (setq temp nil
 fn (car x)
 blkname (cadr x)
 expath (caddr x)
 blkobj (last x)
 temp (cons (list fn blkname expath blkobj) temp)
 )

;;;; AVOID scanning the project folder twice.
 ;; Do speed test compared to beta 1.15.
 (foreach i masterlst
 (if (eq fn (car i))
 (setq paths (cdr i))
 )
 )

;; Finally seems right.
 (setq pathlst (cons (append temp paths) pathlst))

)

(setq oklst nil multiplelst nil)

;; Each list in pathlst is like this
 (foreach x pathlst
 (cond
 ((= 1 (length (cdr x)))
 (setq oklst (cons x oklst))
 )
 ((= 0 (length (cdr x)))
 (setq temp (caar x))
 (if (not (vl-position temp notfoundlst))
 (setq notfoundlst (cons temp notfoundlst))
 )
 )
 ((< 1 (length (cdr x)))
 (setq multiplelst (cons x multiplelst))
 )
 )
 )

(if (eq multans "Yes") (setq oklst (append multiplelst oklst)))

(if (and targdoc oklst)
 (if (setq temp (RPX:Repath targdoc oklst))
 (setq returnlst (cons temp returnlst))
 )
 )

;; Save ODBX documents.
 (if
 (and
 targdoc
 (not (vl-position targdoc docslst))
 )
 (vl-catch-all-apply 'vla-SaveAs (list targdoc x))
 )

(if
 (and
 targdoc
 (not (vlax-object-released-p targdoc))
 )
 (vlax-release-object targdoc)
 )

) ;end foreach file selected


(textscr)

;; typical return list


(foreach x (reverse returnlst)
 ;; print file name
 (princ (strcat "\n\n" (car x)))
 ;; xref name and new path
 (foreach xr (last x)
 (princ (strcat "\n Xref: " (car xr) " repathed: \n"))
 (princ (strcat " " (cadr xr)))
 )
 )

(if notfoundlst
 (progn
 (princ "\n\nXrefs not found in project folder: ")
 (foreach x notfoundlst
 (princ (strcat "\n " x))
 )
 )
 )

;; Number of nested xrefs if any.
 ;; Only reported with the Current option.
 (if (eq "Current" rpwhat)
 (if (not (zerop nestcnt))
 (princ (strcat "\n\nNumber of nested xrefs found: " (itoa nestcnt)))
 )
 )

(princ (strcat "\n\nTotal number of xrefs repathed: " (itoa cnt) "\n"))

(if newerdoclst
 (progn
 (princ
 (strcat "\nThe following files were not repathed. "
 "\n The file format is later than the version in use "
 "or the file is read-only. \n"
 )
 )
 (foreach x newerdoclst
 (princ (strcat "\n " x))
 )
 )
 )

) ;progn
 ) ;if msg = 4

(dos_waitcursor)

(*error* nil)

) ;end RepathXrefs

;-------------------------------
 ;shortcut
 ;(defun c:FRX () (c:RepathXrefs))
 ;-------------------------------

;|
 (defun c:LoadedXrefs2 ( / blocks name)
 (setq blocks
 (vla-get-blocks
 (vla-get-activedocument
 (vlax-get-acad-object))))
 (vlax-for x blocks
 (setq name (vlax-get x 'Name))
 (if (= -1 (vlax-get x 'IsXref))
 (cond
 ((not
 (vl-catch-all-error-p
 (vl-catch-all-apply
 'vlax-get
 (list x 'XrefDatabase)
 )
 )
 )
 (princ (strcat "\n" name " is loaded. "))
 )
 (T (princ (strcat "\n" name " is not loaded. ")))
 )
 )
 )
 (princ)
 )
 (c:FRX)




Thanks for any help!
Civil3D 2020

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18

MSTG007

  • Gator
  • Posts: 2598
  • I can't remeber what I already asked! I need help!
Re: Change All Xrefs Path type - Found
« Reply #2 on: June 30, 2016, 07:22:47 AM »
Thanks for finding that.

Also wanted to share that I needed to have the following to get the routine to execute for 2016.

http://wiki.mcneel.com/doslib/home
Civil3D 2020

ChrisCarlson

  • Guest
Re: Change All Xrefs Path type - Found
« Reply #3 on: June 30, 2016, 08:03:51 AM »
Give this page a once over, malformed list is a common issue when you have a mis-matched parenthesis.

http://www.lee-mac.com/errormessages.html

MSTG007

  • Gator
  • Posts: 2598
  • I can't remeber what I already asked! I need help!
Re: Change All Xrefs Path type - Found
« Reply #4 on: June 30, 2016, 08:05:40 AM »
hum.... I can see how copy and paste can make it or break it now. Thanks for sharing that.
Civil3D 2020