Jump to content

How to replace strings in blocks without replacing the entire string?


JimmyJohn

Recommended Posts

```c
(defun replaceall (old new / regex)
  ;; Create the regex object
  (setq regex (vlax-get-or-create-object "VBScript.RegExp"))
  (vlax-put-property regex 'global :vlax-true)
  (vlax-put-property regex 'ignorecase :vlax-true)
  (vlax-put-property regex 'multiline :vlax-true)
  ;; Set the pattern to match exact word
  (vlax-put-property regex 'pattern (strcat "\\b" old "\\b"))
 
  ;; Process every block
  (vlax-for n (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
    (vlax-for m n
      (if (member (vla-get-objectname m) '("AcDbMText" "AcDbText"))
        (progn
          (setq original-text (vla-get-textstring m))
          (setq new-text original-text)
          
          ;; Replace using regex only if there's a match
          (setq replaced-text (vlax-invoke regex 'replace original-text new))
          
          ;; Only update if there was a change
          (if (/= original-text replaced-text)
            (vla-put-textstring m replaced-text)
          )
        )
      )
    )
  )
  (princ "Replacement done.")
)
```


This AUTOLISP Routine does almost exactly what I want it to. It searches through blocks for exact string, and attempts to replace that exact string with an exact replacement. However I am running into the problem that no matter what I try, I cannot get the output to be what i want. For example, running this code with the inputs (replaceall "1" "vanilla pudding") attempts to replace all instances of "1" by itself in the blocks with "vanilla pudding." However if there is a string in the block "1 Sprinkles", Ideally if you use the input above the output would end up being "vanilla pudding sprinkles". I want this to be able to completely decode a block given predefined inputs. I am not understanding the resources online, and would like some assistance with understanding if possible!

Edited by SLW210
Added Code Tags!
Link to comment
Share on other sites

9 minutes ago, ronjonp said:

@JimmyJohn

 

Use VL-STRING-SUBST ( only replaces the first occurrence )
 

(vl-string-subst "vanilla pudding" "1" "1 Sprinkles")
;; "vanilla pudding Sprinkles" 

 

I'm sorry but where do I put this? When I tried to replace it with ```vla-put-text-string``` it gave me an error for too few arguments. I am sorry I am new to Autolisp and coding in general.

Link to comment
Share on other sites

 

;; Substitute text within blocks
(defun _foo (old new / a d txt)
  (vlax-for l (vla-get-layers (setq d (vla-get-activedocument (vlax-get-acad-object))))
    (cond ((= -1 (vlax-get l 'lock)) (vlax-put l 'lock 0) (setq a (cons l a))))
  )
  (vlax-for b (vla-get-blocks d)
    ;; This line will only process block definitions
    (if	(= 0 (vlax-get b 'isxref) (vlax-get b 'islayout))
      (vlax-for	o b
	(if (and (vlax-write-enabled-p o)
		 (wcmatch (strcase (vla-get-objectname o)) "*TEXT*")
		 (wcmatch (setq txt (vla-get-textstring o)) (strcat "*" old "*"))
	    )
	  (vla-put-textstring o (vl-string-subst new old txt))
	)
      )
    )
  )
  ;; Relock layers
  (foreach l a (vlax-put l 'lock -1))
  ;; Regen to see changes
  (vla-regen d 1)
  (princ)
)
;; Usage
(_foo "1" "vanilla pudding")

 

Edited by ronjonp
Link to comment
Share on other sites

21 minutes ago, ronjonp said:

 

;; Substitute text within blocks
(defun _foo (old new / a d txt)
  (vlax-for l (vla-get-layers (setq d (vla-get-activedocument (vlax-get-acad-object))))
    (cond ((= -1 (vlax-get l 'lock)) (vlax-put l 'lock 0) (setq a (cons l a))))
  )
  (vlax-for b (vla-get-blocks d)
    ;; This line will only process block definitions
    (if	(= 0 (vlax-get b 'isxref) (vlax-get b 'islayout))
      (vlax-for	o b
	(if (and (vlax-write-enabled-p o)
		 (wcmatch (strcase (vla-get-objectname o)) "*TEXT*")
		 (wcmatch (setq txt (vla-get-textstring o)) (strcat "*" old "*"))
	    )
	  (vla-put-textstring o (vl-string-subst new old txt))
	)
      )
    )
  )
  ;; Relock layers
  (foreach l a (vlax-put l 'lock -1))
  ;; Regen to see changes
  (vla-regen d 1)
  (princ)
)
;; Usage
(_foo "1" "vanilla pudding")

 

Yes this is great! And you are right I completely overlooked the fact it would change on sheets. That would have been embarrassing. There is one thing that happens, if there happens to be a 1 in the string elsewhere, it turns that into vanilla pudding. So if there is an 11 somewhere in the string it turns into "vanilla puddingvanillapudding". How would you go about making it so that if I input (_foo "1" "vanilla pudding") It will only change individual "1" 's in strings to vanilla pudding? Just to be as clear as possible, if the string in the block was 1 2 3 4 5, after I run this code with the input above I would like it to be vanilla pudding 2 3 4 5. Is that possible? What has to be changed or added? Thank you for your help so far!

Link to comment
Share on other sites

@JimmyJohn If the string is "11" the result would be "vanilla pudding1" What would this string look like "1 2 3 4 5 1" ? A stated above vl-string-subst only changes the first occurrence.
 

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...