Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Block Calculation

k005
Advisor

Block Calculation

k005
Advisor
Advisor

Hello to everyone

How can I multiply the texts in this format > SZ01 (30/60) within the selected blocks?

I want to calculate the volume by multiplying and adding the parenthesized expressions in the block and multiplying by 15.

 

Details are in the sample file.

I am attaching the sample file.

0 Likes
Reply
Accepted solutions (1)
853 Views
8 Replies
Replies (8)

3wood
Advisor
Advisor

For your blocks, you can try following steps:

1. EXPLODE blocks

2. JOIN lines as polyline

3. BHATCH all polyline 

4. LIST the last object to get the total area.

AREA.gif

k005
Advisor
Advisor

Hi @3wood ,

 

Thank you for the answer. I already have the solution you described...

 

I want to go to the solution by using a parameter like */* without exploding.

 

So we're not going to explode.

0 Likes

_gile
Mentor
Mentor

Hi,

Given all the help you have received regarding retrieving numbers in strings with regular expressions (Regex), you should be able to solve this problem by yourself.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes

k005
Advisor
Advisor

@_gile 

 

Yes. I solved only text object case with regex. This will be a second addition... so calculating for Block...

0 Likes

3wood
Advisor
Advisor
Accepted solution

Please try the lisp below:

TAFT.gif

;;; TAFT.lsp by 3wood
;;; Calculate total area from text in select blocks. Texts need in a format of "SZ01 (30/60)".
;;; https://forums.autodesk.com/t5/net/block-calculation/m-p/10798183#M71113

(defun C:TAFT (/ b1 i1 p1 p2 p3 p4
	       RESULT s1 t1 )
  (setq s1 (ssget '((0 . "INSERT")))
	RESULT 0.0)
  (repeat (setq i1 (sslength s1))
    (setq i1 (1- i1))
    (vlax-for b1 (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (vla-get-name (vlax-ename->vla-object (ssname s1 i1))))
      (if (and (equal (vla-get-ObjectName b1) "AcDbText")
	       (setq t1 (vla-get-textstring b1)
		     p1 (vl-string-search "(" t1)
		     p2 (vl-string-search "/" t1)
		     p3 (vl-string-search ")" t1))
	       )
	(setq RESULT (+ RESULT  (* (* (atof (substr t1 (+ p1 2) (- p2 p1 1))) (atof (substr t1 (+ p2 2) (- p3 p2 1)))) 0.0001)))
	)
      )
    )
  (setq P4 (getpoint "\nPick up point:"))
  (vl-cmdf "text" P4 "0.39" "0.0" (strcat "Hacim : "(rtos RESULT 2 2)" m\U+00B2 x 15 = " (rtos (* RESULT 15.0) 2 2) " m\U+00B3"))
  )

 

 

_gile
Mentor
Mentor

Here is an F# code that works.
I think it's self-explanatory enough that you should know how to convert it to C#.

module TestFsharp.Commands

open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Runtime

type AcCoreApp = Autodesk.AutoCAD.ApplicationServices.Core.Application
type AcExn = Autodesk.AutoCAD.Runtime.Exception

// =================================== HELPERS ==================================== //

module Active =
    let doc = AcCoreApp.DocumentManager.MdiActiveDocument
    let db = doc.Database
    let ed = doc.Editor

let getTopTransaction (db: Database) =
    match db.TransactionManager.TopTransaction with
    | null -> raise (AcExn(ErrorStatus.NoActiveTransactions))
    | tr -> tr

let getObject<'T when 'T 😆 DBObject> mode (id: ObjectId) =
    let tr = getTopTransaction id.Database
    tr.GetObject(id, mode) :?> 'T

let getObjects<'T when 'T 😆 DBObject> mode (ids: System.Collections.IEnumerable) =
    let rx = RXObject.GetClass typeof<'T>
    ids
    |> Seq.cast<ObjectId>
    |> Seq.choose (fun id ->
        if id.ObjectClass.IsDerivedFrom rx then Some(getObject<'T> mode id) else None)

// ===================================== MAIN ====================================== //

open System.Text.RegularExpressions

let rgx = Regex(@"^SZ\d+ \((\d+)/(\d+)\)$")

let getArea (btr: BlockTableRecord) =
    btr
    |> getObjects<DBText> OpenMode.ForRead
    |> Seq.map (fun t -> t.TextString)
    |> Seq.pick (fun s ->
        let groups = rgx.Match(s).Groups
        if groups.Count = 3 then 
            Some ((groups.[1].Value |> float) * (groups.[2].Value |> float) * 0.0001) 
        else 
            None)

[<CommandMethod("TEST")>]
let test() = 
    let ss = 
        Active.ed.GetSelection(SelectionFilter([| 
            TypedValue(0, "INSERT")
            TypedValue(2, "IDE723Entity*") |]))
    if ss.Status = PromptStatus.OK then
        use tr = Active.db.TransactionManager.StartTransaction()
        let area =
            ss.Value.GetObjectIds()
            |> getObjects<BlockReference> OpenMode.ForRead
            |> Seq.map (fun br -> 
                br.BlockTableRecord |> getObject<BlockTableRecord> OpenMode.ForRead)
            |> Seq.sumBy getArea
        let ppr = Active.ed.GetPoint("\nInsertion point: ")
        if ppr.Status = PromptStatus.OK then   
            let text = new DBText()
            text.Position <- ppr.Value.TransformBy(Active.ed.CurrentUserCoordinateSystem)
            text.TextString <- sprintf "Hacim = %.2f m² x 15 = %.2f m\U+00B3" area (area * 15.)
            text.Height <- 0.4
            let cSpace = getObject<BlockTableRecord> OpenMode.ForWrite Active.db.CurrentSpaceId
            cSpace.AppendEntity(text) |> ignore
            tr.AddNewlyCreatedDBObject(text, true)
            tr.Commit()

 

 

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

k005
Advisor
Advisor

@3wood 

 

Thank you very much, very nice work. good luck to you.

0 Likes

k005
Advisor
Advisor

@_gile 

 

Since you gave F#. Can I get information about the difference and usage of this from C# code?


I think I can translate this example to C#... Thank you.

 

If I translate, I will give solution approval.

 

************************************************************************************************************

 

 

More confused.. 😞 What is F#?

 

1- I understood the active part of the module.
2- I understood the regex part.
3- I understood a little bit in Command TEST.

 

but that's all...


*I also forgot to write. We will take the values into the listbox in their current form.

 

 

0 Likes