Request to Upgrade a lisp action

Request to Upgrade a lisp action

smallƑish
Advocate Advocate
856 Views
13 Replies
Message 1 of 14

Request to Upgrade a lisp action

smallƑish
Advocate
Advocate

Please help to upgrade this.

 

(defun c:CFM (/ DuctW DuctH DuctA a2f CFM)
  (setq Height (getreal "\nEnter Duct Width: "))
  (setq Width (getreal "\nEnter Duct Height: "))
  (setq DuctA (* Width Height))
  (setq a2f (/ DuctA 100000)) ; Convert square mm to square feet with exta value
  (setq CFM_VALUE (* a2f 600))
  (princ (strcat "\nCFM (Cubic Feet per Minute): " (rtos CFM_VALUE 2 2)))
)


Instead of typing the Width and Height. Can Lisp extract the Digits from a text object, and substitute
Example;
EAD1000X700
FAD 500 X 300
SA200X400
As its finding area doesn't matter if width and Height are interchanged.

 

smallish_0-1694607861963.png

 

0 Likes
Accepted solutions (2)
857 Views
13 Replies
Replies (13)
Message 2 of 14

Kent1Cooper
Consultant
Consultant

Does the part before the first number always and only end with a capital D [with or without a space]?

Kent Cooper, AIA
0 Likes
Message 3 of 14

smallƑish
Advocate
Advocate

Not always,

1. There could be a space in some situations

2. Sometimes there won't be any first alphabets

3. Can guarantee the X value always seperate the width and height. ( Still Capital or small letter ) also with or without a space between the X.

0 Likes
Message 4 of 14

Kent1Cooper
Consultant
Consultant
Accepted solution

Some of the pieces you can use:

Force the X to be capitalized:

Command: (setq txt (strcase "FAD 2100 x 450")); an example string
"FAD 2100 X 450"

Take off all characters before the first numerical one:

Command: (while (not (wcmatch txt "#*")) (setq txt (substr txt 2)))
"2100 X 450"

Get the numerical part before the X, omitting any spaces:

Command: (setq beforeX (vl-string-trim " " (substr txt 1 (vl-string-position 88 txt))))
"2100"

And likewise after:

Command: (setq afterX (vl-string-trim " " (substr txt (+ 2 (vl-string-position 88 txt)))))
"450"

Kent Cooper, AIA
Message 5 of 14

smallƑish
Advocate
Advocate

Wow that's Amazing.

Thank you so much!!!!!!! 

0 Likes
Message 6 of 14

smallƑish
Advocate
Advocate

In this case how can we eliminate 750 and choose 2100 only as setq beforeX ?

750 CFM FAD 2100 X 450

0 Likes
Message 7 of 14

Kent1Cooper
Consultant
Consultant

So the earlier examples were not really representative of the possibilities....

 

The (vl-string-position) function has the option to look from the end of the string, so this:

(vl-string-position 88 txt 1 T)

will return the position of the "X" regardless of what comes before, which will give you a place to get the afterX part.  Lop that much off and save the rest to a new variable, then do (vl-string-trim) as in my earlier suggestion to eliminate the space [if any], and then do a (while) function testing with (wcmatch) whether the last character is numerical.  As long as it is, take it off with (substr).  When it isn't [whether a space or a letter], you'll know where the number you want begins, and can get it with (substr).

 

Are you capable of putting that together?

 

Kent Cooper, AIA
Message 8 of 14

smallƑish
Advocate
Advocate

Yes, that was my mistake I missed the point in earlier examples.

I'm not that capable. Looks very complicated 

here the existing lisp;

 

 

(defun c:CFM (/)  
  (setq raw (car (entsel "\nSelect the Duct Size: ")))
  (setq txt (strcase (cdr (assoc 1 (entget raw)))))
  (while (not (wcmatch txt "#*")) (setq txt (substr txt 2)))  
  (if (wcmatch txt "*X*")
    (progn
      (setq BEFOREX (atof (substr txt 1 (vl-string-position 88 txt))))  
      (setq AFTERX (atof (substr txt (+ 2 (vl-string-position 88 txt)))))      
(setq ROUND_AREA (* 1.3 (expt (* BEFOREX AFTERX) 0.625) (expt (+ BEFOREX AFTERX) -0.25)))
      (setq LPS (* 3 1000 (* pi (expt (/ ROUND_AREA 1000.0 2) 2))))
            (setq CFM (* LPS 2.11888))
      
      ;; Display the CFM value
      (prompt (strcat "\nMax L/S: " (rtos LPS 2 2)))
           (prompt (strcat "\nMax CFM: " (rtos CFM 2 2)))
    )
    (prompt "\nInvalid text format. Please select text containing dimensions in the format 'X' (e.g., '10 X 12').")
  )  
  (princ)
)

 

0 Likes
Message 9 of 14

Kent1Cooper
Consultant
Consultant
Accepted solution

Try this [minimally tested] for the extraction-of-the-numbers part:

 

....
  (if (wcmatch txt "*X*")
    (progn
      (setq
        AFTERX (atof (substr txt (+ 2 (setq Xpos (vl-string-position 88 txt 1 T)))))
        beforeXtxt (vl-string-trim " " (substr txt 1 Xpos))
        temptxt beforeXtxt
      )
      (while (wcmatch temptxt "*#"); ends in numerical character
        (setq temptxt (substr temptxt 1 (1- (strlen temptxt))))
      )
      (setq BEFOREX (atof (substr beforeXtxt (1+ (strlen temptxt)))))
    ); progn
    .... [ processing ] ....
    (prompt "\nInvalid....
  ); if
....

 

It is subject to the possibility that text of inappropriate content but that happens to contain an x somewhere, or some object type that has no text content, will be selected.  Checks or filtering for such things can be incorporated.

Kent Cooper, AIA
0 Likes
Message 10 of 14

smallƑish
Advocate
Advocate

Thank you so much!

0 Likes
Message 11 of 14

smallƑish
Advocate
Advocate
I have an issue,
It's not working with Mleader and Qleader Data.
How can we fix it?
0 Likes
Message 12 of 14

Kent1Cooper
Consultant
Consultant

@smallƑish wrote:
I have an issue,  It's not working with Mleader and Qleader Data.  How can we fix it?

For some reason, the text content of a MultiLeader is in the code-304 entry rather than the code-1 entry used for Text and Mtext and Dimension override text.  But for a Qleader, there's no such object -- the Leader part is a Leader, and the text part is simply Mtext, so the same code-1 entry has its content.

 

So line 3 in the code in Message 8 should get the text content from the Mtext made along with Leader or Qleader.   What does "not working" mean for a Qleader?  Are you picking on the Leader part, not the Mtext part?  [You can pick a MultiLeader that way, but not the Mtext made with Leader or Qleader.]  Does the Mtext have internal formatting to complicate things?  [That could be an issue with a MultiLeader, too.]

 

You can change the 1 to 304 to get it from a MultiLeader.

 

You can easily make a separate command for use with MultiLeaders with that change.  If you want a universal command for any kind of text element, you could use the "TextString" VLA property, which is applicable to Text & Mtext & MultiLeaders.  Try replacing that line 3 with:

  (setq txt (strcase (vla-get-TextString (vlax-ename->vla-object raw))))

That does not apply to Dimension text override -- that's a different property name, so if you need that, there would need to be a test for entity type to determine what property to extract.

Kent Cooper, AIA
0 Likes
Message 13 of 14

smallƑish
Advocate
Advocate

Thank you, It works for me.

 

As part of testing, I have tried it on an attribute block. But it does not work, Is there any solution for that, just for general information, not a requirement for this process.

0 Likes
Message 14 of 14

Kent1Cooper
Consultant
Consultant

@smallƑish wrote:

....

As part of testing, I have tried it on an attribute block. But it does not work, Is there any solution for that, just for general information, not a requirement for this process.


That would be possible, but it would require an entity-type test on the original selection, and if it's a Block reference, something like (nentselp) applied at the selection point to get to the Attribute rather than the containing Block.  But once there, the text value is in the same code-1 entry as for Text/Mtext/Dimension overrides.

Kent Cooper, AIA
0 Likes