LISP TO FIND DUPLICATE IN SELECTED TEXT & MTEXT.

LISP TO FIND DUPLICATE IN SELECTED TEXT & MTEXT.

arpansark0544TCX
Advocate Advocate
805 Views
9 Replies
Message 1 of 10

LISP TO FIND DUPLICATE IN SELECTED TEXT & MTEXT.

arpansark0544TCX
Advocate
Advocate

Dear All,

I am sharing a working code of the above subject. Hope it will be use full to you all.

 

(defun strip-formatting (s)
  ;; Strip out formatting control characters (e.g., special symbols in MTEXT)
  (vl-remove-if '(lambda (x) (or (< x 32) (> x 126))) (vl-string->list s))
)

(defun clean-text (s)
  ;; Clean up the text by trimming spaces, converting to lowercase, and removing special formatting characters
  (setq s (vl-list->string (strip-formatting s))) ;; Remove non-printable characters
  (vl-string-right-trim " \t\r\n" (vl-string-left-trim " \t\r\n" (strcase s))) ;; Trim spaces and convert to lowercase
)

(defun c:HighlightDuplicates ( / ss lst ent i txt objType colorOverride cleanedTxt textCount)
  ;; Prompt user to select TEXT and MTEXT objects
  (setq ss (ssget '((0 . "TEXT,MTEXT")))) ;; Select TEXT and MTEXT objects
 
  ;; Check if the user selected any objects
  (if ss
    (progn
      (setq lst '()) ;; Initialize an empty list to track unique text
      (setq textCount '()) ;; Create a list to count occurrences of each text

      ;; First pass: Count occurrences of each cleaned text
      (repeat (setq i (sslength ss))
        (setq ent (ssname ss (setq i (- i 1)))) ;; Get the entity name
        (setq objType (cdr (assoc 0 (entget ent)))) ;; Get the object type (TEXT or MTEXT)

        ;; Extract the text depending on the object type
        (setq txt (cdr (assoc 1 (entget ent)))) ;; Get the raw text for both TEXT and MTEXT
        (setq cleanedTxt (clean-text txt)) ;; Clean the text
       
        ;; Count occurrences
        (if (assoc cleanedTxt textCount)
          (setq textCount (subst (cons cleanedTxt (1+ (cdr (assoc cleanedTxt textCount))))
                                  (assoc cleanedTxt textCount) textCount))
          (setq textCount (cons (cons cleanedTxt 1) textCount))
        )
      )
     
      ;; Second pass: Highlight duplicates
      (foreach item textCount
        (if (> (cdr item) 1) ;; Only highlight if count is greater than 1
          (progn
            (setq colorOverride '(62 . 1)) ;; Set color override to red (1)
            ;; Loop through the selected entities again to apply color
            (repeat (setq i (sslength ss))
              (setq ent (ssname ss (setq i (- i 1)))) ;; Get the entity name
              (setq objType (cdr (assoc 0 (entget ent)))) ;; Get the object type (TEXT or MTEXT)

              ;; Extract the text
              (setq txt (cdr (assoc 1 (entget ent)))) ;; Get the raw text for both TEXT and MTEXT
              (setq cleanedTxt (clean-text txt)) ;; Clean the text

              ;; Check if the cleaned text matches the duplicate
              (if (equal cleanedTxt (car item))
                (progn
                  ;; Apply the color directly
                  (entmod (append (entget ent) (list colorOverride)))
                  ;; Update the entity
                  (entupd ent)
                )
              )
            )
          )
        )
      )

      (princ "\nDuplicate entities have been highlighted.")
    )
    (princ "\nNo TEXT or MTEXT selected.")
  )
  (princ)
)
0 Likes
Accepted solutions (1)
806 Views
9 Replies
Replies (9)
Message 2 of 10

john.uhden
Mentor
Mentor

@arpansark0544TCX ,

What's wrong with characters like (chr 176) or (chr 177)?

John F. Uhden

0 Likes
Message 3 of 10

arpansark0544TCX
Advocate
Advocate
i don,t know
0 Likes
Message 4 of 10

john.uhden
Mentor
Mentor

@arpansark0544TCX ,

Then why did you exclude them?

John F. Uhden

0 Likes
Message 5 of 10

john.uhden
Mentor
Mentor

@arpansark0544TCX ,

My previous response was improper.

Your code excludes any text with (chr #s) below 32 and above 126.

There are a bundle of characters in those ranges that we use quite often.

I was just rather curious as to why you would exclude those ranges.  I presume it was because someone told you to.

John F. Uhden

0 Likes
Message 6 of 10

arpansark0544TCX
Advocate
Advocate
Oh! As I had only simple test and m text so I used that.
0 Likes
Message 7 of 10

Sea-Haven
Mentor
Mentor
Message 8 of 10

arpansark0544TCX
Advocate
Advocate
If some one have a idea to improve it. Kindly mention it below. Let see if we can improve it.
0 Likes
Message 9 of 10

john.uhden
Mentor
Mentor
Accepted solution

@arpansark0544TCX ,

My apologies for not having asked...

Are you looking for duplicate phrases, or duplicate words, or just duplicate characters, or maybe just duplicate numbers?

BTW, when looking for text strings within mtext, dxf 1 returns the entire string only if the string length is  <= 250.  If longer then it is broken into dxf 3 codes with the last being dxf 1, so try this:

(defun getmtextstr (e / ent pieces str)
  (setq ent (entget e))
  (setq pieces (vl-remove-if-not '(lambda (x)(vl-position (car x)'(1 3))) ent))
  (setq str (apply 'strcat (mapcar 'cdr pieces)))
)

 But a better way might be to use @Kent1Cooper 's suggestion of getting the 'text property of the vla-object.  He taught us that the 'textstring property includes all the formatting codes but the 'text property excludes all those codes (if the release is 20## or newer). (At least I think that's how it works, but I'm sure that Kent will chime in if I am mistaken.)

John F. Uhden

Message 10 of 10

arpansark0544TCX
Advocate
Advocate

I am not looking for anything. The code was working good for me so I posted to help other cad users if they need it. If you have any thoughts of improving it any further please free to do so.

Thank you.

0 Likes