Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to speed up this Autolisp?

15 REPLIES 15
SOLVED
Reply
Message 1 of 16
Pablo_1985
2153 Views, 15 Replies

How to speed up this Autolisp?

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 🙂

 

15 REPLIES 15
Message 2 of 16
hmsilva
in reply to: Pablo_1985

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

 

 

EESignature

Message 3 of 16
Pablo_1985
in reply to: hmsilva

Thanks Henrique I´m sending there!
Message 4 of 16
hmsilva
in reply to: Pablo_1985

You're welcome, Pablo_1985

Henrique

EESignature

Message 5 of 16
hmsilva
in reply to: Pablo_1985

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

EESignature

Message 6 of 16
doni49
in reply to: hmsilva

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.

 

http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/using-vl-string-subst-to-do-a-find-an...



Don Ireland
Engineering Design Technician




If a reply solves your issue, please remember to click on "Accept as Solution". This will help other users looking to solve a similar issue. Thank you.


Please do not send a PM asking for assistance. That's what the forums are for. This allows everyone to benefit from the question asked and the answers given.

Message 7 of 16
Pablo_1985
in reply to: doni49

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

 

 

Message 8 of 16
hmsilva
in reply to: Pablo_1985

Hi Pablo_1985,

 

one more question, do you want to replace the TEXT/MTEXT in whole dwg, or just the current space?

 

Henrique

EESignature

Message 9 of 16
Pablo_1985
in reply to: hmsilva

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

Message 10 of 16
hmsilva
in reply to: Pablo_1985

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

EESignature

Message 11 of 16
Pablo_1985
in reply to: hmsilva

Now it´s completely instantaneous!! Thank you very much!!

 

 

Message 12 of 16
hmsilva
in reply to: Pablo_1985

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

EESignature

Message 13 of 16
doni49
in reply to: Pablo_1985


@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




If a reply solves your issue, please remember to click on "Accept as Solution". This will help other users looking to solve a similar issue. Thank you.


Please do not send a PM asking for assistance. That's what the forums are for. This allows everyone to benefit from the question asked and the answers given.

Message 14 of 16
hmsilva
in reply to: doni49


@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

EESignature

Message 15 of 16
Pablo_1985
in reply to: hmsilva

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

Message 16 of 16
Pablo_1985
in reply to: Pablo_1985

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

 

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost