Thousands Separator

Thousands Separator

ramimann
Contributor Contributor
1,511 Views
16 Replies
Message 1 of 17

Thousands Separator

ramimann
Contributor
Contributor

Hello

I'm looking for a lisp that adds a thousands separator for a selection set of text (not a single text)

Thanks

0 Likes
Accepted solutions (2)
1,512 Views
16 Replies
Replies (16)
Message 2 of 17

CADaSchtroumpf
Advisor
Advisor

Perhaps this?

 

(defun convert_str2mil (str2cnv flag / l_str n l_nw)
  (setq l_str (if flag (reverse (vl-string->list str2cnv)) (vl-string->list str2cnv)) n 1)
  (while l_str
    (if (zerop (rem n 3))
      (setq l_nw (cons 32 (cons (car l_str) l_nw)))
      (setq l_nw (cons (car l_str) l_nw))
    )
    (setq l_str (cdr l_str) n (1+ n))
  )
  (vl-list->string (if (not flag) (reverse l_nw) l_nw))
)
(defun c:TEST-CONV ( / ss n ent dxf_ent val_txt nb_dec)
  (setq ss
    (ssget
      (list
        (cons 0 "TEXT")
        (cons 67 (if (eq (getvar "CVPORT") 2) 0 1))
        (cons 410 (if (eq (getvar "CVPORT") 2) "Model" (getvar "CTAB")))
      )
    )
  )
  (cond
    (ss
      (repeat (setq n (sslength ss))
        (setq
          ent (ssname ss (setq n (1- n)))
          dxf_ent (entget ent)
          val_txt (cdr (assoc 1 dxf_ent))
        )
        (cond
          ((numberp (read val_txt))
            (if (eq (type (read val_txt)) 'INT)
              (setq val_txt (convert_str2mil val_txt T))
              (setq
                nb_dec (1- (- (strlen val_txt) (vl-string-position 46 val_txt)))
                val_txt (atof val_txt)
                val_txt
                (strcat
                  (convert_str2mil (rtos (setq mantisse (fix val_txt)) 2 0) T)
                  "."
                  (convert_str2mil (substr (rtos (setq p_decimal (- val_txt (fix val_txt))) 2 nb_dec) 3) nil)
                )
              )
            )
            (entmod (subst (cons 1 val_txt) (assoc 1 dxf_ent) dxf_ent))
          )
        )
      )
    )
  )
  (prin1)
)

 

0 Likes
Message 3 of 17

ramimann
Contributor
Contributor

Hello

Thanks, but it returns "bad argument type: numberp: nil

0 Likes
Message 4 of 17

ramimann
Contributor
Contributor

Maybe because my numbers are integers...Please make it accept all kind of numbers

0 Likes
Message 5 of 17

CADaSchtroumpf
Advisor
Advisor
Hello, I updated the previous code to correctly handle integers
0 Likes
Message 6 of 17

ramimann
Contributor
Contributor

It worked perfectly. Excuse my weak knowledge of Autolisp, I only can make some little editing in lisps...Thank you about helping me. Please tell me what can I edit in this lisp to make it add commas instead of spaces...

0 Likes
Message 7 of 17

Sea-Haven
Mentor
Mentor

I thought I posted something, you have posted on 3 forums. 

 

Anyway my suggestion.

 

A suggestion you can use (strlen str) which returns how many characters in a string so 2 tests is it greater than 6 1,000,000 and is it greater than 3 1,000. I doubt any where in the world is 9 characters.

The second is that if you have 1000.123 then strip the fraction from it using the FIX function and check strlen.

Using the strlen you can break the string into parts and add the "," (substr str (- lenstr 3)) then use strcat and join back together.

So when adding text to grid convert string first before labelling.

Have a go if get stuck ask again.

 

I do have add grids in a layout based on world co-ords, supports non rectangular viewports like a "L" etc. 

0 Likes
Message 8 of 17

CADaSchtroumpf
Advisor
Advisor
Accepted solution

Overwrite the function "conver_str2mil" by:

(defun convert_str2mil (str2cnv flag / l_str n l_nw)
  (setq l_str (if flag (reverse (vl-string->list str2cnv)) (vl-string->list str2cnv)) n 1)
  (while l_str
    (if (zerop (rem n 3))
      (setq l_nw (cons 44 (cons (car l_str) l_nw)))
      (setq l_nw (cons (car l_str) l_nw))
    )
    (setq l_str (cdr l_str) n (1+ n))
  )
  (vl-string-right-trim "," (vl-string-left-trim "," (vl-list->string (if (not flag) (reverse l_nw) l_nw))))
)
0 Likes
Message 9 of 17

john.uhden
Mentor
Mentor

@ramimann ,

Here's a function that might help you.

   ;;----------------------------------------------------
   ;; This function pads a numeric string with commas.
   ;; Revised to handle negative values (03-14-02)
   ;;
   ;; Re-written (11-20-04)
   (defun @rtoc (N Prec / Sign Str i j)
      (setq Prec (max 0 Prec)
            Sign (if (minusp N) "-" "")
            Str  (rtos (abs N) 2 Prec)
            i    (vl-string-search "." Str)
      )
      (if (not i)(setq i (strlen Str)))
      (setq j i)
      (if (zerop (setq i (rem i 3)))(setq i 3))
      (while (< i j)
         (setq Str (strcat (substr Str 1 i) "," (substr Str (1+ i)))
              i (+ i 4)
              j (1+ j)
         )
      )
      (strcat Sign Str)
   )

John F. Uhden

Message 10 of 17

ramimann
Contributor
Contributor

Thanks everyone

I'l give "them" a try

0 Likes
Message 11 of 17

ramimann
Contributor
Contributor

It worked 100%

Thanks

0 Likes
Message 12 of 17

ramimann
Contributor
Contributor

A last editing Please

It did not work with negative coordinates: It returned -,120,000...thus it put a comma after the minus sign.

0 Likes
Message 13 of 17

ramimann
Contributor
Contributor

Sorry

I don't know how to use such a lisp that is without "c:". I tried to put it into CADaSchtroumpf code, but...in vain.

0 Likes
Message 14 of 17

CADaSchtroumpf
Advisor
Advisor
Accepted solution

@ramimann  a écrit :

A last editing Please

It did not work with negative coordinates: It returned -,120,000...thus it put a comma after the minus sign.


@ramimann 

Here is my corrected version to take into account the sign (also takes into account the "+" sign if present)

(defun convert_str2mil (str2cnv flag / l_str mts sgn n l_nw)
  (setq
    l_str
    (if flag
      (progn
        (setq mts (vl-string->list str2cnv))
        (if (or (eq (car mts) 43) (eq (car mts) 45))
          (setq
            sgn (car mts)
            mts (vl-remove sgn mts)
          )
        )
        (reverse mts)
      )
      (vl-string->list str2cnv)
    )
    n 1
  )
  (while l_str
    (if (zerop (rem n 3))
      (setq l_nw (cons 44 (cons (car l_str) l_nw)))
      (setq l_nw (cons (car l_str) l_nw))
    )
    (setq l_str (cdr l_str) n (1+ n))
  )
  (strcat
    (if sgn (chr sgn) "")
    (vl-string-right-trim "," (vl-string-left-trim "," (vl-list->string (if (not flag) (reverse l_nw) l_nw))))
  )
)
(defun c:TEST-CONV ( / ss n ent dxf_ent val_txt nb_dec)
  (setq ss
    (ssget
      (list
        (cons 0 "TEXT")
        (cons 67 (if (eq (getvar "CVPORT") 2) 0 1))
        (cons 410 (if (eq (getvar "CVPORT") 2) "Model" (getvar "CTAB")))
      )
    )
  )
  (cond
    (ss
      (repeat (setq n (sslength ss))
        (setq
          ent (ssname ss (setq n (1- n)))
          dxf_ent (entget ent)
          val_txt (cdr (assoc 1 dxf_ent))
        )
        (cond
          ((numberp (read val_txt))
            (if (eq (type (read val_txt)) 'INT)
              (setq val_txt (convert_str2mil val_txt T))
              (setq
                nb_dec (1- (- (strlen val_txt) (vl-string-position 46 val_txt)))
                val_txt
                (strcat
                  (if (eq (substr val_txt 1 1) "+") "+" "")
                  (convert_str2mil (rtos (fix (atof val_txt)) 2 0) T)
                  "."
                  (convert_str2mil (substr (rtos (abs (- (atof val_txt) (fix (atof val_txt)))) 2 nb_dec) 3) nil)
                )
              )
            )
            (entmod (subst (cons 1 val_txt) (assoc 1 dxf_ent) dxf_ent))
          )
        )
      )
    )
  )
  (prin1)
)

I also give you the usable version of @john.uhden  which works fine too but it ignores the "+" sign if forced and only converts the mantissa of the number not the decimal part.

;;----------------------------------------------------
;; This function pads a numeric string with commas.
;; Revised to handle negative values (03-14-02)
;;
;; Re-written (11-20-04)
(defun @rtoc (N Prec / Sign Str i j)
  (setq Prec (max 0 Prec)
        Sign (if (minusp N) "-" "")
        Str  (rtos (abs N) 2 Prec)
        i    (vl-string-search "." Str)
  )
  (if (not i)(setq i (strlen Str)))
  (setq j i)
  (if (zerop (setq i (rem i 3)))(setq i 3))
  (while (< i j)
     (setq Str (strcat (substr Str 1 i) "," (substr Str (1+ i)))
          i (+ i 4)
          j (1+ j)
     )
  )
  (strcat Sign Str)
)
(defun c:TEXT-CONV ( / ss n ent dxf_ent val_txt nb_dec)
  (setq ss
    (ssget
      (list
        (cons 0 "TEXT")
        (cons 67 (if (eq (getvar "CVPORT") 2) 0 1))
        (cons 410 (if (eq (getvar "CVPORT") 2) "Model" (getvar "CTAB")))
      )
    )
  )
  (cond
    (ss
      (repeat (setq n (sslength ss))
        (setq
          ent (ssname ss (setq n (1- n)))
          dxf_ent (entget ent)
          val_txt (cdr (assoc 1 dxf_ent))
        )
        (cond
          ((numberp (read val_txt))
            (if (eq (type (read val_txt)) 'INT)
              (setq nb_dec 0)
              (setq nb_dec (1- (- (strlen val_txt) (vl-string-position 46 val_txt))))
            )
            (entmod (subst (cons 1 (@rtoc (read val_txt) nb_dec)) (assoc 1 dxf_ent) dxf_ent))
          )
        )
      )
    )
  )
  (prin1)
)
Message 15 of 17

john.uhden
Mentor
Mentor

@ramimann ,

@rtoc is a function just like rtos or itoa or setq, and it usually requires input arguments.  It is intended to be used inside or referenced by a parent function, as @CADaSchtroumpf did.

Whereas a C:function is a command function which can be invoked from the command line just by typing it in.  But a command function hardly ever requires input arguments, but instead accepts input for each parameter it prompts you to enter.

John F. Uhden

Message 16 of 17

john.uhden
Mentor
Mentor

@CADaSchtroumpf ,

That was very kind of you.

I never knew that anyone puts commas after the decimal point.

John F. Uhden

0 Likes
Message 17 of 17

CADaSchtroumpf
Advisor
Advisor

@john.uhden 

I agree with you John.
Between Europe (Latin) and the Anglo-Saxon notation we do not have the same uses.
For you it's more like: 1,234,456.78987654 (as an excel spreadsheet can do)
Here we prefer: 1 234 456.789 876 54 but it is still a personal choice.

A text in French explaining this:





According to the 9th General Conference (1948, Resolution 7) and the 22nd General Conference (2003, Resolution 10), numbers with a large number of digits may be split into three-digit ranges, separated by a space, in order to facilitate reading. These slices are never separated by dots or commas. However, when there are only four digits before or after the decimal separator, it is customary not to isolate a digit with a space.

Or this Quebec page

So my code intended for our use and which I have adapted (use of commas and dots) is not suitable for your uses.

0 Likes