Hi to all!
It´s my first time writting here but I´ve been reading you guys for some time :). I´m an Excel-VBA user, trying to control Autocad (2015) from "here"... bear in mind that my knowledge about autocad is quite limited.
I have an VBA aplication that opens Autocad, load a file replace some text in the autocad as per a table in an excel sheet then save it with another name and close it.
For replacing the text I´m using an AutoLisp code taken from here:
http://www.cadtutor.net/forum/showthread.php?14084-Find-amp-Replace-Text/page2
So basically in my VBA code I send the commands though the comand line to run the AutoLisp script. I see the speed at which it changes the text and it´s very slow, like 10 seconds for changing 5 texts, so when I have to open hundred of drawings with several changes in each drawing it can take several hours.
I tried to put the commands directly in the command line to see if the slow part is taking the data from excel and then sending it to Autocad, or just the script, putting this in the command line the following and running the script directly:
(FindReplaceAll "1" "a")
(FindReplaceAll "2" "b")
(FindReplaceAll "3" "c")
(FindReplaceAll "4" "d")
(FindReplaceAll "5" "e")
(FindReplaceAll "6" "f")
(FindReplaceAll "7" "g")
(FindReplaceAll "8" "h")
(FindReplaceAll "9" "i")
But by doing this I see that the script is still very slow (ten seconds) so it is somehow something related with Autolisp, the command line and Autocad. I thought about trying to run directly the script through VBA skipping the command line part, or rewritting some code in VBA for not depending of autoLisp, but I don´t know how could I do this and if at the end that would solve the problem.
Anyone can do the test by running that Autolisp, in a test drawing with numbers from 1 to 9.
Any comment is welcome!
Thanks in advance 🙂
Solved! Go to Solution.
Solved by hmsilva. Go to Solution.
Hi Pablo_1985,
should be easier to get help on your code at,
for the VBA try the Visual Basic Customization forum
and for the AutoLISP try the Visual LISP, AutoLISP and General Customization forum
HTH
Henrique
Hi Pablo_1985,
as this thread as has been moved from the 'AutoCAD 2013/2014/2015' to the 'Visual LISP, AutoLISP and General Customization' forum, let's see if I can help you.
The code you are using, was written to replace text in TEXT, MTEXT, DIMENSIONS and ATTRIBUTES.
Is your goal to replace text in all these types of entities?
If not, will not be necessary to select entities that will not be modified.
Henrique
Pablo,
In addition to deciding if you want to perform this operation on all these types, I see an issue with the loop within the FindAndReplace function.
It performs a loop checking each character individually. That means that it's looping through EVERY SINGLE CHARACTER in EVERY SINGLE TEXT/MTEXT/ATTRIBUTE in the file.
Instead of using the FindAndReplace function that you've currently got defined, have a look at the replace function in the following link. I think this should speed things up considerably even before limiting the TYPES of objects you perform this on.
Don Ireland
Engineering Design Technician
I basically have to search in Mtext and sometimes in Text, nothing else...
Ok forget my lack of knowledge of autolisp, I guess you reffer to the code Marc´ Antonio posted:
; Marc'Antonio Alessi - http://alessi.xoom.it//alessi/ ; Function: ALE_StringSubstAll ; ; Version 1.01 - 21/01/2004 ; ; Description: ; Multiple substitution of a pattern string ; ; Arguments: ; NewStr: the string to be substituted for pattern ; PatStr: a string containing the pattern to be replaced ; InpStr: the string to be searched for pattern ; SttPos: 0, nil or an integer identifying the starting position of the search ; ; Return Values: the value of string after any substitutions have been made ; ; Example: ; (ALE_StringSubstAll "new" "old" "old test for old method" nil) ; ; Notes: ; the search is case-sensitive ; SttPos = 0 or nil > substitution start from first character ; NewStr = "" remove all instances of PatStr from SttPos ; ; Suggestions: ; use (vl-string-translate "\t" " " "Hi\tthis\tis\ta\ttest!") ; for single (or set) character substitution (not to remove) ; (N.B. the inversion of arguments) ; (defun ALE_StringSubstAll (NewStr PatStr InpStr SttPos / NewLen) (cond ( (= "" PatStr) InpStr ) ( (setq NewLen (strlen NewStr)) (while (setq SttPos (vl-string-search PatStr InpStr SttPos)) (setq InpStr (vl-string-subst NewStr PatStr InpStr SttPos) SttPos (+ SttPos NewLen) ) ) InpStr ) ) )
I´m trying this but it does not change the text, but the console returns the string with the changed text. also for my example I understand that PatStr and InpStr are the same.
I´m trying to read and understand this code but it feels very hard to read (for me as a complete newbie in AutoLisp):
;Function definition, with “Newlen” as a return (defun StringSubstAll (NewStr PatStr InpStr SttPos / NewLen) ;If “something” I don´t understand, then put in Newlen the the string length of NewStr (cond ( (= "" PatStr) InpStr ) ( (setq NewLen (strlen NewStr)) ;if not, then store in SttPos the string position of the searched string inside the string pattern, if not found then returns 0 and you exit the while (while (setq SttPos (vl-string-search PatStr InpStr SttPos)) ;If you find it once you store the position inside the string then replace it and increase Sttpos Newlen. (setq InpStr (vl-string-subst NewStr PatStr InpStr SttPos) SttPos (+ SttPos NewLen) ) ) InpStr ) ) )
Would you help me to understand what is happening? why it´snt working?
Regards,
Pablo
Hi Pablo_1985,
one more question, do you want to replace the TEXT/MTEXT in whole dwg, or just the current space?
Henrique
Hi Henrique,
In my case I think it is the same thing, because I open a dwg which is a template, then by replacing some text in the dwg according to an excel I create my drawing, save it with a different name and close it, then I move to the next drawing... I do this loop until I create all my drawing collection. And I should do this in this ways because the texts in the templates are an alfanumeric code that is common to all the templates, so opening and replacing each template one by one is mandatory.
I hope I replied to your question.
Thank you very much,
Pablo
Pablo,
a quick one:
(vl-load-com) (defun subst-txt (old new /) (if (setq ss (ssget "_X" '((0 . "TEXT,MTEXT")))) (repeat (setq i (sslength ss)) (setq ent (ssname ss (setq i (1- i))) obj (vlax-ename->vla-object ent) str (vlax-get-property obj 'TextString) ) (if (vl-string-search old str) (progn (while (vl-string-search old str) (setq str (vl-string-subst new old str)) ) (if (vlax-write-enabled-p obj) (vla-put-TextString obj str) ) ) ) ) ) (princ) ) ;; usaje ;; (subst-txt "oldtextstring" "newtextstring")
Hope that helps
Henrique
You're welcome, Pablo
Glad I could help
EDIT: too quick, change
(defun subst-txt (old new /) ;; to (defun subst-txt (old new / ent i obj ss str)
Henrique
@Pablo_1985 wrote:
Now it´s completely instantaneous!! Thank you very much!!
Beleive it or not, you could still speed it up even more. As of right now, the routine will process all text/mtext in the file -- it just won't change the objects that don't meet the requirements.
Assuming for a minute that the variable old contains the string that you're looking to replace, the following will select ONLY text/mtext that contains at least one instance of the desired string. Thus limiting the routine to running on objects known to contain the search string. The fewer objects it needs to process, the less time it'll take to run.
Obviously if it's running "instantaneously" as you say, then I wouldn't worry about changing it. But it's still always useful to think of ways to improve things (IMHO).
(setq ss(ssget "_x" (list (cons 0 "TEXT,MTEXT")(cons 1 (strcat "*" old "*")))))
Don Ireland
Engineering Design Technician
@doni49 wrote:
Beleive it or not, you could still speed it up even more. As of right now, the routine will process all text/mtext in the file -- it just won't change the objects that don't meet the requirements.
Obviously if it's running "instantaneously" as you say, then I wouldn't worry about changing it. But it's still always useful to think of ways to improve things (IMHO).
(setq ss(ssget "_x" (list (cons 0 "TEXT,MTEXT")(cons 1 (strcat "*" old "*")))))
Well thought, Don.
Henrique
Thanks Don! to be fair I wouldn´t know which part should I change. I´m still struggling to understand this coding and since I´m mostlIy focused in VBA I didn´t have time to study it, YET. I tried to change 9 different values in 1300 different texts and it takes 1 second... So... hehehe, if you tell me where to put it i can tell you how much it improves ;).
Right now my VBA code creates the .lsp file put it inside autocad´s file "Template" load it, use it and once it´s done delete it, so it is extremely easy to changes the autolisp code (if you know what and where to change).
Best regards,
Pablo
EDIT: Wording
Ok I did it! and... I cannot feel any difference, so i run both codes 3 times, the code does the following:
My sub does:
add vba references
create lsp file and move it to autocad files
open autocad
open document
go to modelspace
load lsp
loop for replacing Mtext and text (1296 Mtext to be changed)
Old text ->New text: 1-> x, 2-> a, 3-> b, 4-> c, 5, d-> 6-> e, 7-> f, 8-> g, 9-> -_´´ç+``¨Ç*^[]}{¿?'¡!|ª
save dwg as
close document
close autocad
delete lsp file
Henrique´s solution: 7.32s, 6.98s, 6.66s ->average: 6.98s
Don´s solution: 7.88s, 7.15s, 7.52s ->average:7.51s
So Henrique´s solution is the winner being half second faster!
Thanks for all!
Pablo