dingleboy Posted September 20, 2012 Posted September 20, 2012 Hi guys, Long time reader, seldom if ever poster. I think I've got a good one this time and can't find a solution. I'm seeking to find and replace strings in hundreds of xref paths. It's not the path I need to change, but a string in the name of the drawing. For example: "otl" should be found and replaced with "int" *\PLANS\p_otl_001.dwg -> *\PLANS\p_int_001.dwg *\PLANS\p_otl_002.dwg -> *\PLANS\p_int_002.dwg I can quickly change the reference name using RENAME and the Reference Manager can change all paths, but affects only the file path and not the name of the drawing. REDIR with * wildcards doesn't work either. I've searched for hours for a script that will achieve this but I cannot seem to find one. Has anyone found a solution to this before? (I'll buy you many beers first chance I get.) Using AutoCAD Architecture 2012. Quote
Lee Mac Posted September 20, 2012 Posted September 20, 2012 Here is a very simple find & replace drawing file renamer, use at your own risk: ([color=BLUE]defun[/color] c:fixdwg ( [color=BLUE]/[/color] dir new old ) ([color=BLUE]if[/color] ([color=BLUE]and[/color] ([color=BLUE]setq[/color] old ([color=BLUE]getstring[/color] [color=BLUE]t[/color] [color=MAROON]"\nSpecify string to find: "[/color])) ([color=BLUE]setq[/color] new ([color=BLUE]getstring[/color] [color=BLUE]t[/color] [color=MAROON]"\nSpecify string to replace: "[/color])) ([color=BLUE]setq[/color] dir (LM:BrowseForFolder [color=MAROON]"Select directory of drawings to rename"[/color] [color=BLUE]nil[/color] 0)) ) ([color=BLUE]foreach[/color] dwg ([color=BLUE]vl-directory-files[/color] dir [color=MAROON]"*.dwg"[/color] 1) ([color=BLUE]if[/color] ([color=BLUE]vl-string-search[/color] old ([color=BLUE]vl-filename-base[/color] dwg)) ([color=BLUE]vl-file-rename[/color] ([color=BLUE]strcat[/color] dir [color=MAROON]"\\"[/color] dwg) ([color=BLUE]strcat[/color] dir [color=MAROON]"\\"[/color] ([color=BLUE]vl-string-subst[/color] new old ([color=BLUE]vl-filename-base[/color] dwg)) [color=MAROON]".dwg"[/color]) ) ) ) ) ([color=BLUE]princ[/color]) ) [color=GREEN];;------------------=={ Browse for Folder }==-----------------;;[/color] [color=GREEN];; ;;[/color] [color=GREEN];; Displays a dialog prompting the user to select a folder. ;;[/color] [color=GREEN];;------------------------------------------------------------;;[/color] [color=GREEN];; Author: Lee Mac, Copyright © 2012 - www.lee-mac.com ;;[/color] [color=GREEN];;------------------------------------------------------------;;[/color] [color=GREEN];; Arguments: ;;[/color] [color=GREEN];; msg - message to display at top of dialog ;;[/color] [color=GREEN];; dir - root directory (or nil) ;;[/color] [color=GREEN];; flg - bit coded flag specifying dialog display settings ;;[/color] [color=GREEN];;------------------------------------------------------------;;[/color] [color=GREEN];; Returns: Selected folder filepath, else nil ;;[/color] [color=GREEN];;------------------------------------------------------------;;[/color] ([color=BLUE]defun[/color] LM:BrowseForFolder ( msg dir flg [color=BLUE]/[/color] err shell fold self path ) ([color=BLUE]setq[/color] err ([color=BLUE]vl-catch-all-apply[/color] ([color=BLUE]function[/color] ([color=BLUE]lambda[/color] ( [color=BLUE]/[/color] acapp hwnd ) ([color=BLUE]if[/color] ([color=BLUE]setq[/color] acapp ([color=BLUE]vlax-get-acad-object[/color]) shell ([color=BLUE]vla-getinterfaceobject[/color] acapp [color=MAROON]"shell.application"[/color]) hwnd ([color=BLUE]vl-catch-all-apply[/color] '[color=BLUE]vla-get-hwnd[/color] ([color=BLUE]list[/color] acapp)) fold ([color=BLUE]vlax-invoke-method[/color] shell 'browseforfolder ([color=BLUE]if[/color] ([color=BLUE]vl-catch-all-error-p[/color] hwnd) 0 hwnd) msg flg dir) ) ([color=BLUE]setq[/color] self ([color=BLUE]vlax-get-property[/color] fold 'self) path ([color=BLUE]vlax-get-property[/color] self 'path) path ([color=BLUE]vl-string-right-trim[/color] [color=MAROON]"\\"[/color] ([color=BLUE]vl-string-translate[/color] [color=MAROON]"/"[/color] [color=MAROON]"\\"[/color] path)) ) ) ) ) ) ) ([color=BLUE]if[/color] self ([color=BLUE]vlax-release-object[/color] self)) ([color=BLUE]if[/color] fold ([color=BLUE]vlax-release-object[/color] fold)) ([color=BLUE]if[/color] shell ([color=BLUE]vlax-release-object[/color] shell)) ([color=BLUE]if[/color] ([color=BLUE]vl-catch-all-error-p[/color] err) ([color=BLUE]prompt[/color] ([color=BLUE]vl-catch-all-error-message[/color] err)) path ) ) ([color=BLUE]vl-load-com[/color]) ([color=BLUE]princ[/color]) For your given example, type "otl" for the 'find' string and "int" as the 'replace' string. Quote
dingleboy Posted September 20, 2012 Author Posted September 20, 2012 Lee Mac, thanks very much for the code and monster fast reply. However, this changes the names of the drawing files, but I'm wondering if I can change the names of the saved paths in the current drawing. I should also probably mention that I'm experienced with RhinoScript and some .NET for Grasshopper, but haven't yet made the jump to .NET for AutoCAD. That's next on the list. Count me in as a fan of very simple, and thanks again for looking... Quote
Lee Mac Posted September 20, 2012 Posted September 20, 2012 Lee Mac, thanks very much for the code and monster fast reply. However, this changes the names of the drawing files, but I'm wondering if I can change the names of the saved paths in the current drawing. I guess I have misunderstood your requirements; when you stated in your first post: "It's not the path I need to change, but a string in the name of the drawing.", I took this to mean that you didn't wish to change the XRef Path property, but rather change the physical filename of the drawing file referenced by the XRef. Try this instead: (defun c:fixpath ( / new old pth ) (setq old "otl" ;; string to find new "int" ;; string to replace ) (vlax-for blk (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (if (and (= :vlax-true (vla-get-isxref blk)) (vl-string-search old (vl-filename-base (setq pth (vla-get-path blk)))) ) (vla-put-path blk (strcat (vl-filename-directory pth) "\\" (vl-string-subst new old (vl-filename-base pth)) ".dwg" ) ) ) ) (princ) ) (vl-load-com) (princ) Note that the drawing will need to be closed and re-opened for the changes in the XRef Block Definition to be reflected across the references of the XRef in the drawing. As I can't warrant spending too much time on this, the above code is extremely simplistic, with the find/replace strings hard-coded and case-sensitive. The find/replace operation will also only replace the first occurrence of the find string in the XRef source drawing filename. Quote
dingleboy Posted September 20, 2012 Author Posted September 20, 2012 I guess I have misunderstood your requirements; when you stated in your first post: "It's not the path I need to change, but a string in the name of the drawing.", I took this to mean that you didn't wish to change the XRef Path property, but rather change the physical filename of the drawing file referenced by the XRef. It's true, I suppose that sentence was a bit ambiguous. Regardless, major thanks to you for spending the time to look at this. Also thanks for explaining the caveats. This is massively helpful to me and I'm sure it will be to others too. I've spliced in the user input portion of your first post - success. Could also edit out the pth portion but no matter: (defun c:fixpath ( / new old pth ) (setq old (getstring t "\nSpecify string to find: ")) (setq new (getstring t "\nSpecify string to replace: ")) (vlax-for blk (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (if (and (= :vlax-true (vla-get-isxref blk)) (vl-string-search old (vl-filename-base (setq pth (vla-get-path blk)))) ) (vla-put-path blk (strcat (vl-filename-directory pth) "\\" (vl-string-subst new old (vl-filename-base pth)) ".dwg" ) ) ) ) (princ) ) (vl-load-com) (princ) Thank you again. So helpful. Quote
Lee Mac Posted September 20, 2012 Posted September 20, 2012 Regardless, major thanks to you for spending the time to look at this. Also thanks for explaining the caveats. This is massively helpful to me and I'm sure it will be to others too. You're very welcome, and thank you for your politeness & gratitude. It was only hastily written code, but I'm glad it will save you some time. I've spliced in the user input portion of your first post - success. Good stuff Could also edit out the pth portion but no matter. I'm not sure what you mean by this though? Quote
dingleboy Posted September 21, 2012 Author Posted September 21, 2012 You're very welcome, and thank you for your politeness & gratitude. It was only hastily written code, but I'm glad it will save you some time. Good stuff I'm not sure what you mean by this though? Ah, I just misread the code and thought the pth parameter was referring to nothing. My mistake. I've since found that I'd like to find and replace in the xref path, then rename the reference name to the newly established path (so I don't have to mess around with the RENAME command), then reload all references to show the results. I have VERY ungracefully smashed together three separate chunks of code in order to do this, and success - at least in my specific case. No error catching and some potentially flawed logic, but here it is: (defun c:fixpath4 ( / new old pth ) (setq old (getstring t "\nSpecify string to find: ")) (setq new (getstring t "\nSpecify string to replace: ")) (vlax-for blk (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (if (and (= :vlax-true (vla-get-isxref blk)) (vl-string-search old (vl-filename-base (setq pth (vla-get-path blk)))) ) (vla-put-path blk (strcat (vl-filename-directory pth) "\\" (vl-string-subst new old (vl-filename-base pth)) ".dwg" ) ) ) ) (vlax-for bo (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))) (if (= (vla-get-IsXref bo) :vlax-true) (progn (setq name (vla-get-Path bo)) (while (wcmatch name "*\\*") (setq name (substr name (+ (vl-string-search "\\" name) 2))) ) (while (wcmatch name "*.[dD][wW][gG]") (setq name (substr name 1 (- (strlen name) 4))) ) (vl-catch-all-apply 'vla-put-Name (list bo name)) ) ) ) (setvar "modemacro" "Reloading loaded xrefs......please wait......") (setvar "cmdecho" 0) (setq cObj(tblnext "BLOCK" T)) (while cObj (setq cName(cdr(assoc 2 cObj))) (if (and (=(logand(cdr(assoc 70 cObj))32)32) (=(logand(cdr(assoc 70 cObj))4)4) ); end and (progn (vl-cmdf "_.xref" "_unload" cName) (vl-cmdf "_.xref" "_reload" cName) ); end progn ); wnd if (setq cObj(tblnext "BLOCK")) ); end while (setvar "modemacro" ".") (setvar "cmdecho" 1) (prompt "\n--- Xref change finished! ---") (princ) ) (vl-load-com) (princ) Borrowed from this thread: http://www.cadtutor.net/forum/showthread.php?62998-Changing-quot-Reference-Name-quot-to-match-xref-file-name& After spending 6-8 hours of my late night studying code snippets and generous advice, I have to say that this lisp language is refreshingly succinct. It's a pity I'm having trouble finding documentation for it - and The Swamp isn't accepting new members! Quote
Lee Mac Posted September 21, 2012 Posted September 21, 2012 Ah, I just misread the code and thought the pth parameter was referring to nothing. My mistake. No problem I've since found that I'd like to find and replace in the xref path, then rename the reference name to the newly established path (so I don't have to mess around with the RENAME command), then reload all references to show the results. I have VERY ungracefully smashed together three separate chunks of code in order to do this, and success - at least in my specific case. No error catching and some potentially flawed logic, but here it is: Since my code is already iterating over the XRefs within the Block Collection, that could be condensed to: (defun c:fixpath5 ( / new nme old pth ) (if (and (/= "" (setq old (getstring t "\nSpecify string to find: "))) (/= "" (setq new (getstring t "\nSpecify string to replace: "))) ) (vlax-for blk (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (if (and (= :vlax-true (vla-get-isxref blk)) (vl-string-search old (vl-filename-base (setq pth (vla-get-path blk)))) ) (progn (setq nme (vl-string-subst new old (vl-filename-base pth))) (vla-put-path blk (strcat (vl-filename-directory pth) "\\" nme ".dwg")) (vla-put-name blk nme) (vla-reload blk) ) ) ) ) (princ) ) (vl-load-com) (princ) Quote
dingleboy Posted September 25, 2012 Author Posted September 25, 2012 Huge help, Lee Mac. Thank you again. Quote
MarkytheSparky Posted May 15, 2018 Posted May 15, 2018 (edited) I have a drawing with about 30 cells from an excel spreadsheet DATALINK ed. Everyone once in a while I will make changes to the excel file and save it as a new revision... ..\Electrical Data v8.4.xlsx ..\Electrical Data v8.5.xlsx I then go to the xref manager and select the Saved Path of one of the data links and change the name of the saved path file. Select all, copy, go to the next datalink, select all, paste... In my drawing, the names of the data links and the cell ranges do not change, but the file they reference does. I welcome any feedback or code help. Thanks in advance. As a follow up: I did find out that Datalink information is stored in the drawings's dictionary file but shows up an xref (defun c:ListDictionaries ( / ed ed1) (prompt "\nDictionaries in current drawing: ") (foreach ed (entget (namedobjdict)) (progn (cond ((= (car ed) 3) (prompt (strcat "\n" (cdr ed)))) ((= (car ed) 350) (progn (foreach ed1 (entget (cdr ed)) (if (= (car ed1) 3) (prompt (strcat "\n " (cdr ed1))) ) ) )) ) ) ) (princ) ) Edited May 15, 2018 by MarkytheSparky I was able to dig a little deeper and get some structure code Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.