Jump to content

Code for mathematical calculations of two numbers


Recommended Posts

Posted

Help me fix the errors.
The division operation is not highlighted
When selecting MTEXT, the code returns an error: invalid argument type: stringp nil.

 

;************************
(defun getNumericValue (ent / edata val str1 str3)
  (setq edata (entget ent))
  (cond
    ;; TEXT
    ((equal (cdr (assoc 0 edata)) "TEXT")
     (setq val (cdr (assoc 1 edata))))  
    ;; MTEXT
    ((equal (cdr (assoc 0 edata)) "MTEXT")

     (setq str1 (cdr (assoc 1 edata)))
     (setq str3 (cdr (assoc 3 edata)))  
     (setq val (strcat str1 str3))      
    )
    (T
     (setq val "0") 
    )
  )
  (atof val)
)

;*****************
(defun c:CalcTwoTxt ( / lastOp prompt op ent1 ent2 v1 v2 result inspt validOps)
  (setq validOps '("*" "+" "-" "/")) 

  (setq lastOp (getenv "CALC_TXT_LAST_OP"))

  (setq prompt (strcat "\nSelect an operation [*/+/-//] <" (if lastOp lastOp "") ">: "))

  (setq op (getstring "\nSelect an operation [*/+/-//]: "))

  (if (= op "") (setq op lastOp))

  (if (not (member op validOps))
    (progn
(alert "An invalid operation. The operation is used \"+\".")
           (setq op "+")
    )
  )

  (setenv "CALC_TXT_LAST_OP" op)

  (setq ent1 (car (entsel "\nSelect the first text or MTEXT: ")))
  (if (null ent1) (exit)) 

  (setq ent2 (car (entsel "\nSelect the second text or MTEXT: ")))
  (if (null ent2) (exit)) 


  (setq v1 (getNumericValue ent1))
  (setq v2 (getNumericValue ent2))

  (cond
    ((= op "*") (setq result (* v1 v2)))
    ((= op "+") (setq result (+ v1 v2)))
    ((= op "-") (setq result (- v1 v2)))
    ((= op "/")
      (if (zerop v2)
        (setq result 0.0)
        (setq result (/ v1 v2))
      )
    )
    (T (setq result 0.0)) 
  )

  (setq inspt (getpoint "\nSpecify the insertion point of the result: "))
  (if (null inspt) (exit))

  (command "_.TEXT" inspt "2.5" "0" (rtos result 2 2) "")
  (princ)
)


 

Posted

Hi Nikon

Probably: '(cdr (assoc 3 edata))' is nil

Posted

Since it's not a text string and you want to concatenate it with '(cdr (assoc 1 edata))', it gets 'indigestible' and 'erupts': stringp nil'

😄

  • Thanks 1
Posted
  On 3/21/2025 at 12:19 PM, GLAVCVS said:

Since it's not a text string and you want to concatenate it with '(cdr (assoc 1 edata))', it gets 'indigestible' and 'erupts': stringp nil'

Expand  

And how to write it correctly in the code?

Posted

Whereever in the code occurs v1 or v2, change them to (atof v1) and (atof v2)...

  • Like 1
  • Thanks 1
Posted

I see Marko probably already knows the problem and the solution.

But if not, what do you hope to achieve with '(cdr (assoc 3 edata))'?

Posted
  On 3/21/2025 at 12:30 PM, GLAVCVS said:

But if not, what do you hope to achieve with '(cdr (assoc 3 edata))'?

Expand  

Most of the texts are stored in code group 1,
     but if they are longer than 250 characters, the additional text goes to code group 3.
     (setq str1 (cdr (assoc 1 edata)))
     (setq str3 (cdr (assoc 3 edata)))  ; it can be nil if there are no additional lines. 

But I'm not sure if this is correct.

Posted

I think the quickest way to clarify this is to attach a drawing.

Posted (edited)
  On 3/21/2025 at 12:23 PM, marko_ribar said:

Whereever in the code occurs v1 or v2, change them to (

atof v1) and (atof v2)...

Expand  

error: syntax error

;************************
(defun getNumericValue (ent / edata val str1 str3)
 (setq edata (entget ent))
 (cond
 ;; TEXT
 ((equal (cdr (assoc 0 edata)) "TEXT")
 (setq val (cdr (assoc 1 edata)))) 
 ;; MTEXT
 ((equal (cdr (assoc 0 edata)) "MTEXT")

 (setq str1 (cdr (assoc 1 edata)))
 (setq str3 (cdr (assoc 3 edata))) 
 (setq val (strcat str1 str3)) 
 )
 (T
 (setq val "0") 
 )
 )
 (atof val)
)

;*****************
(defun c:CalcTwoTxt ( / lastOp prompt op ent1 ent2 atof v1 atof v2 result inspt validOps)
 (setq validOps '("*" "+" "-" "/")) 

 (setq lastOp (getenv "CALC_TXT_LAST_OP"))

 (setq prompt (strcat "\nSelect an operation [*/+/-//] <" (if lastOp lastOp "") ">: "))

 (setq op (getstring "\nSelect an operation [*/+/-//]: "))

 (if (= op "") (setq op lastOp))

 (if (not (member op validOps))
 (progn
(alert "An invalid operation. The operation is used \"+\".")
 (setq op "+")
 )
 )

 (setenv "CALC_TXT_LAST_OP" op)

 (setq ent1 (car (entsel "\nSelect the first text or MTEXT: ")))
 (if (null ent1) (exit)) 

 (setq ent2 (car (entsel "\nSelect the second text or MTEXT: ")))
 (if (null ent2) (exit)) 


 (setq (atof v1) (getNumericValue ent1))
 (setq (atof v2) (getNumericValue ent2))

 (cond
 ((= op "*") (setq result (* (atof v1) (atof v2))))
 ((= op "+") (setq result (+ (atof v1) (atof v2))))
 ((= op "-") (setq result (- (atof v1) (atof v2))))
 ((= op "/")
 (if (zerop (atof v2))
 (setq result 0.0)
 (setq result (/ (atof v1) (atof v2)))
 )
 )
 (T (setq result 0.0)) 
 )

 (setq inspt (getpoint "\nSpecify the insertion point of the result: "))
 (if (null inspt) (exit))

 (command "_.TEXT" inspt "2.5" "0" (rtos result 2 2) "")
 (princ)
)

 

Edited by Nikon
(atof v1) (atof v2)
Posted
  On 3/21/2025 at 12:46 PM, GLAVCVS said:

I think the quickest way to clarify this is to attach a drawing.

Expand  

I have simple operations with numbers, the drawing will not clarify anything.😉

Posted
  On 3/21/2025 at 12:54 PM, Nikon said:

Tengo operaciones sencillas con números, el dibujo no me aclara nada.😉

Expand  

👍🏼

Posted

Nikon, you forgot to add open and closing brackets for v1 and v2... Like I said it should be : (atof v1) and (atof v2)...

  • Like 1
  • Thanks 1
Posted (edited)
  On 3/21/2025 at 3:59 PM, marko_ribar said:

Nikon, you forgot to add open and closing brackets for v1 and v2... Like I said it should be : (atof v1) and (atof v2)...

Expand  

Unfortunately, error: syntax error

Edited by Nikon
Posted

In numerical functions, 

this:

    ;; TEXT
    ((equal (cdr (assoc 0 edata)) "TEXT")
     (setq val (cdr (assoc 1 edata))))  
    ;; MTEXT
    ((equal (cdr (assoc 0 edata)) "MTEXT")

     (setq str1 (cdr (assoc 1 edata)))
     (setq str3 (cdr (assoc 3 edata)))  
     (setq val (strcat str1 str3))      
    )

 

could probably be just

 

    ;; TEXT
    ((equal (cdr (assoc 0 edata)) "*TEXT")
     (setq val (cdr (assoc 1 edata)))
    )

 

reason being in text. assoc 3 comes into things if the text string is over 256 characters long... which is a very very big number.

  • Thanks 1
Posted (edited)

Cold try this as a modification, keeping your method:

 

Putting getNumericValue as a subroutine (I find that better for these forum LISPs, copy and paste 1 routine rather than several), getNumericValue altered. I didn't test for mtexts numbers over 256 characters - it should work if you really really want to.

 

Changed the order in the main routine a bit, calculates and reports the value of the 'v's just after selection - handy to have a confirmation of the selected value just after selection

 

Works in my quick tests

 

 

(defun c:CalcTwoTxt ( / lastOp prompt op ent1 ent2 v1 v2 result inspt validOps)
  (defun getNumericValue (ent / edata val str1 str3)
    (setq edata (entget ent))
    (setq val 0)
    (if (or (equal (cdr (assoc 0 edata)) "TEXT")(equal (cdr (assoc 0 edata)) "MTEXT"))
      (progn
        (setq val (cdr (assoc 1 edata)))
        (if (assoc 3 edata) (setq val (strcat str1 str3)))
      ) ; end progn
    )
    (princ val)
    (atof val)
  )

  (setq validOps '("*" "+" "-" "/")) 
  (setq lastOp (getenv "CALC_TXT_LAST_OP"))
  (setq prompt (strcat "\nSelect an operation [*/+/-/\/] <" (if lastOp lastOp "") ">: "))
  (setq op (getstring "\nSelect an operation [*/+/-/]: "))
  (if (= op "") (setq op lastOp))
  (if (not (member op validOps))
    (progn
      (alert "An invalid operation. The operation is used \"+\".")
      (setq op "+")
    )
  )

  (setenv "CALC_TXT_LAST_OP" op)
  (setq ent1 (car (entsel "\nSelect the first text or MTEXT: ")))
  (if (null ent1) (exit)) 
  (setq v1 (getNumericValue ent1))

  (setq ent2 (car (entsel "\nSelect the second text or MTEXT: ")))
  (if (null ent2) (exit)) 
  (setq v2 (getNumericValue ent2))

  (cond
    ((= op "*") (setq result (* v1 v2)))
    ((= op "+") (setq result (+ v1 v2)))
    ((= op "-") (setq result (- v1 v2)))
    ((= op "/")
      (if (zerop v2)
        (setq result 0.0)
        (setq result (/ v1 v2))
      )
    )
    (T (setq result 0.0)) 
  )

  (setq inspt (getpoint "\nSpecify the insertion point of the result: "))
  (if (null inspt) (exit))

  (command "_.TEXT" inspt "2.5" "0" (rtos result 2 2) "")
  (princ)
)

 

Edited by Steven P
  • Thanks 1
Posted (edited)

My way, if can be a pleasure...

(defun ExtractNumber (str / l rslt)
  (setq
    l
    (mapcar
      '(lambda (x)
        (if (and (> x 44) (< x 58) (/= x 47)) x 32)
      )
      (vl-string->list str)
    )
    l
    (mapcar
      '(lambda (x y)
        (if (not (= x y 32)) x)
      )
      l
      (append (cdr l) '(32))
    )
    l (vl-remove-if-not '(lambda (x) (eq (type x) 'INT) x) l)
    l (mapcar '(lambda (x) (if (not (eq x 32)) x (list nil))) l)
  )
  (eval (read (strcat "(setq rslt (list " (apply 'strcat (mapcar '(lambda (x) (if (not (listp x)) (chr x) " ")) l)) "))")))
)
(defun c:CalcTwoTxt ( / ss1 ss2 val1 val2 op rslt inspt)
  (princ "\nSelect first text")
  (while (not (setq ss1 (ssget "_+.:E:S" '((0 . "*TEXT"))))))
  (princ "\nSelect second text")
  (while (not (setq ss2 (ssget "_+.:E:S" '((0 . "*TEXT"))))))
  (setq val1 (extractnumber (cdr (assoc 1 (entget (ssname ss1 0))))))
  (setq val2 (extractnumber (cdr (assoc 1 (entget (ssname ss2 0))))))
  (cond
    ((and val1 val2)
      (initget "* + - /")
      (setq op (getkword "\nSelect an operation [*/+/-/\/]? <+>: "))
      (if (not op) (setq op "+"))
      (if (and (eq op "/") (member 0 val2))
        (setq rslt 0.0)
        (setq rslt (apply (read op) (append val1 val2)))
      )
      (initget 1)
      (setq inspt (getpoint "\nSpecify the insertion point of the result: "))
      (command "_.TEXT" inspt "2.5" "0" (rtos rslt 2 2))
    )
    (T (princ "\No value found in text"))
  )
  (prin1)
)

NB:The extractnumber function recovers all the digital values contained in a text in the form of a list

exemple:
(extractnumber "area floor = 45.60m², length 12.56m heigth = 2.12m") -> (45.6 12.56 2.12)

Edited by Tsuky
  • Like 1
Posted (edited)
  On 3/22/2025 at 12:20 AM, Tsuky said:

My way, if can be a pleasure...

Expand  

@Tsuky HUGE thank. The division operation is  active, but there is one drawback.
Dividing a smaller number by a larger one gives 0.
For example, 5/10=0 or 5/550=0... decimal division works fine 05./50.5=0.9.

???

Is it possible to remember the last choice of operation?

Edited by Nikon
Posted
  On 3/21/2025 at 10:15 PM, Steven P said:

Cold try this as a modification, keeping your method:

 

Putting getNumericValue as a subroutine (I find that better for these forum LISPs, copy and paste 1 routine rather than several), getNumericValue altered. I didn't test for mtexts numbers over 256 characters - it should work if you really really want to.

 

Changed the order in the main routine a bit, calculates and reports the value of the 'v's just after selection - handy to have a confirmation of the selected value just after selection

 

Works in my quick tests

Expand  

For some reason, the code gives an error...

; error: incorrectly generated list at the entrance

Posted

think I left in something I was trying - edited now

  • Thanks 1
Posted
  On 3/22/2025 at 9:39 PM, Steven P said:

think I left in something I was trying - edited now

Expand  

Unfortunately, I can't check the code,  the same error.

; error: incorrectly generated list at the entrance

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...